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 /// Returns the unique [`crate::boundary::Condition`] with the
3170 /// given [`ConditionKind`] in `preconditions ∪ postconditions`,
3171 /// or [`None`] if zero or `≥ 2` such conditions exist — the
3172 /// union arm of the (precondition, postcondition, condition-
3173 /// union) `Option<&Condition>`-witnessing peer of the Boolean
3174 /// [`Self::has_unique_of_condition_kind`] on the per-kind
3175 /// cardinality "= 1" mid-endpoint at the ephemeral surface.
3176 /// Composed body: a two-step short-circuit walk over the chained
3177 /// per-kind iterator [`Self::iter_condition_kind`]. Byte-for-
3178 /// byte peer of [`crate::boundary::Boundary::unique_of_condition_kind`]
3179 /// on the point-domain surface — both compose against the SAME
3180 /// slice-level substrate primitive
3181 /// [`crate::boundary::ConditionSliceExt::unique_of_kind`] via
3182 /// the two-slice chain.
3183 #[must_use]
3184 pub fn unique_of_condition_kind(
3185 &self,
3186 kind: ConditionKind,
3187 ) -> Option<&crate::boundary::Condition> {
3188 let mut it = self.iter_condition_kind(kind);
3189 let first = it.next()?;
3190 match it.next() {
3191 None => Some(first),
3192 Some(_) => None,
3193 }
3194 }
3195
3196 /// Returns the unique [`crate::boundary::Condition`] with the
3197 /// given [`ConditionKind`] in [`Self::preconditions`], or
3198 /// [`None`] — the precondition-side arm of the (precondition,
3199 /// postcondition, condition-union) `Option<&Condition>`-
3200 /// witnessing peer triad on [`EphemeralSpec`]. Thin typed
3201 /// delegate to [`crate::boundary::ConditionSliceExt::unique_of_kind`]
3202 /// over [`Self::preconditions`]. Peer of
3203 /// [`crate::boundary::Boundary::unique_of_precondition_kind`] on
3204 /// the point-domain surface — both compose against the SAME
3205 /// slice-level substrate primitive.
3206 #[must_use]
3207 pub fn unique_of_precondition_kind(
3208 &self,
3209 kind: ConditionKind,
3210 ) -> Option<&crate::boundary::Condition> {
3211 self.preconditions.unique_of_kind(kind)
3212 }
3213
3214 /// Returns the unique [`crate::boundary::Condition`] with the
3215 /// given [`ConditionKind`] in [`Self::postconditions`], or
3216 /// [`None`] — the postcondition-side arm of the (precondition,
3217 /// postcondition, condition-union) `Option<&Condition>`-
3218 /// witnessing peer triad on [`EphemeralSpec`]. Thin typed
3219 /// delegate to [`crate::boundary::ConditionSliceExt::unique_of_kind`]
3220 /// over [`Self::postconditions`]. Peer of
3221 /// [`crate::boundary::Boundary::unique_of_postcondition_kind`]
3222 /// on the point-domain surface. See
3223 /// [`Self::unique_of_precondition_kind`] for the full rationale —
3224 /// the two methods share ONE lift motivation, ONE fail-before-
3225 /// pass-after composition-law pin, and ONE two-surface parity
3226 /// contract with the point-domain
3227 /// [`crate::boundary::Boundary`] per-kind witness peer methods.
3228 #[must_use]
3229 pub fn unique_of_postcondition_kind(
3230 &self,
3231 kind: ConditionKind,
3232 ) -> Option<&crate::boundary::Condition> {
3233 self.postconditions.unique_of_kind(kind)
3234 }
3235
3236 /// True iff this ephemeral spec's stored [`TeardownPolicy`] equals
3237 /// `kind` — the substrate primitive that owns the
3238 /// (`&EphemeralSpec`, [`TeardownPolicy`]) → `bool` presence-probe
3239 /// shape on the sugar-surface type.
3240 ///
3241 /// # Peer to [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
3242 ///
3243 /// [`EphemeralLifetime::has_teardown_policy`] carries the same
3244 /// `(&self, TeardownPolicy) -> bool` signature on the point-surface
3245 /// carrier ([`ProcessSpec`]'s nested [`crate::lifetime::Lifetime`]
3246 /// slot reached through
3247 /// [`crate::lifetime::Lifetime::resolved_ephemeral`]); this peer
3248 /// composes byte-identical `==` semantics on
3249 /// [`EphemeralSpec`]'s direct `teardown: TeardownPolicy` scalar
3250 /// slot, so both surfaces' `teardown-policy-<kind>` require-tag
3251 /// families ([`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
3252 /// on the point surface, this peer on the ephemeral surface) route
3253 /// through the SAME scalar `==` shape. A future normalization at
3254 /// the probe shape (a widened return carrying a `TerminatePolicy`
3255 /// disambiguator, a debug-build assertion on operator-set vs
3256 /// defaulted overrides, a fleet-wide warn on `Never` combined with
3257 /// short TTLs) lands at ONE site per surface and every downstream
3258 /// `teardown-policy-<kind>` require-tag family + closed-set audit
3259 /// dispatcher picks it up mechanically.
3260 ///
3261 /// # Semantics — VARIANT match, not POPULATED slot
3262 ///
3263 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
3264 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
3265 /// absent state to detect. `has_teardown_policy(kind)` returns
3266 /// `true` iff `self.teardown == kind`. On a hand-authored
3267 /// [`EphemeralSpec`] that omits `:teardown` from the
3268 /// `(defephemeral …)` form (or a Rust builder that reaches
3269 /// [`TeardownPolicy::default`]) the probe returns `true` for
3270 /// [`TeardownPolicy::Always`] and `false` for every other variant
3271 /// — distinct from the Option-slot axis where a default carrier
3272 /// returns `false` for EVERY kind. An operator who left
3273 /// `:teardown` at the substrate default IS configured for
3274 /// `Always`, and a `:requires (teardown-policy-Always)` check
3275 /// should pass; only an operator who deliberately overrode the
3276 /// policy to `OnAttested` / `OnFailed` / `Never` fails the tag on
3277 /// this axis.
3278 ///
3279 /// # Corner — (required-scalar-child)
3280 ///
3281 /// Fresh corner on the ephemeral surface's presence-probe algebra:
3282 /// [`EphemeralSpec`] has no Option-parent hop between the sugar
3283 /// struct and the `teardown` scalar (the point surface reaches
3284 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
3285 /// through the Option-parent `resolved_ephemeral()` gate), so the
3286 /// probe body is a bare scalar `==` on a required field. Distinct
3287 /// from [`Self::has_condition_kind`] on this same surface, which
3288 /// walks a `Vec<Condition>` slice-child.
3289 ///
3290 /// # Compounding
3291 ///
3292 /// The ephemeral require-tag classifier composes this primitive
3293 /// with the closed-set `FromStr` autoderived on [`TeardownPolicy`]
3294 /// through the `strip_and_classify_prefixed_kind` substrate to
3295 /// publish a `teardown-policy-<kind>` prefix family byte-for-byte
3296 /// symmetrical with the point surface's family via
3297 /// [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]. A
3298 /// future fifth [`TeardownPolicy`] variant added to `ALL` (a
3299 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
3300 /// reaches BOTH surfaces' `teardown-policy-<kind>` prefix families
3301 /// through the SAME closed-set walk with no per-caller edit — the
3302 /// two-surface symmetry means adding a variant on the closed set
3303 /// publishes it in lockstep across every downstream consumer.
3304 ///
3305 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
3306 /// preserves proofs — the scalar-carrier presence-probe body lives
3307 /// at ONE substrate site per surface so every downstream
3308 /// (`teardown-policy-<kind>` require-tag families on both surfaces
3309 /// in tatara-check, closed-set audit dispatchers, future variant
3310 /// additions on [`TeardownPolicy`]) binds through the SAME
3311 /// `has(kind)` shape rather than restating the `<eph>.teardown ==
3312 /// kind` closure body at each call site). THEORY.md §VI.1
3313 /// (generation over composition — a future variant lands at ONE
3314 /// `ALL` entry + one `as_str` arm on the closed set and the probe
3315 /// picks it up mechanically without further per-consumer edits).
3316 #[must_use]
3317 pub fn has_teardown_policy(&self, kind: TeardownPolicy) -> bool {
3318 self.teardown == kind
3319 }
3320
3321 /// Derived-bool-predicate presence probe on the stored
3322 /// [`Self::teardown`] slot — `true` iff this ephemeral sugar's
3323 /// [`TeardownPolicy`] would auto-SIGTERM the Process on the
3324 /// queried [`ProcessPhase`] transition (as read through
3325 /// [`TeardownPolicy::should_teardown_on`]).
3326 ///
3327 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
3328 ///
3329 /// Same shape, same axis, one refinement lower: the point-surface
3330 /// peer on [`crate::lifetime::EphemeralLifetime`] composes the SAME
3331 /// [`TeardownPolicy::should_teardown_on`] predicate against the
3332 /// SAME stored `teardown_policy` slot; this method composes the
3333 /// same predicate against the sugar surface's flattened
3334 /// [`Self::teardown`] slot. Both bodies delegate to the ONE
3335 /// substrate owner [`TeardownPolicy::should_teardown_on`], so a
3336 /// regression at the (policy, phase) → bool truth table surfaces
3337 /// at THAT primitive's tests rather than as silent drift at
3338 /// either struct-level caller.
3339 ///
3340 /// # Corner — (required-scalar-parent × derived-bool-predicate-child)
3341 ///
3342 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
3343 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
3344 /// Option-parent hop between the sugar struct and the `teardown`
3345 /// scalar (the point surface reaches
3346 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
3347 /// through the Option-parent `resolved_ephemeral()` gate). The
3348 /// probe body is a bare predicate application on a required
3349 /// field. Distinct from [`Self::has_teardown_policy`] on this
3350 /// same surface, which reads the raw stored variant for equality
3351 /// (`self.teardown == kind`) rather than the derived firing-arm
3352 /// predicate against a [`ProcessPhase`] argument.
3353 ///
3354 /// # Compounding
3355 ///
3356 /// The ephemeral require-tag classifier composes this primitive
3357 /// with the closed-set [`crate::phase::ProcessPhase`]'s
3358 /// autoderived `FromStr` through the
3359 /// `strip_and_classify_prefixed_kind` substrate to publish a
3360 /// `teardown-fires-on-<phase>` prefix family byte-for-byte
3361 /// symmetrical with the point surface's family via
3362 /// [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`].
3363 /// A future fifth [`TeardownPolicy`] variant added to `ALL` (a
3364 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
3365 /// reaches BOTH surfaces' `teardown-fires-on-<phase>` prefix
3366 /// families through the SAME
3367 /// [`TeardownPolicy::should_teardown_on`] match with no per-
3368 /// caller edit — the two-surface symmetry means adding a variant
3369 /// on the closed set publishes it in lockstep across every
3370 /// downstream consumer.
3371 ///
3372 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
3373 /// preserves proofs — the derived-bool-predicate presence-probe
3374 /// body lives at ONE substrate site per surface, both composing
3375 /// the SAME [`TeardownPolicy::should_teardown_on`] projection, so
3376 /// every downstream (`teardown-fires-on-<phase>` require-tag
3377 /// families on both surfaces in tatara-check, closed-set audit
3378 /// dispatchers, future variant additions on either
3379 /// [`TeardownPolicy`] or [`crate::phase::ProcessPhase`]) binds
3380 /// through the SAME `has_teardown_firing_on(phase)` shape rather
3381 /// than restating the `<eph>.teardown.should_teardown_on(phase)`
3382 /// closure body at each call site). THEORY.md §VI.1 (generation
3383 /// over composition — a future variant lands at ONE `ALL` entry +
3384 /// one `as_str` arm + one `should_teardown_on` arm on the closed
3385 /// set and the probe picks it up mechanically without further
3386 /// per-consumer edits).
3387 #[must_use]
3388 pub const fn has_teardown_firing_on(&self, phase: ProcessPhase) -> bool {
3389 self.teardown.should_teardown_on(phase)
3390 }
3391
3392 /// Resolve the operator-authored [`Self::classification`] slot to
3393 /// the concrete [`Classification`] the point surface sees, filling
3394 /// `None` through the same [`default_ephemeral_class`] baseline the
3395 /// `From<EphemeralSpec> for ProcessSpec` lowering uses when the
3396 /// operator omits `:classification` from the `(defephemeral …)`
3397 /// form. Returns [`Cow::Borrowed`] on the populated arm (zero
3398 /// allocation), else [`Cow::Owned`] with the workspace-baseline
3399 /// `(Gate, Compute, Bounded, Monotone, Internal)` value the sibling
3400 /// primitive [`Classification::gate_compute`] owns.
3401 ///
3402 /// # ONE substrate primitive for `Option<Classification>` resolution
3403 ///
3404 /// This is the ONE `EphemeralSpec`-inherent primitive that owns the
3405 /// `Option<Classification>` → resolved-[`Classification`] walk.
3406 /// Every downstream classification-axis presence probe on the
3407 /// [`EphemeralSpec`] surface ([`Self::has_point_type`],
3408 /// [`Self::has_substrate`], [`Self::has_calm`],
3409 /// [`Self::has_data_classification`], [`Self::has_horizon_kind`],
3410 /// [`Self::has_optimization_direction`], [`Self::has_input_arity`],
3411 /// [`Self::has_output_arity`]) routes through THIS
3412 /// primitive so the "`None` fills through
3413 /// [`default_ephemeral_class`]" resolution lives at ONE site rather
3414 /// than being restated in each per-axis probe body. A future
3415 /// regression on the fill-through (a shift from the `(Gate,
3416 /// Compute, …)` baseline to a different `default_ephemeral_class`
3417 /// body, a shift from the `Option`-carrier shape to a
3418 /// serde-defaulted required-field carrier, an eventual audit hook
3419 /// naming the resolved-vs-authored provenance) lands at ONE site
3420 /// and every downstream axis-probe on the ephemeral surface picks
3421 /// it up mechanically.
3422 ///
3423 /// # Sibling to the `From<EphemeralSpec>` lowering
3424 ///
3425 /// The lowering `From<EphemeralSpec> for ProcessSpec` fills
3426 /// [`ProcessSpec::classification`] through the SAME
3427 /// `.unwrap_or_else(default_ephemeral_class)` walk that this
3428 /// primitive owns on the borrow-friendly `Cow` return. Both sites
3429 /// resolve the same operator-authored slot through the same default
3430 /// so a future two-surface parity contract on the classification
3431 /// axes (`point-type-<kind>` on both surfaces, `substrate-<kind>`
3432 /// on both surfaces, …) reads identically through the sibling
3433 /// point-surface probe [`Classification::has_<axis>`] on the
3434 /// lowered `ProcessSpec` and through THIS primitive on the same
3435 /// authored [`EphemeralSpec`].
3436 ///
3437 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3438 /// preserves proofs; the `Option<Classification>` resolution body
3439 /// lives at ONE substrate primitive on the ephemeral surface so
3440 /// every downstream classification-axis probe binds through the
3441 /// SAME `resolved_classification()` shape rather than restating
3442 /// the `self.classification.as_ref().unwrap_or(&default_…)`
3443 /// closure body at each callsite. THEORY.md §VI.1 — generation
3444 /// over composition; a future classification-axis peer
3445 /// (`has_substrate`, `has_calm`, …) lands as ONE inherent method
3446 /// that delegates through the resolver's `has_<axis>(kind)` call
3447 /// on the sibling [`Classification`] closed-set primitive with no
3448 /// per-axis restatement of the fill-through logic.
3449 #[must_use]
3450 pub fn resolved_classification(&self) -> Cow<'_, Classification> {
3451 match &self.classification {
3452 Some(c) => Cow::Borrowed(c),
3453 None => Cow::Owned(default_ephemeral_class()),
3454 }
3455 }
3456
3457 /// Overlay a single [`ClassificationAxis`] variant onto this
3458 /// ephemeral spec's authored [`Self::classification`] slot, filling
3459 /// `None` through [`Classification::gate_compute`] before the
3460 /// overlay so the resulting slot carries `Some(_)` regardless of
3461 /// the pre-call state. Fluent chaining primitive: the peer of
3462 /// [`ProcessSpec::gate_compute_with_axis`] (fresh-spec × axis
3463 /// overlay) and [`Classification::with_axis`] (arbitrary-base ×
3464 /// axis overlay) on the ephemeral sugar surface.
3465 ///
3466 /// # Substrate ergonomics
3467 ///
3468 /// Pre-lift the four-line shape `let mut classification =
3469 /// Classification::gate_compute(); classification.<axis> =
3470 /// populated; let spec = EphemeralSpec { classification:
3471 /// Some(classification), ..ephemeral_fixture() };` (and its newer
3472 /// three-line peer `let classification =
3473 /// Classification::gate_compute_with_axis(populated); let spec =
3474 /// EphemeralSpec { classification: Some(classification),
3475 /// ..ephemeral_fixture() };`) recurred at THIRTY-SIX hand-authored
3476 /// callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger
3477 /// inside `tatara-reconciler::bin::tatara-check`'s
3478 /// `evaluate_ephemeral_require_tag_*` classifier-facing test
3479 /// module. Post-lift each callsite reads
3480 /// `let spec = ephemeral_fixture().with_classification_axis(populated);`
3481 /// — one line, one immutable binding, and every per-axis loop
3482 /// dispatches its per-iteration axis mutation through the SAME
3483 /// [`ClassificationAxis::overlay`] trait rather than by directly
3484 /// poking a `classification.<axis>` field or restating the
3485 /// `Some(_)` wrap.
3486 ///
3487 /// # Fluent chaining semantics
3488 ///
3489 /// * `EphemeralSpec { classification: None, .. }
3490 /// .with_classification_axis(axis)` produces
3491 /// `EphemeralSpec { classification:
3492 /// Some(Classification::gate_compute_with_axis(axis)), .. }` —
3493 /// the `None`-arm short-circuit fills through
3494 /// [`Classification::gate_compute`] identically to the sibling
3495 /// [`Self::resolved_classification`] resolver on the read side.
3496 /// * `EphemeralSpec { classification: Some(prior), .. }
3497 /// .with_classification_axis(axis)` produces
3498 /// `EphemeralSpec { classification: Some(prior.with_axis(axis)),
3499 /// .. }` — the axis overlay composes onto the existing carrier
3500 /// via [`ClassificationAxis::overlay`], preserving every other
3501 /// axis slot on `prior`. Chained calls
3502 /// `.with_classification_axis(a).with_classification_axis(b)`
3503 /// compose arbitrary N-axis conjunctions on the ephemeral
3504 /// sugar surface with the same order-independence guarantee
3505 /// [`Classification::with_axis`] carries on distinct-slot axes.
3506 ///
3507 /// # Sibling to [`ProcessSpec::gate_compute_with_axis`]
3508 ///
3509 /// Same (spec-carrier × axis) shape, one refinement lower on
3510 /// the composition-depth axis: `ProcessSpec::gate_compute_with_axis`
3511 /// owns the (fresh-`gate_compute_defaults`-spec × axis-overlay)
3512 /// construction on the point-surface carrier;
3513 /// [`Self::with_classification_axis`] owns the
3514 /// (arbitrary-`EphemeralSpec` × axis-overlay-onto-authored-classification)
3515 /// construction on the ephemeral sugar-surface carrier. Both
3516 /// primitives compose through the SAME
3517 /// [`ClassificationAxis::overlay`] trait so a regression on any
3518 /// axis's overlay surfaces at both composer owners' pin sets
3519 /// simultaneously.
3520 ///
3521 /// # Compounding
3522 ///
3523 /// A future SIXTH classification axis lands as ONE peer
3524 /// `impl ClassificationAxis` — every ephemeral-surface fixture
3525 /// that binds through this primitive picks up the sixth axis
3526 /// mechanically without a `classification.<new-axis> = value;`
3527 /// restatement per site. A future audit dispatcher walking the
3528 /// (ephemeral-surface × axis-loop) shape (per-axis matrix
3529 /// generator, closed-set-sweep sagas, per-axis-XOR-partition-
3530 /// witness synthesis on the ephemeral side) binds through the
3531 /// SAME composer regardless of which axis it targets. Directly
3532 /// benefits the P1 caixa-tatara renderer target
3533 /// (`(defaplicacao …)` → `Process` mechanical lowering test
3534 /// fixtures that construct authored classifications through the
3535 /// ephemeral sugar surface) and future ephemeral-surface XOR-
3536 /// partition landmark tests peer to the point-surface pins in
3537 /// `tatara-check.rs`.
3538 ///
3539 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3540 /// preserves proofs; the [`ClassificationAxis::overlay`] trait
3541 /// owns the axis-dispatch proof at ONE site and this primitive
3542 /// extends the ONE-site guarantee to the (ephemeral-spec ×
3543 /// authored-classification × axis-overlay) construction shape.
3544 /// THEORY.md §VI.1 — generation over composition; the 3-to-4-line
3545 /// hand-authored classification-then-wrap shape recurred at ≥ 36
3546 /// hand-authored callsites past the ★★ PRIME-DIRECTIVE ≥ 2
3547 /// duplication threshold and is lifted onto ONE substrate owner
3548 /// here.
3549 #[must_use]
3550 pub fn with_classification_axis<A: ClassificationAxis>(mut self, axis: A) -> Self {
3551 let mut c = self
3552 .classification
3553 .take()
3554 .unwrap_or_else(Classification::gate_compute);
3555 axis.overlay(&mut c);
3556 self.classification = Some(c);
3557 self
3558 }
3559
3560 /// True iff the resolved [`Classification`] carries the given
3561 /// [`ConvergencePointType`] on its `point_type` slot — byte-for-
3562 /// byte peer of [`Classification::has_point_type`] wrapped through
3563 /// the [`Self::resolved_classification`] resolver so an
3564 /// operator-omitted `:classification` slot reads as the
3565 /// [`default_ephemeral_class`] baseline the sibling
3566 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3567 ///
3568 /// # Two-surface parity contract
3569 ///
3570 /// A given [`EphemeralSpec`] classifies identically through this
3571 /// primitive AND through
3572 /// `<eph.clone().into::<ProcessSpec>>().classification.has_point_type(kind)`
3573 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3574 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3575 /// the lowering side both dereference the same
3576 /// `default_ephemeral_class()` value on `None` and the same
3577 /// authored value on `Some(_)`. This means the ephemeral-surface
3578 /// `point-type-<kind>` `:requires` family in
3579 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3580 /// truth on the SAME authored spec as the point-surface family
3581 /// on the mechanically-lowered `ProcessSpec`.
3582 ///
3583 /// # Sibling to the seven other classification axes
3584 ///
3585 /// FIRST classification-axis peer on the [`EphemeralSpec`]
3586 /// surface. Six future sibling axes on the SAME `Cow`-resolver
3587 /// carrier ([`Self::has_substrate`] opened the SECOND,
3588 /// [`Self::has_calm`] the THIRD,
3589 /// [`Self::has_data_classification`] the FOURTH,
3590 /// [`Self::has_horizon_kind`] the FIFTH,
3591 /// [`Self::has_optimization_direction`] the SIXTH; then
3592 /// `has_input_arity`, `has_output_arity`) land as one-line
3593 /// wrappers around the SAME resolver + the sibling
3594 /// [`Classification`] closed-set primitive, so a future variant
3595 /// added to [`ConvergencePointType`] (or any of the seven other
3596 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3597 /// families through the SAME closed-set walk with no per-caller
3598 /// edit.
3599 ///
3600 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3601 /// preserves proofs; the classification-axis presence-probe body
3602 /// composes ONE resolver primitive
3603 /// ([`Self::resolved_classification`]) with ONE closed-set
3604 /// primitive ([`Classification::has_point_type`]) so every
3605 /// downstream (`point-type-<kind>` require-tag families on both
3606 /// surfaces in tatara-check, closed-set audit dispatchers, future
3607 /// variant additions on [`ConvergencePointType`]) binds through
3608 /// the SAME `has(kind)` shape rather than restating either the
3609 /// resolver walk or the closed-set equality at the callsite.
3610 #[must_use]
3611 pub fn has_point_type(&self, kind: ConvergencePointType) -> bool {
3612 self.resolved_classification().has_point_type(kind)
3613 }
3614
3615 /// True iff the resolved [`Classification`] carries the given
3616 /// [`SubstrateType`] on its `substrate` slot — byte-for-byte peer
3617 /// of [`Classification::has_substrate`] wrapped through the
3618 /// [`Self::resolved_classification`] resolver so an operator-
3619 /// omitted `:classification` slot reads as the
3620 /// [`default_ephemeral_class`] baseline the sibling
3621 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3622 ///
3623 /// # Two-surface parity contract
3624 ///
3625 /// A given [`EphemeralSpec`] classifies identically through this
3626 /// primitive AND through
3627 /// `<eph.clone().into::<ProcessSpec>>().classification.has_substrate(kind)`
3628 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3629 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3630 /// the lowering side both dereference the same
3631 /// `default_ephemeral_class()` value on `None` and the same
3632 /// authored value on `Some(_)`. This means the ephemeral-surface
3633 /// `substrate-<kind>` `:requires` family in
3634 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3635 /// truth on the SAME authored spec as the point-surface family
3636 /// on the mechanically-lowered `ProcessSpec`.
3637 ///
3638 /// # SECOND classification-axis peer on the ephemeral surface
3639 ///
3640 /// Peer of [`Self::has_point_type`] — both route through the SAME
3641 /// [`Self::resolved_classification`] resolver, so the operator-
3642 /// omitted `:classification` slot's fill-through logic lives at
3643 /// ONE substrate primitive rather than being restated in each
3644 /// per-axis probe body. Five future sibling axes on the SAME
3645 /// `Cow`-resolver carrier ([`Self::has_calm`] opened the THIRD,
3646 /// [`Self::has_data_classification`] the FOURTH,
3647 /// [`Self::has_horizon_kind`] the FIFTH,
3648 /// [`Self::has_optimization_direction`] the SIXTH; then
3649 /// `has_input_arity`, `has_output_arity`) land as one-line
3650 /// wrappers around the SAME resolver + the sibling
3651 /// [`Classification`] closed-set primitive, so a future variant
3652 /// added to [`SubstrateType`] (or any of the six other closed
3653 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
3654 /// through the SAME closed-set walk with no per-caller edit.
3655 ///
3656 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3657 /// preserves proofs; the classification-axis presence-probe body
3658 /// composes ONE resolver primitive
3659 /// ([`Self::resolved_classification`]) with ONE closed-set
3660 /// primitive ([`Classification::has_substrate`]) so every
3661 /// downstream (`substrate-<kind>` require-tag families on both
3662 /// surfaces in tatara-check, closed-set audit dispatchers, future
3663 /// variant additions on [`SubstrateType`]) binds through the
3664 /// SAME `has(kind)` shape rather than restating either the
3665 /// resolver walk or the closed-set equality at the callsite.
3666 #[must_use]
3667 pub fn has_substrate(&self, kind: SubstrateType) -> bool {
3668 self.resolved_classification().has_substrate(kind)
3669 }
3670
3671 /// True iff the resolved [`Classification`] carries the given
3672 /// [`CalmClassification`] on its `calm` slot — byte-for-byte peer
3673 /// of [`Classification::has_calm`] wrapped through the
3674 /// [`Self::resolved_classification`] resolver so an operator-
3675 /// omitted `:classification` slot reads as the
3676 /// [`default_ephemeral_class`] baseline the sibling
3677 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3678 ///
3679 /// # Two-surface parity contract
3680 ///
3681 /// A given [`EphemeralSpec`] classifies identically through this
3682 /// primitive AND through
3683 /// `<eph.clone().into::<ProcessSpec>>().classification.has_calm(kind)`
3684 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3685 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3686 /// the lowering side both dereference the same
3687 /// `default_ephemeral_class()` value on `None` and the same
3688 /// authored value on `Some(_)`. This means the ephemeral-surface
3689 /// `calm-<kind>` `:requires` family in
3690 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3691 /// truth on the SAME authored spec as the point-surface family
3692 /// on the mechanically-lowered `ProcessSpec`.
3693 ///
3694 /// # THIRD classification-axis peer on the ephemeral surface
3695 ///
3696 /// Peer of [`Self::has_point_type`] and [`Self::has_substrate`] —
3697 /// all three route through the SAME
3698 /// [`Self::resolved_classification`] resolver, so the operator-
3699 /// omitted `:classification` slot's fill-through logic lives at
3700 /// ONE substrate primitive rather than being restated in each
3701 /// per-axis probe body. FIRST occupant on the (Option-parent ×
3702 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
3703 /// of the ephemeral-surface presence-probe algebra — distinct
3704 /// from the (Option-parent × NON-DEFAULT-scalar-child) corner
3705 /// the first two classification-axis peers opened, since
3706 /// [`CalmClassification`] carries `#[default] = Monotone` on the
3707 /// closed set. The default-arm short-circuit on the absent-
3708 /// classification arm reads `true` on the [`CalmClassification`]
3709 /// child's `#[default]` variant precisely because BOTH the parent
3710 /// Option's fill-through baseline (`default_ephemeral_class`) AND
3711 /// the child's own `#[default]` land on the SAME variant
3712 /// ([`CalmClassification::Monotone`]) — a two-defaults
3713 /// composition property distinct from the NON-DEFAULT-scalar
3714 /// peers, whose absent-classification arm defaults through a
3715 /// specific chosen baseline (`ConvergencePointType::Gate`,
3716 /// `SubstrateType::Compute`) rather than through the child's own
3717 /// `#[default]`. Four future sibling axes on the SAME
3718 /// `Cow`-resolver carrier ([`Self::has_data_classification`]
3719 /// opened the FOURTH, [`Self::has_horizon_kind`] the FIFTH,
3720 /// [`Self::has_optimization_direction`] the SIXTH; then
3721 /// `has_input_arity`, `has_output_arity`) land as one-line
3722 /// wrappers around the SAME resolver + the sibling
3723 /// [`Classification`] closed-set primitive, so a future variant
3724 /// added to [`CalmClassification`] (or any of the five other
3725 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3726 /// families through the SAME closed-set walk with no per-caller
3727 /// edit.
3728 ///
3729 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3730 /// preserves proofs; the classification-axis presence-probe body
3731 /// composes ONE resolver primitive
3732 /// ([`Self::resolved_classification`]) with ONE closed-set
3733 /// primitive ([`Classification::has_calm`]) so every downstream
3734 /// (`calm-<kind>` require-tag families on both surfaces in
3735 /// tatara-check, closed-set audit dispatchers, future variant
3736 /// additions on [`CalmClassification`]) binds through the SAME
3737 /// `has(kind)` shape rather than restating either the resolver
3738 /// walk or the closed-set equality at the callsite.
3739 #[must_use]
3740 pub fn has_calm(&self, kind: CalmClassification) -> bool {
3741 self.resolved_classification().has_calm(kind)
3742 }
3743
3744 /// True iff the resolved [`Classification`] carries the given
3745 /// [`DataClassification`] on its `data_classification` slot —
3746 /// byte-for-byte peer of [`Classification::has_data_classification`]
3747 /// wrapped through the [`Self::resolved_classification`] resolver
3748 /// so an operator-omitted `:classification` slot reads as the
3749 /// [`default_ephemeral_class`] baseline the sibling
3750 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3751 ///
3752 /// # Two-surface parity contract
3753 ///
3754 /// A given [`EphemeralSpec`] classifies identically through this
3755 /// primitive AND through
3756 /// `<eph.clone().into::<ProcessSpec>>().classification.has_data_classification(kind)`
3757 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3758 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3759 /// the lowering side both dereference the same
3760 /// `default_ephemeral_class()` value on `None` and the same
3761 /// authored value on `Some(_)`. This means the ephemeral-surface
3762 /// `data-classification-<kind>` `:requires` family in
3763 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3764 /// truth on the SAME authored spec as the point-surface family
3765 /// on the mechanically-lowered `ProcessSpec`.
3766 ///
3767 /// # FOURTH classification-axis peer on the ephemeral surface
3768 ///
3769 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`], and
3770 /// [`Self::has_calm`] — all four route through the SAME
3771 /// [`Self::resolved_classification`] resolver, so the operator-
3772 /// omitted `:classification` slot's fill-through logic lives at
3773 /// ONE substrate primitive rather than being restated in each
3774 /// per-axis probe body. SECOND occupant on the (Option-parent ×
3775 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
3776 /// of the ephemeral-surface presence-probe algebra alongside
3777 /// [`Self::has_calm`] — both probe REQUIRED [`Classification`]
3778 /// sub-slots whose child closed set carries its own `#[default]`
3779 /// ([`DataClassification::Internal`] here,
3780 /// [`CalmClassification::Monotone`] on the peer), so the
3781 /// default-arm short-circuit on the absent-classification arm
3782 /// reads `true` on the [`DataClassification`] child's
3783 /// `#[default]` variant precisely because BOTH the parent
3784 /// Option's fill-through baseline (`default_ephemeral_class`)
3785 /// AND the child's own `#[default]` land on the SAME variant
3786 /// ([`DataClassification::Internal`]). The two-defaults
3787 /// composition property now walks TWO independent defaulted-
3788 /// scalar-child slots on the SAME ephemeral resolver — a
3789 /// regression that promoted a different [`DataClassification`]
3790 /// variant to `#[default]` (or wired the arm to a fixed variant
3791 /// answer) fails HERE at ONE narrow substrate site before
3792 /// drifting through every unadorned ephemeral spec's baseline
3793 /// data-classification answer. Distinct from the FIRST + SECOND
3794 /// peers on the (Option-parent × NON-DEFAULT-scalar-child)
3795 /// corner, whose absent-classification arm defaults through a
3796 /// specific chosen baseline (`ConvergencePointType::Gate`,
3797 /// `SubstrateType::Compute`) rather than through the child's own
3798 /// `#[default]`. Four future sibling axes on the SAME
3799 /// `Cow`-resolver carrier ([`Self::has_horizon_kind`] opened the
3800 /// FIFTH, [`Self::has_optimization_direction`] the SIXTH; then
3801 /// `has_input_arity`, `has_output_arity`) land as one-line
3802 /// wrappers around the SAME resolver + the sibling
3803 /// [`Classification`] closed-set primitive, so a future variant
3804 /// added to [`DataClassification`] (or any of the four other
3805 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3806 /// families through the SAME closed-set walk with no per-caller
3807 /// edit.
3808 ///
3809 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3810 /// preserves proofs; the classification-axis presence-probe body
3811 /// composes ONE resolver primitive
3812 /// ([`Self::resolved_classification`]) with ONE closed-set
3813 /// primitive ([`Classification::has_data_classification`]) so
3814 /// every downstream (`data-classification-<kind>` require-tag
3815 /// families on both surfaces in tatara-check, closed-set audit
3816 /// dispatchers, future variant additions on
3817 /// [`DataClassification`]) binds through the SAME `has(kind)`
3818 /// shape rather than restating either the resolver walk or the
3819 /// closed-set equality at the callsite.
3820 #[must_use]
3821 pub fn has_data_classification(&self, kind: DataClassification) -> bool {
3822 self.resolved_classification().has_data_classification(kind)
3823 }
3824
3825 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
3826 /// carries the given [`HorizonKind`] discriminator on its
3827 /// `horizon.kind` slot — byte-for-byte peer of
3828 /// [`Classification::has_horizon_kind`] wrapped through the
3829 /// [`Self::resolved_classification`] resolver so an operator-
3830 /// omitted `:classification` slot reads as the
3831 /// [`default_ephemeral_class`] baseline the sibling
3832 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3833 ///
3834 /// # Two-surface parity contract
3835 ///
3836 /// A given [`EphemeralSpec`] classifies identically through this
3837 /// primitive AND through
3838 /// `<eph.clone().into::<ProcessSpec>>().classification.has_horizon_kind(kind)`
3839 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3840 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3841 /// the lowering side both dereference the same
3842 /// `default_ephemeral_class()` value on `None` and the same
3843 /// authored value on `Some(_)`. This means the ephemeral-surface
3844 /// `horizon-<kind>` `:requires` family in
3845 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3846 /// truth on the SAME authored spec as the point-surface family
3847 /// on the mechanically-lowered `ProcessSpec`.
3848 ///
3849 /// # FIFTH classification-axis peer on the ephemeral surface
3850 ///
3851 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3852 /// [`Self::has_calm`], and [`Self::has_data_classification`] — all
3853 /// five route through the SAME [`Self::resolved_classification`]
3854 /// resolver, so the operator-omitted `:classification` slot's
3855 /// fill-through logic lives at ONE substrate primitive rather
3856 /// than being restated in each per-axis probe body. OPENS a fresh
3857 /// (Option-parent × NESTED-STRUCT-scalar-child ×
3858 /// operator-resolvable-baseline) corner on the ephemeral-surface
3859 /// presence-probe algebra — the four prior peers on this surface
3860 /// all read the closed-set discriminator DIRECTLY off a scalar
3861 /// [`Classification`] slot (`point_type`, `substrate`, `calm`,
3862 /// `data_classification`); this probe instead threads through a
3863 /// NESTED-STRUCT intermediary ([`Horizon`], the defaulted nested
3864 /// struct owning the `horizon` axis) to reach a scalar
3865 /// [`HorizonKind`] discriminator on `horizon.kind`. The
3866 /// default-arm short-circuit on the absent-classification arm
3867 /// reads `true` on the [`HorizonKind`] child's `#[default]`
3868 /// variant precisely because BOTH the parent Option's fill-
3869 /// through baseline ([`default_ephemeral_class`], which fills
3870 /// `horizon: Horizon::default()`) AND the child's own `#[default]`
3871 /// land on the SAME variant ([`HorizonKind::Bounded`]). A
3872 /// regression that dropped `#[default]` on [`HorizonKind`], or
3873 /// promoted `Asymptotic` to `#[default]`, or wired the arm to a
3874 /// fixed variant answer, or crossed the wires through the wrong
3875 /// nested struct fails HERE at ONE narrow substrate site before
3876 /// drifting through every unadorned ephemeral spec's baseline
3877 /// horizon answer. Distinct from the FIRST + SECOND peers on the
3878 /// (Option-parent × NON-DEFAULT-scalar-child) corner
3879 /// (`has_point_type`, `has_substrate`) whose absent-classification
3880 /// arm defaults through a specific chosen baseline
3881 /// (`ConvergencePointType::Gate`, `SubstrateType::Compute`), AND
3882 /// distinct from the THIRD + FOURTH peers on the (Option-parent ×
3883 /// DEFAULTED-scalar-child) corner (`has_calm`,
3884 /// `has_data_classification`) which reach a defaulted scalar
3885 /// DIRECTLY off the parent without a nested-struct hop. Three
3886 /// future sibling axes on the SAME `Cow`-resolver carrier
3887 /// ([`Self::has_optimization_direction`] opened the SIXTH; then
3888 /// `has_input_arity`, `has_output_arity`) land as one-line
3889 /// wrappers around the SAME resolver + the sibling
3890 /// [`Classification`] closed-set primitive, so a future variant
3891 /// added to [`HorizonKind`] (or any of the three other closed
3892 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
3893 /// through the SAME closed-set walk with no per-caller edit.
3894 ///
3895 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3896 /// preserves proofs; the classification-axis presence-probe body
3897 /// composes ONE resolver primitive
3898 /// ([`Self::resolved_classification`]) with ONE closed-set
3899 /// primitive ([`Classification::has_horizon_kind`]) so every
3900 /// downstream (`horizon-<kind>` require-tag families on both
3901 /// surfaces in tatara-check, closed-set audit dispatchers, future
3902 /// variant additions on [`HorizonKind`]) binds through the SAME
3903 /// `has(kind)` shape rather than restating either the resolver
3904 /// walk or the closed-set equality at the callsite.
3905 #[must_use]
3906 pub fn has_horizon_kind(&self, kind: HorizonKind) -> bool {
3907 self.resolved_classification().has_horizon_kind(kind)
3908 }
3909
3910 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
3911 /// carries the given [`OptimizationDirection`] discriminator on its
3912 /// `horizon.direction` slot (with the substrate
3913 /// `Option::unwrap_or_default` treating `None` as the closed set's
3914 /// `#[default] Minimize`) — byte-for-byte peer of
3915 /// [`Classification::has_optimization_direction`] wrapped through
3916 /// the [`Self::resolved_classification`] resolver so an operator-
3917 /// omitted `:classification` slot reads as the
3918 /// [`default_ephemeral_class`] baseline the sibling
3919 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3920 ///
3921 /// # Two-surface parity contract
3922 ///
3923 /// A given [`EphemeralSpec`] classifies identically through this
3924 /// primitive AND through
3925 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
3926 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3927 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3928 /// the lowering side both dereference the same
3929 /// `default_ephemeral_class()` value on `None` and the same
3930 /// authored value on `Some(_)`, and the sibling
3931 /// [`Classification::has_optimization_direction`] applies the same
3932 /// `Option::unwrap_or_default` collapse on the inner
3933 /// `horizon.direction` slot on both sides. This means the
3934 /// ephemeral-surface `optimization-direction-<kind>` `:requires`
3935 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3936 /// SAME truth on the SAME authored spec as the point-surface
3937 /// family on the mechanically-lowered `ProcessSpec`.
3938 ///
3939 /// # SIXTH classification-axis peer on the ephemeral surface
3940 ///
3941 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3942 /// [`Self::has_calm`], [`Self::has_data_classification`], and
3943 /// [`Self::has_horizon_kind`] — all six route through the SAME
3944 /// [`Self::resolved_classification`] resolver, so the operator-
3945 /// omitted `:classification` slot's fill-through logic lives at
3946 /// ONE substrate primitive rather than being restated in each per-
3947 /// axis probe body. SECOND occupant on the (Option-parent ×
3948 /// NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
3949 /// corner alongside [`Self::has_horizon_kind`] — both probes thread
3950 /// through the SAME nested [`Horizon`] intermediary to reach a
3951 /// scalar discriminator on the six-axis classification lattice, but
3952 /// this method additionally traverses an `Option`-slot with
3953 /// `unwrap_or_default` so a Process filled through
3954 /// [`crate::classification::Horizon::default`] (leaves `direction:
3955 /// None`) still reads `true` on the closed set's default arm
3956 /// ([`OptimizationDirection::Minimize`]). The corner therefore
3957 /// admits BOTH direct nested-scalar shapes ([`Self::has_horizon_kind`]
3958 /// walks `horizon.kind: HorizonKind` directly) AND Option-nested-
3959 /// scalar shapes (this method walks `horizon.direction:
3960 /// Option<OptimizationDirection>` through `unwrap_or_default`),
3961 /// pinning the corner as a proven-repeatable primitive shape on the
3962 /// ephemeral surface rather than a single-example curiosity. The
3963 /// two-defaults composition property (parent Option's fill-through
3964 /// baseline via `default_ephemeral_class` AND child's closed-set
3965 /// `#[default]` land on the SAME variant) reaches through TWO
3966 /// hops here: the parent Option's `.unwrap_or_else(default_…)`
3967 /// AND the inner Option's `.unwrap_or_default()` both dereference
3968 /// to the same [`OptimizationDirection::Minimize`] baseline the
3969 /// closed set publishes. A regression that flipped
3970 /// [`OptimizationDirection`]'s `#[default]` off `Minimize` (which
3971 /// would silently invert every unadorned `Asymptotic` Process's
3972 /// rate-window evaluator polarity), or that dropped the resolver
3973 /// hop, or that wired the arm to a fixed variant answer, fails
3974 /// HERE at ONE narrow substrate site before drifting through every
3975 /// unadorned ephemeral spec's baseline direction answer. Two future
3976 /// sibling axes on the SAME `Cow`-resolver carrier
3977 /// (`has_input_arity`, `has_output_arity`) land as one-line
3978 /// wrappers around the SAME resolver + the sibling
3979 /// [`Classification`] closed-set primitive, so a future variant
3980 /// added to [`OptimizationDirection`] (or any of the two other
3981 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3982 /// families through the SAME closed-set walk with no per-caller
3983 /// edit.
3984 ///
3985 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3986 /// preserves proofs; the classification-axis presence-probe body
3987 /// composes ONE resolver primitive
3988 /// ([`Self::resolved_classification`]) with ONE closed-set
3989 /// primitive ([`Classification::has_optimization_direction`]) so
3990 /// every downstream (`optimization-direction-<kind>` require-tag
3991 /// families on both surfaces in tatara-check, closed-set audit
3992 /// dispatchers, future variant additions on
3993 /// [`OptimizationDirection`]) binds through the SAME `has(kind)`
3994 /// shape rather than restating either the resolver walk or the
3995 /// closed-set equality plus the nested-struct-Option-hop at the
3996 /// callsite.
3997 #[must_use]
3998 pub fn has_optimization_direction(&self, kind: OptimizationDirection) -> bool {
3999 self.resolved_classification()
4000 .has_optimization_direction(kind)
4001 }
4002
4003 /// True iff the resolved [`Classification`]'s nested
4004 /// [`ConvergencePointType`] projects (via the many-to-one
4005 /// [`ConvergencePointType::input_arity`] typed projection) to the
4006 /// given [`Arity`] discriminator — byte-for-byte peer of
4007 /// [`Classification::has_input_arity`] wrapped through the
4008 /// [`Self::resolved_classification`] resolver so an operator-omitted
4009 /// `:classification` slot reads as the [`default_ephemeral_class`]
4010 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
4011 /// lowering fills.
4012 ///
4013 /// # Two-surface parity contract
4014 ///
4015 /// A given [`EphemeralSpec`] classifies identically through this
4016 /// primitive AND through
4017 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
4018 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
4019 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
4020 /// lowering side both dereference the same
4021 /// `default_ephemeral_class()` value on `None` and the same
4022 /// authored value on `Some(_)`, and the sibling
4023 /// [`Classification::has_input_arity`] applies the same
4024 /// `point_type.input_arity()` typed projection on both sides. This
4025 /// means the ephemeral-surface `input-arity-<kind>` `:requires`
4026 /// family in `tatara-reconciler::bin::tatara-check` publishes the
4027 /// SAME truth on the SAME authored spec as the point-surface family
4028 /// on the mechanically-lowered `ProcessSpec`.
4029 ///
4030 /// # SEVENTH classification-axis peer on the ephemeral surface — first via a derived-typed-projection
4031 ///
4032 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
4033 /// [`Self::has_calm`], [`Self::has_data_classification`],
4034 /// [`Self::has_horizon_kind`], and
4035 /// [`Self::has_optimization_direction`] — all seven route through
4036 /// the SAME [`Self::resolved_classification`] resolver, so the
4037 /// operator-omitted `:classification` slot's fill-through logic
4038 /// lives at ONE substrate primitive rather than being restated in
4039 /// each per-axis probe body. FIRST occupant on the (Option-parent ×
4040 /// NESTED-STRUCT-scalar-child × derived-typed-projection) corner on
4041 /// the ephemeral surface — byte-for-byte symmetric with the
4042 /// derived-typed-projection precedent set by
4043 /// [`Classification::has_input_arity`] on the point surface: THAT
4044 /// peer routes through [`ConvergencePointType::input_arity`] on a
4045 /// required [`Classification`] carrier; THIS peer routes through the
4046 /// SAME projection on the `Cow`-resolver carrier so the resolver
4047 /// walk composes with the projection at ONE substrate site rather
4048 /// than being restated per surface. Distinct from the SIXTH peer
4049 /// [`Self::has_optimization_direction`] (which walks
4050 /// `horizon.direction` through an `Option::unwrap_or_default`
4051 /// collapse to reach a defaulted scalar child) and the FIFTH peer
4052 /// [`Self::has_horizon_kind`] (which walks `horizon.kind` DIRECTLY
4053 /// as a scalar without any typed-projection hop) on ONE dimension:
4054 /// this probe threads through the many-to-one closed-set typed
4055 /// projection [`ConvergencePointType::input_arity`] (`Transform |
4056 /// Fork | Broadcast | Observe → One`, `Join | Gate | Select |
4057 /// Reduce → Many`) so the child's closed set ([`Arity`]) is REACHED
4058 /// THROUGH a projection layer, not read raw off a scalar. The
4059 /// corner therefore admits three ephemeral-surface traversal
4060 /// shapes through the SAME `resolved_classification().<field>`
4061 /// walk: direct-nested-scalar
4062 /// ([`Self::has_horizon_kind`] reads `horizon.kind: HorizonKind`
4063 /// directly), Option-nested-scalar
4064 /// ([`Self::has_optimization_direction`] reads `horizon.direction:
4065 /// Option<OptimizationDirection>` through `unwrap_or_default`), and
4066 /// derived-typed-projection (this method reads
4067 /// `point_type.input_arity(): Arity` through a many-to-one
4068 /// projection). The co-tenant derived-typed-projection axis on the
4069 /// SAME `Cow`-resolver carrier ([`Self::has_output_arity`]) lands as
4070 /// a one-line wrapper around the SAME resolver + the sibling
4071 /// [`Classification`] closed-set primitive, so a future variant
4072 /// added to [`Arity`] or to [`ConvergencePointType`] reaches BOTH
4073 /// surfaces' `<axis>-<kind>` prefix families through the SAME
4074 /// closed-set walk with no per-caller edit.
4075 ///
4076 /// # Semantics — VARIANT match on the projected image
4077 ///
4078 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
4079 /// `#[default]`), so exactly ONE of the two arms answers `true` per
4080 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
4081 /// shortcut. The absent-`:classification` baseline
4082 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
4083 /// [`ConvergencePointType::input_arity`] projects `Gate → Many`, so
4084 /// the ephemeral sugar surface's `input-arity-Many` require-tag
4085 /// reads `true` on every operator-authored spec that omits the
4086 /// `:classification` slot — pinning the workspace's convergent-by-
4087 /// default point posture on the input side. The many-to-one
4088 /// projection shape means the answer is invariant under intra-
4089 /// bucket point-type swaps (`Transform ↔ Fork ↔ Broadcast ↔
4090 /// Observe` all keep `input-arity-One = true`) and flips at bucket
4091 /// boundaries (`Transform ↔ Join` flips `input-arity-One` from
4092 /// `true` to `false`). A regression that dropped the resolver hop,
4093 /// probed [`ConvergencePointType`] directly (dropping the
4094 /// `.input_arity()` call), inverted the projection (`One ↔ Many`),
4095 /// or crossed the wires with the sibling
4096 /// [`ConvergencePointType::output_arity`] projection fails HERE at
4097 /// ONE narrow substrate site before drifting through every
4098 /// unadorned ephemeral spec's baseline input-arity answer.
4099 ///
4100 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4101 /// preserves proofs; the classification-axis presence-probe body
4102 /// composes ONE resolver primitive
4103 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
4104 /// ([`Classification::has_input_arity`]) so every downstream
4105 /// (`input-arity-<kind>` require-tag families on both surfaces in
4106 /// tatara-check, closed-set audit dispatchers, future variant
4107 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
4108 /// through the SAME `has(kind)` shape rather than restating either
4109 /// the resolver walk or the closed-set equality plus the typed-
4110 /// projection hop at the callsite.
4111 #[must_use]
4112 pub fn has_input_arity(&self, kind: Arity) -> bool {
4113 self.resolved_classification().has_input_arity(kind)
4114 }
4115
4116 /// True iff the resolved [`Classification`]'s nested
4117 /// [`ConvergencePointType`] projects (via the many-to-one
4118 /// [`ConvergencePointType::output_arity`] typed projection) to the
4119 /// given [`Arity`] discriminator — byte-for-byte peer of
4120 /// [`Classification::has_output_arity`] wrapped through the
4121 /// [`Self::resolved_classification`] resolver so an operator-omitted
4122 /// `:classification` slot reads as the [`default_ephemeral_class`]
4123 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
4124 /// lowering fills.
4125 ///
4126 /// # Two-surface parity contract
4127 ///
4128 /// A given [`EphemeralSpec`] classifies identically through this
4129 /// primitive AND through
4130 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
4131 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
4132 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
4133 /// lowering side both dereference the same
4134 /// `default_ephemeral_class()` value on `None` and the same
4135 /// authored value on `Some(_)`, and the sibling
4136 /// [`Classification::has_output_arity`] applies the same
4137 /// `point_type.output_arity()` typed projection on both sides. This
4138 /// means the ephemeral-surface `output-arity-<kind>` `:requires`
4139 /// family in `tatara-reconciler::bin::tatara-check` publishes the
4140 /// SAME truth on the SAME authored spec as the point-surface family
4141 /// on the mechanically-lowered `ProcessSpec`.
4142 ///
4143 /// # EIGHTH classification-axis peer — closes the ephemeral-side DAG-composition arity pair
4144 ///
4145 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
4146 /// [`Self::has_calm`], [`Self::has_data_classification`],
4147 /// [`Self::has_horizon_kind`], [`Self::has_optimization_direction`],
4148 /// and [`Self::has_input_arity`] — all eight route through the SAME
4149 /// [`Self::resolved_classification`] resolver, so the operator-
4150 /// omitted `:classification` slot's fill-through logic lives at ONE
4151 /// substrate primitive rather than being restated in each per-axis
4152 /// probe body. SECOND occupant on the (Option-parent × NESTED-
4153 /// STRUCT-scalar-child × derived-typed-projection) corner on the
4154 /// ephemeral surface — co-tenant with [`Self::has_input_arity`] on
4155 /// the SAME `point_type` scalar carrier through the SAME [`Arity`]
4156 /// closed set but through the sibling many-to-one typed projection
4157 /// [`ConvergencePointType::output_arity`] (`Transform | Join | Gate
4158 /// | Select | Reduce | Observe → One`, `Fork | Broadcast → Many`).
4159 /// Closes the DAG-composition arity pair on the ephemeral side —
4160 /// the two projections DISAGREE on the diffusive arms `Fork |
4161 /// Broadcast` (input `One` vs. output `Many`) and on the convergent
4162 /// arms `Join | Gate | Select | Reduce` (input `Many` vs. output
4163 /// `One`), and AGREE on the endomorphic arms `Transform | Observe`
4164 /// (both `One`). Byte-for-byte symmetric with the DAG-composition
4165 /// arity pair on the point surface ([`Classification::has_input_arity`] +
4166 /// [`Classification::has_output_arity`]) — THAT pair walks a required
4167 /// [`Classification`] carrier; THIS pair walks the SAME projection
4168 /// pair on the `Cow`-resolver carrier so the resolver walk composes
4169 /// with the projection at ONE substrate site rather than being
4170 /// restated per surface.
4171 ///
4172 /// # Semantics — VARIANT match on the projected image
4173 ///
4174 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
4175 /// `#[default]`), so exactly ONE of the two arms answers `true` per
4176 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
4177 /// shortcut. The absent-`:classification` baseline
4178 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
4179 /// [`ConvergencePointType::output_arity`] projects `Gate → One`, so
4180 /// the ephemeral sugar surface's `output-arity-One` require-tag
4181 /// reads `true` on every operator-authored spec that omits the
4182 /// `:classification` slot — pinning the workspace's convergent-by-
4183 /// default point posture on the output side. The many-to-one
4184 /// projection shape means the answer is invariant under intra-
4185 /// bucket point-type swaps (`Fork ↔ Broadcast` both keep
4186 /// `output-arity-Many = true`; `Transform ↔ Join ↔ Gate ↔ Select ↔
4187 /// Reduce ↔ Observe` all keep `output-arity-One = true`) and flips
4188 /// at bucket boundaries (`Fork ↔ Transform` flips `output-arity-
4189 /// Many` from `true` to `false`). A regression that dropped the
4190 /// resolver hop, probed [`ConvergencePointType`] directly (dropping
4191 /// the `.output_arity()` call), inverted the projection (`One ↔
4192 /// Many`), or crossed the wires with the sibling
4193 /// [`ConvergencePointType::input_arity`] projection fails HERE at
4194 /// ONE narrow substrate site before drifting through every
4195 /// unadorned ephemeral spec's baseline output-arity answer.
4196 ///
4197 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4198 /// preserves proofs; the classification-axis presence-probe body
4199 /// composes ONE resolver primitive
4200 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
4201 /// ([`Classification::has_output_arity`]) so every downstream
4202 /// (`output-arity-<kind>` require-tag families on both surfaces in
4203 /// tatara-check, closed-set audit dispatchers, future variant
4204 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
4205 /// through the SAME `has(kind)` shape rather than restating either
4206 /// the resolver walk or the closed-set equality plus the typed-
4207 /// projection hop at the callsite.
4208 #[must_use]
4209 pub fn has_output_arity(&self, kind: Arity) -> bool {
4210 self.resolved_classification().has_output_arity(kind)
4211 }
4212
4213 /// Derived-boolean predicate — does this ephemeral spec's
4214 /// resolved [`Classification`]'s [`Horizon`] project to `true`
4215 /// under [`crate::classification::HorizonKind::terminates`]?
4216 /// Byte-for-byte peer of
4217 /// [`Classification::horizon_terminates`] wrapped through the
4218 /// [`Self::resolved_classification`] resolver so an operator-
4219 /// omitted `:classification` slot on `(defephemeral …)` still
4220 /// answers via the substrate default. The ONE ephemeral-surface
4221 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4222 /// derived-nullary-boolean walk on the classification-horizon
4223 /// axis.
4224 ///
4225 /// # Two-surface parity — resolver hop + Classification primitive
4226 ///
4227 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
4228 /// [`Self::has_calm`], [`Self::has_data_classification`],
4229 /// [`Self::has_horizon_kind`],
4230 /// [`Self::has_optimization_direction`],
4231 /// [`Self::has_input_arity`], and [`Self::has_output_arity`] on
4232 /// the (resolver-hop × [`Classification`] presence primitive)
4233 /// axis: all nine methods route through the SAME
4234 /// [`Self::resolved_classification`] resolver, and each composes
4235 /// against ONE [`Classification`] primitive. This method
4236 /// distinguishes itself by targeting the [`Classification`]
4237 /// primitive [`Classification::horizon_terminates`] which is the
4238 /// FIRST derived-nullary-boolean (no closed-set argument)
4239 /// primitive on the [`Classification`] surface — every prior
4240 /// peer probe on [`Classification`] admits a closed-set `kind`
4241 /// argument and answers a variant-equality question, while this
4242 /// probe collapses [`HorizonKind::ALL`] onto a single boolean
4243 /// via the closed set's own [`HorizonKind::terminates`]
4244 /// predicate.
4245 ///
4246 /// # Semantics — resolver hop + derived-nullary-boolean
4247 ///
4248 /// `horizon_terminates()` returns `true` iff
4249 /// `self.resolved_classification().horizon_terminates()`. The
4250 /// resolver returns the authored [`Classification`] when
4251 /// present and the substrate default
4252 /// [`Classification::gate_compute`] on absence. Because
4253 /// [`Classification::gate_compute`] uses [`Horizon::default`]
4254 /// (whose `kind` field defaults to [`HorizonKind::Bounded`] via
4255 /// `#[default]`), a bare ephemeral spec with no `:classification`
4256 /// slot answers `true` — the default-arm short-circuit
4257 /// propagates through THREE layers of `Default`
4258 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
4259 /// [`HorizonKind::default`]) to this predicate's answer, matching
4260 /// the default-arm shortcut every prior defaulted-child probe
4261 /// on this surface publishes. A regression that dropped the
4262 /// resolver hop, probed [`Classification::has_horizon_kind`]
4263 /// directly (dropping the `.terminates()` projection), or
4264 /// crossed the wires with the antisymmetric partner
4265 /// [`HorizonKind::requires_metric_axes`] fails HERE at ONE
4266 /// narrow substrate site before drifting through every
4267 /// unadorned ephemeral spec's baseline horizon-terminates
4268 /// answer.
4269 ///
4270 /// # Compounding
4271 ///
4272 /// The ephemeral require-tag classifier composes this primitive
4273 /// as a fixed tag `terminating-horizon` on
4274 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4275 /// surface's `terminating-horizon` fixed tag on
4276 /// `POINT_FIXED_TAG_ARMS` via [`Classification::horizon_terminates`]
4277 /// directly. The two-surface parity contract holds by
4278 /// construction: both surfaces route through the SAME
4279 /// [`Classification::horizon_terminates`] primitive after the
4280 /// ephemeral surface pays ONE resolver hop — a future
4281 /// [`HorizonKind`] variant or a future normalization at the
4282 /// substrate primitive lands at ONE site and both surfaces'
4283 /// `terminating-horizon` fixed tags inherit the shift
4284 /// mechanically. A future co-tenant peer on this surface (a
4285 /// hypothetical `horizon_requires_metric_axes` composing the
4286 /// antisymmetric partner [`HorizonKind::requires_metric_axes`]
4287 /// through the SAME resolver hop) lands as ONE peer inherent
4288 /// method with the same nullary-derived body.
4289 ///
4290 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4291 /// preserves proofs; the classification-axis derived-nullary-
4292 /// boolean probe body composes ONE resolver primitive
4293 /// ([`Self::resolved_classification`]) with ONE
4294 /// [`Classification`] primitive
4295 /// ([`Classification::horizon_terminates`]) so every downstream
4296 /// (`terminating-horizon` fixed tags on both surfaces in
4297 /// tatara-check, future scheduler / termination-shape
4298 /// validators, future variant additions on [`HorizonKind`])
4299 /// binds through the SAME `horizon_terminates()` shape rather
4300 /// than restating either the resolver walk or the closed-set
4301 /// projection composition at the callsite. THEORY.md §VI.1 —
4302 /// generation over composition; a future [`HorizonKind`]
4303 /// variant lands at ONE `ALL` entry + ONE `terminates` arm on
4304 /// the closed set and both surfaces pick it up mechanically.
4305 #[must_use]
4306 pub fn horizon_terminates(&self) -> bool {
4307 self.resolved_classification().horizon_terminates()
4308 }
4309
4310 /// Derived-boolean predicate — does this ephemeral spec's
4311 /// resolved [`Classification`]'s [`Horizon`] project to `true`
4312 /// under [`crate::classification::HorizonKind::requires_metric_axes`]?
4313 /// Byte-for-byte peer of
4314 /// [`Classification::horizon_requires_metric_axes`] wrapped
4315 /// through the [`Self::resolved_classification`] resolver so an
4316 /// operator-omitted `:classification` slot on `(defephemeral …)`
4317 /// still answers via the substrate default. The ONE ephemeral-
4318 /// surface substrate primitive that owns the
4319 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on
4320 /// the metric-axes-required question over the classification-
4321 /// horizon axis.
4322 ///
4323 /// # Antisymmetric peer of [`Self::horizon_terminates`]
4324 ///
4325 /// Byte-for-byte antisymmetric peer of [`Self::horizon_terminates`]
4326 /// via the SAME [`Self::resolved_classification`] resolver hop
4327 /// and the SAME closed set [`crate::classification::HorizonKind`]:
4328 /// [`Self::horizon_terminates`] composes
4329 /// [`Classification::horizon_terminates`] (walking
4330 /// [`crate::classification::HorizonKind::terminates`]); this
4331 /// method composes the ANTISYMMETRIC partner
4332 /// [`Classification::horizon_requires_metric_axes`] (walking
4333 /// [`crate::classification::HorizonKind::requires_metric_axes`]).
4334 /// The closed set pins the XOR contract
4335 /// `terminates() ^ requires_metric_axes()` on every variant, so
4336 /// exactly ONE of these two ephemeral-surface derived-nullary
4337 /// probes answers `true` per resolved [`Classification`] and the
4338 /// two probes together partition the resolver's output space into
4339 /// two disjoint buckets on every ephemeral spec — authored or
4340 /// defaulted.
4341 ///
4342 /// # Semantics — resolver hop + derived-nullary-boolean
4343 ///
4344 /// `horizon_requires_metric_axes()` returns `true` iff
4345 /// `self.resolved_classification().horizon_requires_metric_axes()`.
4346 /// The resolver returns the authored [`Classification`] when
4347 /// present and the substrate default
4348 /// [`Classification::gate_compute`] on absence. Because
4349 /// [`Classification::gate_compute`] uses [`Horizon::default`]
4350 /// (whose `kind` field defaults to
4351 /// [`crate::classification::HorizonKind::Bounded`] via
4352 /// `#[default]`), a bare ephemeral spec with no `:classification`
4353 /// slot answers `false` — the default-arm short-circuit
4354 /// propagates through THREE layers of `Default`
4355 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
4356 /// [`crate::classification::HorizonKind::default`]) to this
4357 /// predicate's answer, the mirror image of
4358 /// [`Self::horizon_terminates`]'s default-arm `true` answer. A
4359 /// regression that dropped the resolver hop, probed
4360 /// [`Classification::has_horizon_kind`] directly (dropping the
4361 /// `.requires_metric_axes()` projection), or crossed the wires
4362 /// with the antisymmetric partner
4363 /// [`crate::classification::HorizonKind::terminates`] fails HERE
4364 /// at ONE narrow substrate site before drifting through every
4365 /// unadorned ephemeral spec's baseline metric-provisioning
4366 /// answer.
4367 ///
4368 /// # Compounding
4369 ///
4370 /// The ephemeral require-tag classifier composes this primitive
4371 /// as a fixed tag `metric-axes-required` on
4372 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4373 /// surface's `metric-axes-required` fixed tag on
4374 /// `POINT_FIXED_TAG_ARMS` via
4375 /// [`Classification::horizon_requires_metric_axes`] directly. The
4376 /// two-surface parity contract holds by construction: both
4377 /// surfaces route through the SAME
4378 /// [`Classification::horizon_requires_metric_axes`] primitive
4379 /// after the ephemeral surface pays ONE resolver hop — a future
4380 /// [`crate::classification::HorizonKind`] variant or a future
4381 /// normalization at the substrate primitive lands at ONE site and
4382 /// both surfaces' `metric-axes-required` fixed tags inherit the
4383 /// shift mechanically.
4384 ///
4385 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4386 /// preserves proofs; the classification-axis derived-nullary-
4387 /// boolean probe body composes ONE resolver primitive
4388 /// ([`Self::resolved_classification`]) with ONE
4389 /// [`Classification`] primitive
4390 /// ([`Classification::horizon_requires_metric_axes`]) so every
4391 /// downstream (`metric-axes-required` fixed tags on both
4392 /// surfaces in tatara-check, future scheduler / metric-
4393 /// provisioning validators, future variant additions on
4394 /// [`crate::classification::HorizonKind`]) binds through the
4395 /// SAME `horizon_requires_metric_axes()` shape rather than
4396 /// restating either the resolver walk or the closed-set
4397 /// projection composition at the callsite. THEORY.md §VI.1 —
4398 /// generation over composition; a future
4399 /// [`crate::classification::HorizonKind`] variant lands at ONE
4400 /// `ALL` entry + ONE `requires_metric_axes` arm on the closed
4401 /// set and both surfaces pick it up mechanically.
4402 #[must_use]
4403 pub fn horizon_requires_metric_axes(&self) -> bool {
4404 self.resolved_classification()
4405 .horizon_requires_metric_axes()
4406 }
4407
4408 /// Derived-boolean predicate — does this ephemeral spec's
4409 /// resolved [`Classification`]'s [`crate::classification::CalmClassification`]
4410 /// project to `true` under
4411 /// [`crate::classification::CalmClassification::requires_coordination`]?
4412 /// Byte-for-byte peer of
4413 /// [`Classification::calm_requires_coordination`] wrapped through
4414 /// the [`Self::resolved_classification`] resolver so an operator-
4415 /// omitted `:classification` slot on `(defephemeral …)` still
4416 /// answers via the substrate default. The ONE ephemeral-surface
4417 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4418 /// derived-nullary-boolean walk on the coordination-required
4419 /// question over the classification-calm axis.
4420 ///
4421 /// # Third derived-nullary-boolean peer on the ephemeral surface
4422 ///
4423 /// Peer of [`Self::horizon_terminates`] and
4424 /// [`Self::horizon_requires_metric_axes`] on the ephemeral
4425 /// surface's (resolver-hop × derived-nullary-bool) shape — the
4426 /// FIRST peer threading the classification-calm axis rather than
4427 /// the classification-horizon axis. Distinct from both prior
4428 /// derived-nullary peers by ONE structural degree at the underlying
4429 /// [`Classification`] primitive: [`Self::horizon_terminates`] +
4430 /// [`Self::horizon_requires_metric_axes`] both walk the nested
4431 /// `.horizon.kind` sub-slot's derived projection, while this probe
4432 /// walks the direct scalar `.calm` field's derived projection.
4433 /// The resolver-hop shape is byte-identical.
4434 ///
4435 /// # Semantics — resolver hop + derived-nullary-boolean
4436 ///
4437 /// `calm_requires_coordination()` returns `true` iff
4438 /// `self.resolved_classification().calm_requires_coordination()`.
4439 /// The resolver returns the authored [`Classification`] when
4440 /// present and the substrate default
4441 /// [`Classification::gate_compute`] on absence. Because
4442 /// [`Classification::gate_compute`] carries
4443 /// [`crate::classification::CalmClassification::default = Monotone`],
4444 /// a bare ephemeral spec with no `:classification` slot answers
4445 /// `false` — the default-arm short-circuit propagates through TWO
4446 /// layers of `Default` ([`Classification::gate_compute`] →
4447 /// [`crate::classification::CalmClassification::default`]) to this
4448 /// predicate's answer. Distinct from the two `horizon_*` peers on
4449 /// this surface, which short-circuit through THREE layers of
4450 /// `Default` ([`Classification::gate_compute`] → [`Horizon::default`]
4451 /// → [`HorizonKind::default`]) because the horizon axis has a
4452 /// nested-struct wrapper between the classification field and the
4453 /// closed-set discriminator. A regression that dropped the
4454 /// resolver hop, probed [`Classification::has_calm`] directly
4455 /// (dropping the `.requires_coordination()` projection), or
4456 /// inverted the projection (silently promoting the Monotone
4457 /// baseline to "requires coordination") fails HERE at ONE narrow
4458 /// substrate site before drifting through every unadorned
4459 /// ephemeral spec's baseline coordination-mode answer.
4460 ///
4461 /// # Compounding
4462 ///
4463 /// The ephemeral require-tag classifier composes this primitive
4464 /// as a fixed tag `coordination-required` on
4465 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4466 /// surface's `coordination-required` fixed tag on
4467 /// `POINT_FIXED_TAG_ARMS` via
4468 /// [`Classification::calm_requires_coordination`] directly. The
4469 /// two-surface parity contract holds by construction: both
4470 /// surfaces route through the SAME
4471 /// [`Classification::calm_requires_coordination`] primitive after
4472 /// the ephemeral surface pays ONE resolver hop — a future
4473 /// [`crate::classification::CalmClassification`] variant or a
4474 /// future normalization at the substrate primitive lands at ONE
4475 /// site and both surfaces' `coordination-required` fixed tags
4476 /// inherit the shift mechanically.
4477 ///
4478 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4479 /// preserves proofs; the classification-axis derived-nullary-
4480 /// boolean probe body composes ONE resolver primitive
4481 /// ([`Self::resolved_classification`]) with ONE
4482 /// [`Classification`] primitive
4483 /// ([`Classification::calm_requires_coordination`]) so every
4484 /// downstream (`coordination-required` fixed tags on both
4485 /// surfaces in tatara-check, future scheduler / coordination-mode
4486 /// validators, future variant additions on
4487 /// [`crate::classification::CalmClassification`]) binds through
4488 /// the SAME `calm_requires_coordination()` shape rather than
4489 /// restating either the resolver walk or the closed-set
4490 /// projection composition at the callsite. THEORY.md §VI.1 —
4491 /// generation over composition; a future
4492 /// [`crate::classification::CalmClassification`] variant lands at
4493 /// ONE `ALL` entry + ONE `requires_coordination` arm on the
4494 /// closed set and both surfaces pick it up mechanically.
4495 #[must_use]
4496 pub fn calm_requires_coordination(&self) -> bool {
4497 self.resolved_classification().calm_requires_coordination()
4498 }
4499
4500 /// Derived-boolean predicate — does this ephemeral spec's
4501 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
4502 /// project to `true` under
4503 /// [`crate::classification::DataClassification::is_regulated`]?
4504 /// Byte-for-byte peer of
4505 /// [`Classification::data_is_regulated`] wrapped through the
4506 /// [`Self::resolved_classification`] resolver so an operator-
4507 /// omitted `:classification` slot on `(defephemeral …)` still
4508 /// answers via the substrate default. The ONE ephemeral-surface
4509 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4510 /// derived-nullary-boolean walk on the regulated-data question
4511 /// over the classification-data axis.
4512 ///
4513 /// # Fourth derived-nullary-boolean peer on the ephemeral surface
4514 ///
4515 /// Peer of [`Self::horizon_terminates`],
4516 /// [`Self::horizon_requires_metric_axes`], and
4517 /// [`Self::calm_requires_coordination`] on the ephemeral surface's
4518 /// (resolver-hop × derived-nullary-bool) shape — the FIRST peer
4519 /// threading the classification-data axis rather than the horizon
4520 /// or calm axes. Structural byte-for-byte peer of
4521 /// [`Self::calm_requires_coordination`]: both walk a DIRECT scalar
4522 /// closed-set field's derived projection on the resolved
4523 /// [`Classification`] (`.calm.requires_coordination()` /
4524 /// `.data_classification.is_regulated()`) — TWO layers of
4525 /// `Default` short-circuit ([`Classification::gate_compute`] →
4526 /// the direct scalar child's `#[default]`) — distinct from the
4527 /// two `horizon_*` peers which walk a NESTED-STRUCT projection
4528 /// (`.horizon.kind`) with THREE layers of `Default`. The resolver-
4529 /// hop shape is byte-identical across all four peers.
4530 ///
4531 /// # Semantics — resolver hop + derived-nullary-boolean
4532 ///
4533 /// `data_is_regulated()` returns `true` iff
4534 /// `self.resolved_classification().data_is_regulated()`. The
4535 /// resolver returns the authored [`Classification`] when present
4536 /// and the substrate default [`Classification::gate_compute`] on
4537 /// absence. Because [`Classification::gate_compute`] carries
4538 /// [`crate::classification::DataClassification::default = Internal`],
4539 /// a bare ephemeral spec with no `:classification` slot answers
4540 /// `false` — the default-arm short-circuit propagates through TWO
4541 /// layers of `Default` ([`Classification::gate_compute`] →
4542 /// [`crate::classification::DataClassification::default`]) to
4543 /// this predicate's answer, mirror-image of
4544 /// [`Self::calm_requires_coordination`]'s Monotone-default
4545 /// short-circuit through the same structural depth. Distinct
4546 /// from the two `horizon_*` peers on this surface which short-
4547 /// circuit through THREE layers of `Default` because the horizon
4548 /// axis has a nested-struct wrapper. A regression that dropped
4549 /// the resolver hop, probed [`Classification::has_data_classification`]
4550 /// directly (dropping the `.is_regulated()` projection), or
4551 /// inverted the projection (silently promoting the Internal
4552 /// baseline to "regulated") fails HERE at ONE narrow substrate
4553 /// site before drifting through every unadorned ephemeral spec's
4554 /// baseline regulatory-regime answer.
4555 ///
4556 /// # Compounding
4557 ///
4558 /// The ephemeral require-tag classifier composes this primitive
4559 /// as a fixed tag `data-regulated` on `EPHEMERAL_FIXED_TAG_ARMS`
4560 /// — byte-for-byte peer of the point surface's `data-regulated`
4561 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4562 /// [`Classification::data_is_regulated`] directly. The two-
4563 /// surface parity contract holds by construction: both surfaces
4564 /// route through the SAME
4565 /// [`Classification::data_is_regulated`] primitive after the
4566 /// ephemeral surface pays ONE resolver hop — a future
4567 /// [`crate::classification::DataClassification`] variant or a
4568 /// future normalization at the substrate primitive lands at ONE
4569 /// site and both surfaces' `data-regulated` fixed tags inherit
4570 /// the shift mechanically.
4571 ///
4572 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4573 /// preserves proofs; the classification-data-axis derived-nullary-
4574 /// boolean probe body composes ONE resolver primitive
4575 /// ([`Self::resolved_classification`]) with ONE
4576 /// [`Classification`] primitive
4577 /// ([`Classification::data_is_regulated`]) so every downstream
4578 /// (`data-regulated` fixed tags on both surfaces in tatara-check,
4579 /// future compliance-baseline / regulatory-regime validators,
4580 /// future variant additions on
4581 /// [`crate::classification::DataClassification`]) binds through
4582 /// the SAME `data_is_regulated()` shape rather than restating
4583 /// either the resolver walk or the closed-set projection
4584 /// composition at the callsite. THEORY.md §VI.1 — generation
4585 /// over composition; a future
4586 /// [`crate::classification::DataClassification`] variant lands
4587 /// at ONE `ALL` entry + ONE `is_regulated` arm on the closed set
4588 /// and both surfaces pick it up mechanically.
4589 #[must_use]
4590 pub fn data_is_regulated(&self) -> bool {
4591 self.resolved_classification().data_is_regulated()
4592 }
4593
4594 /// Derived-boolean predicate — does this ephemeral spec's
4595 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
4596 /// project to `true` under
4597 /// [`crate::classification::DataClassification::is_restricted`]?
4598 /// Byte-for-byte peer of
4599 /// [`Classification::data_is_restricted`] wrapped through the
4600 /// [`Self::resolved_classification`] resolver so an operator-
4601 /// omitted `:classification` slot on `(defephemeral …)` still
4602 /// answers via the substrate default. The ONE ephemeral-surface
4603 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4604 /// derived-nullary-boolean walk on the restricted-data question
4605 /// over the classification-data axis.
4606 ///
4607 /// # Fifth derived-nullary-boolean peer on the ephemeral surface
4608 ///
4609 /// Peer of [`Self::horizon_terminates`],
4610 /// [`Self::horizon_requires_metric_axes`],
4611 /// [`Self::calm_requires_coordination`], and
4612 /// [`Self::data_is_regulated`] on the ephemeral surface's
4613 /// (resolver-hop × derived-nullary-bool) shape — the SECOND peer
4614 /// threading the classification-data axis after
4615 /// [`Self::data_is_regulated`] opened it, pinning the data axis
4616 /// as a proven-repeatable structural sub-corner across TWO sibling
4617 /// closed-set projections (`is_regulated` / `is_restricted`).
4618 /// Structural byte-for-byte peer of
4619 /// [`Self::data_is_regulated`]: both walk the SAME DIRECT scalar
4620 /// closed-set field's derived projection on the resolved
4621 /// [`Classification`] (`.data_classification.is_regulated()` /
4622 /// `.is_restricted()`) — TWO layers of `Default` short-circuit
4623 /// ([`Classification::gate_compute`] → [`crate::classification::DataClassification::default = Internal`])
4624 /// — distinct from the two `horizon_*` peers which walk a NESTED-
4625 /// STRUCT projection (`.horizon.kind`) with THREE layers of
4626 /// `Default`. The resolver-hop shape is byte-identical across all
4627 /// five peers.
4628 ///
4629 /// # Semantics — resolver hop + derived-nullary-boolean
4630 ///
4631 /// `data_is_restricted()` returns `true` iff
4632 /// `self.resolved_classification().data_is_restricted()`. The
4633 /// resolver returns the authored [`Classification`] when present
4634 /// and the substrate default [`Classification::gate_compute`] on
4635 /// absence. Because [`Classification::gate_compute`] carries
4636 /// [`crate::classification::DataClassification::default = Internal`],
4637 /// a bare ephemeral spec with no `:classification` slot answers
4638 /// `true` — the default-arm short-circuit propagates through TWO
4639 /// layers of `Default` ([`Classification::gate_compute`] →
4640 /// [`crate::classification::DataClassification::default`]) to
4641 /// this predicate's answer. FIRST direct-scalar ephemeral-surface
4642 /// peer whose absent-classification default answers `true`, not
4643 /// `false` (`data_is_regulated` and `calm_requires_coordination`
4644 /// both project `false` on the same absent classification),
4645 /// mirror-image of [`Self::horizon_terminates`]'s `Bounded`-default
4646 /// `true` baseline on the nested-struct sub-corner. A regression
4647 /// that dropped the resolver hop, probed
4648 /// [`Classification::has_data_classification`] directly (dropping
4649 /// the `.is_restricted()` projection), or inverted the projection
4650 /// (silently demoting the Internal baseline to "unrestricted")
4651 /// fails HERE at ONE narrow substrate site before drifting
4652 /// through every unadorned ephemeral spec's baseline access-
4653 /// control-mandatory answer.
4654 ///
4655 /// # Compounding
4656 ///
4657 /// The ephemeral require-tag classifier composes this primitive
4658 /// as a fixed tag `data-restricted` on `EPHEMERAL_FIXED_TAG_ARMS`
4659 /// — byte-for-byte peer of the point surface's `data-restricted`
4660 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4661 /// [`Classification::data_is_restricted`] directly. The two-
4662 /// surface parity contract holds by construction: both surfaces
4663 /// route through the SAME
4664 /// [`Classification::data_is_restricted`] primitive after the
4665 /// ephemeral surface pays ONE resolver hop — a future
4666 /// [`crate::classification::DataClassification`] variant or a
4667 /// future normalization at the substrate primitive lands at ONE
4668 /// site and both surfaces' `data-restricted` fixed tags inherit
4669 /// the shift mechanically. The closed-set-internal implication
4670 /// `is_regulated() ⇒ is_restricted()` composes through the
4671 /// resolver hop to
4672 /// `data_is_regulated() ⇒ data_is_restricted()` at this surface
4673 /// too.
4674 ///
4675 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4676 /// preserves proofs; the classification-data-axis derived-nullary-
4677 /// boolean probe body composes ONE resolver primitive
4678 /// ([`Self::resolved_classification`]) with ONE
4679 /// [`Classification`] primitive
4680 /// ([`Classification::data_is_restricted`]) so every downstream
4681 /// (`data-restricted` fixed tags on both surfaces in tatara-check,
4682 /// future compliance-baseline / access-control-mandatory
4683 /// validators, future variant additions on
4684 /// [`crate::classification::DataClassification`]) binds through
4685 /// the SAME `data_is_restricted()` shape rather than restating
4686 /// either the resolver walk or the closed-set projection
4687 /// composition at the callsite. THEORY.md §VI.1 — generation
4688 /// over composition; a future
4689 /// [`crate::classification::DataClassification`] variant lands
4690 /// at ONE `ALL` entry + ONE `is_restricted` arm on the closed set
4691 /// and both surfaces pick it up mechanically.
4692 #[must_use]
4693 pub fn data_is_restricted(&self) -> bool {
4694 self.resolved_classification().data_is_restricted()
4695 }
4696
4697 /// Derived-boolean predicate — does this ephemeral spec's
4698 /// resolved [`Classification`]'s
4699 /// [`crate::classification::ConvergencePointType`] project to
4700 /// `true` under
4701 /// [`crate::classification::ConvergencePointType::is_endomorphic`]?
4702 /// Byte-for-byte peer of
4703 /// [`Classification::point_is_endomorphic`] wrapped through the
4704 /// [`Self::resolved_classification`] resolver so an operator-
4705 /// omitted `:classification` slot on `(defephemeral …)` still
4706 /// answers via the substrate default. The ONE ephemeral-surface
4707 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4708 /// derived-nullary-boolean walk on the 1→1 topology-bucket
4709 /// question over the classification-`point_type` axis.
4710 ///
4711 /// # Sixth derived-nullary-boolean peer on the ephemeral surface
4712 ///
4713 /// Peer of [`Self::horizon_terminates`],
4714 /// [`Self::horizon_requires_metric_axes`],
4715 /// [`Self::calm_requires_coordination`],
4716 /// [`Self::data_is_regulated`], and [`Self::data_is_restricted`]
4717 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
4718 /// shape — the FIRST peer threading the classification-`point_type`
4719 /// axis after the two `horizon_*`, one `calm_*`, and two `data_*`
4720 /// peers populated the horizon, calm, and data axes. Direct-scalar
4721 /// peer of the sibling `data_*` and `calm_*` arms but distinct by
4722 /// ONE structural degree at the underlying [`Classification`]
4723 /// primitive: [`crate::classification::ConvergencePointType`] has
4724 /// NO [`Default`] impl, so the absent-`:classification` baseline
4725 /// answers `false` via the resolver's substrate default
4726 /// [`Classification::gate_compute`] carrying its chosen
4727 /// `point_type: Gate` field (not via a `#[default]` short-circuit
4728 /// on the point-type axis itself). The resolver-hop shape is
4729 /// byte-identical across all six peers.
4730 ///
4731 /// # Semantics — resolver hop + derived-nullary-boolean
4732 ///
4733 /// `point_is_endomorphic()` returns `true` iff
4734 /// `self.resolved_classification().point_is_endomorphic()`. The
4735 /// resolver returns the authored [`Classification`] when present
4736 /// and the substrate default [`Classification::gate_compute`] on
4737 /// absence. Because [`Classification::gate_compute`] carries
4738 /// [`crate::classification::ConvergencePointType::Gate`] (a
4739 /// convergent barrier point, not a 1→1 endomorphism), a bare
4740 /// ephemeral spec with no `:classification` slot answers `false`.
4741 /// A regression that dropped the resolver hop, probed the wrong
4742 /// closed-set arm, or inverted the projection fails HERE at ONE
4743 /// narrow substrate site before drifting through every unadorned
4744 /// ephemeral spec's DAG-composition answer.
4745 ///
4746 /// # Compounding
4747 ///
4748 /// The ephemeral require-tag classifier composes this primitive
4749 /// as a fixed tag `endomorphic-point` on
4750 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4751 /// surface's `endomorphic-point` fixed tag on
4752 /// `POINT_FIXED_TAG_ARMS` via
4753 /// [`Classification::point_is_endomorphic`] directly. The two-
4754 /// surface parity contract holds by construction: both surfaces
4755 /// route through the SAME
4756 /// [`Classification::point_is_endomorphic`] primitive after the
4757 /// ephemeral surface pays ONE resolver hop — a future
4758 /// [`crate::classification::ConvergencePointType`] variant or a
4759 /// future normalization at the substrate primitive lands at ONE
4760 /// site and both surfaces' `endomorphic-point` fixed tags inherit
4761 /// the shift mechanically. Sibling projections
4762 /// [`crate::classification::ConvergencePointType::is_diffusive`]
4763 /// and [`crate::classification::ConvergencePointType::is_convergent`]
4764 /// compose byte-identically as future seventh + eighth ephemeral-
4765 /// surface peers; when all three land the three-way partition
4766 /// contract sealed on the closed set by
4767 /// `convergence_point_type_buckets_cover_every_variant` composes
4768 /// through the resolver-hop layer as a substrate-wide theorem.
4769 ///
4770 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4771 /// preserves proofs; the classification-`point_type`-axis derived-
4772 /// nullary-boolean probe body composes ONE resolver primitive
4773 /// ([`Self::resolved_classification`]) with ONE
4774 /// [`Classification`] primitive
4775 /// ([`Classification::point_is_endomorphic`]) so every downstream
4776 /// (`endomorphic-point` fixed tags on both surfaces in tatara-check,
4777 /// future DAG composition / edge-cardinality validators, future
4778 /// variant additions on
4779 /// [`crate::classification::ConvergencePointType`]) binds through
4780 /// the SAME `point_is_endomorphic()` shape rather than restating
4781 /// either the resolver walk or the closed-set projection
4782 /// composition at the callsite. THEORY.md §VI.1 — generation over
4783 /// composition; a future
4784 /// [`crate::classification::ConvergencePointType`] variant lands
4785 /// at ONE `ALL` entry + ONE `is_endomorphic` arm on the closed
4786 /// set and both surfaces pick it up mechanically.
4787 #[must_use]
4788 pub fn point_is_endomorphic(&self) -> bool {
4789 self.resolved_classification().point_is_endomorphic()
4790 }
4791
4792 /// Derived-boolean predicate — does this ephemeral spec's
4793 /// resolved [`Classification`]'s
4794 /// [`crate::classification::ConvergencePointType`] project to
4795 /// `true` under
4796 /// [`crate::classification::ConvergencePointType::is_diffusive`]?
4797 /// Byte-for-byte peer of
4798 /// [`Classification::point_is_diffusive`] wrapped through the
4799 /// [`Self::resolved_classification`] resolver so an operator-
4800 /// omitted `:classification` slot on `(defephemeral …)` still
4801 /// answers via the substrate default. The ONE ephemeral-surface
4802 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4803 /// derived-nullary-boolean walk on the 1→N fan-out topology-bucket
4804 /// question over the classification-`point_type` axis.
4805 ///
4806 /// # Seventh derived-nullary-boolean peer on the ephemeral surface
4807 ///
4808 /// Peer of [`Self::horizon_terminates`],
4809 /// [`Self::horizon_requires_metric_axes`],
4810 /// [`Self::calm_requires_coordination`],
4811 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`], and
4812 /// [`Self::point_is_endomorphic`] on the ephemeral surface's
4813 /// (resolver-hop × derived-nullary-bool) shape — the SEVENTH peer
4814 /// overall and the SECOND peer threading the classification-
4815 /// `point_type` axis. Direct-scalar peer of
4816 /// [`Self::point_is_endomorphic`]: both compose the SAME resolver
4817 /// hop and the SAME closed-set carrier through the SAME chosen-
4818 /// field baseline discipline (`Gate.is_diffusive() = false`,
4819 /// mirror-image of `Gate.is_endomorphic() = false`). The
4820 /// resolver-hop shape is byte-identical across all seven peers.
4821 ///
4822 /// # Semantics — resolver hop + derived-nullary-boolean
4823 ///
4824 /// `point_is_diffusive()` returns `true` iff
4825 /// `self.resolved_classification().point_is_diffusive()`. The
4826 /// resolver returns the authored [`Classification`] when present
4827 /// and the substrate default [`Classification::gate_compute`] on
4828 /// absence. Because [`Classification::gate_compute`] carries
4829 /// [`crate::classification::ConvergencePointType::Gate`] (a
4830 /// convergent barrier, not a fan-out), a bare ephemeral spec with
4831 /// no `:classification` slot answers `false`. A regression that
4832 /// dropped the resolver hop, probed the wrong closed-set arm, or
4833 /// inverted the projection fails HERE at ONE narrow substrate
4834 /// site before drifting through every unadorned ephemeral spec's
4835 /// DAG-composition answer.
4836 ///
4837 /// # Compounding — first ephemeral-surface corner-peer mutex on the `point_type` axis
4838 ///
4839 /// The ephemeral require-tag classifier composes this primitive
4840 /// as a fixed tag `diffusive-point` on `EPHEMERAL_FIXED_TAG_ARMS`
4841 /// — byte-for-byte peer of the point surface's `diffusive-point`
4842 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4843 /// [`Classification::point_is_diffusive`] directly. The two-
4844 /// surface parity contract holds by construction: both surfaces
4845 /// route through the SAME
4846 /// [`Classification::point_is_diffusive`] primitive after the
4847 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
4848 /// surface corner-peer pair on the `point_type` axis (with
4849 /// [`Self::point_is_endomorphic`]) whose two projections carry a
4850 /// non-trivial closed-set-internal MUTEX relationship
4851 /// (`point_is_endomorphic ⇒ ¬point_is_diffusive`), distinct from
4852 /// the sibling `data`-axis ephemeral corner-peer pair whose two
4853 /// projections carry a non-trivial IMPLICATION relationship. When
4854 /// the third sibling [`Self::point_is_convergent`] lands, the
4855 /// mutex closes into the full three-way XOR partition composed
4856 /// through the resolver-hop layer as a substrate-wide theorem.
4857 ///
4858 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4859 /// preserves proofs; the classification-`point_type`-axis derived-
4860 /// nullary-boolean probe body composes ONE resolver primitive
4861 /// ([`Self::resolved_classification`]) with ONE
4862 /// [`Classification`] primitive
4863 /// ([`Classification::point_is_diffusive`]) so every downstream
4864 /// (`diffusive-point` fixed tags on both surfaces in tatara-check,
4865 /// future DAG composition / edge-cardinality validators, future
4866 /// variant additions on
4867 /// [`crate::classification::ConvergencePointType`]) binds through
4868 /// the SAME `point_is_diffusive()` shape rather than restating
4869 /// either the resolver walk or the closed-set projection
4870 /// composition at the callsite. THEORY.md §VI.1 — generation over
4871 /// composition; a future
4872 /// [`crate::classification::ConvergencePointType`] variant lands
4873 /// at ONE `ALL` entry + ONE `is_diffusive` arm on the closed set
4874 /// and both surfaces pick it up mechanically.
4875 #[must_use]
4876 pub fn point_is_diffusive(&self) -> bool {
4877 self.resolved_classification().point_is_diffusive()
4878 }
4879
4880 /// Derived-boolean predicate — does this ephemeral spec's
4881 /// resolved [`Classification`]'s
4882 /// [`crate::classification::ConvergencePointType`] project to
4883 /// `true` under
4884 /// [`crate::classification::ConvergencePointType::is_convergent`]?
4885 /// Byte-for-byte peer of
4886 /// [`Classification::point_is_convergent`] wrapped through the
4887 /// [`Self::resolved_classification`] resolver so an operator-
4888 /// omitted `:classification` slot on `(defephemeral …)` still
4889 /// answers via the substrate default. The ONE ephemeral-surface
4890 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4891 /// derived-nullary-boolean walk on the N→1 fan-in topology-bucket
4892 /// question over the classification-`point_type` axis.
4893 ///
4894 /// # Eighth derived-nullary-boolean peer on the ephemeral surface
4895 ///
4896 /// Peer of [`Self::horizon_terminates`],
4897 /// [`Self::horizon_requires_metric_axes`],
4898 /// [`Self::calm_requires_coordination`],
4899 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4900 /// [`Self::point_is_endomorphic`], and [`Self::point_is_diffusive`]
4901 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4902 /// bool) shape — the EIGHTH peer overall and the THIRD peer
4903 /// threading the classification-`point_type` axis. Direct-scalar
4904 /// peer of [`Self::point_is_endomorphic`] and
4905 /// [`Self::point_is_diffusive`]: the three compose the SAME
4906 /// resolver hop and the SAME closed-set carrier through the SAME
4907 /// chosen-field baseline discipline, but the answer flips on the
4908 /// baseline — `Gate.is_convergent() = true`, so an ephemeral spec
4909 /// with no `:classification` slot answers `true` HERE (mirror-
4910 /// inverted from the two sibling probes which answer `false`).
4911 /// The resolver-hop shape is byte-identical across all eight
4912 /// peers.
4913 ///
4914 /// # Semantics — resolver hop + derived-nullary-boolean
4915 ///
4916 /// `point_is_convergent()` returns `true` iff
4917 /// `self.resolved_classification().point_is_convergent()`. The
4918 /// resolver returns the authored [`Classification`] when present
4919 /// and the substrate default [`Classification::gate_compute`] on
4920 /// absence. Because [`Classification::gate_compute`] carries
4921 /// [`crate::classification::ConvergencePointType::Gate`] (the
4922 /// canonical convergent barrier), a bare ephemeral spec with no
4923 /// `:classification` slot answers `true` — a regression that
4924 /// dropped the resolver hop, probed the wrong closed-set arm, or
4925 /// inverted the projection fails HERE at ONE narrow substrate
4926 /// site before drifting through every unadorned ephemeral spec's
4927 /// DAG-composition answer.
4928 ///
4929 /// # Compounding — closes the three-way XOR partition on the ephemeral surface
4930 ///
4931 /// The ephemeral require-tag classifier composes this primitive
4932 /// as a fixed tag `convergent-point` on `EPHEMERAL_FIXED_TAG_ARMS`
4933 /// — byte-for-byte peer of the point surface's `convergent-point`
4934 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4935 /// [`Classification::point_is_convergent`] directly. The two-
4936 /// surface parity contract holds by construction: both surfaces
4937 /// route through the SAME
4938 /// [`Classification::point_is_convergent`] primitive after the
4939 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
4940 /// surface peer on the `point_type` axis closing the mutex pair
4941 /// [`Self::point_is_endomorphic`] / [`Self::point_is_diffusive`]
4942 /// into the FULL three-way XOR partition contract composed
4943 /// through the resolver-hop layer as a substrate-wide theorem.
4944 ///
4945 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4946 /// preserves proofs; the classification-`point_type`-axis derived-
4947 /// nullary-boolean probe body composes ONE resolver primitive
4948 /// ([`Self::resolved_classification`]) with ONE
4949 /// [`Classification`] primitive
4950 /// ([`Classification::point_is_convergent`]) so every downstream
4951 /// (`convergent-point` fixed tags on both surfaces in tatara-check,
4952 /// future DAG composition / edge-cardinality validators, future
4953 /// variant additions on
4954 /// [`crate::classification::ConvergencePointType`]) binds through
4955 /// the SAME `point_is_convergent()` shape rather than restating
4956 /// either the resolver walk or the closed-set projection
4957 /// composition at the callsite. THEORY.md §VI.1 — generation over
4958 /// composition; a future
4959 /// [`crate::classification::ConvergencePointType`] variant lands
4960 /// at ONE `ALL` entry + ONE `is_convergent` arm on the closed set
4961 /// and both surfaces pick it up mechanically.
4962 #[must_use]
4963 pub fn point_is_convergent(&self) -> bool {
4964 self.resolved_classification().point_is_convergent()
4965 }
4966
4967 /// Derived-boolean predicate — does this ephemeral spec's
4968 /// resolved [`Classification`]'s
4969 /// [`crate::classification::SubstrateType`] project to `true`
4970 /// under [`crate::classification::SubstrateType::is_resource`]?
4971 /// Byte-for-byte peer of
4972 /// [`Classification::substrate_is_resource`] wrapped through the
4973 /// [`Self::resolved_classification`] resolver so an operator-
4974 /// omitted `:classification` slot on `(defephemeral …)` still
4975 /// answers via the substrate default. The ONE ephemeral-surface
4976 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4977 /// derived-nullary-boolean walk on the resource-plane bucket
4978 /// question over the classification-`substrate` axis.
4979 ///
4980 /// # Ninth derived-nullary-boolean peer on the ephemeral surface
4981 ///
4982 /// Peer of [`Self::horizon_terminates`],
4983 /// [`Self::horizon_requires_metric_axes`],
4984 /// [`Self::calm_requires_coordination`],
4985 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4986 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4987 /// and [`Self::point_is_convergent`] on the ephemeral surface's
4988 /// (resolver-hop × derived-nullary-bool) shape — the NINTH peer
4989 /// overall and the FIRST peer threading the classification-
4990 /// `substrate` axis (the fourth of six classification axes
4991 /// participating on this corner, after `horizon`, `calm`,
4992 /// `data_classification`, and `point_type`). The resolver-hop
4993 /// shape is byte-identical across all nine peers.
4994 ///
4995 /// # Semantics — resolver hop + derived-nullary-boolean
4996 ///
4997 /// `substrate_is_resource()` returns `true` iff
4998 /// `self.resolved_classification().substrate_is_resource()`. The
4999 /// resolver returns the authored [`Classification`] when present
5000 /// and the substrate default [`Classification::gate_compute`] on
5001 /// absence. Because [`Classification::gate_compute`] carries
5002 /// [`crate::classification::SubstrateType::Compute`] (the
5003 /// canonical resource-plane substrate), a bare ephemeral spec
5004 /// with no `:classification` slot answers `true` — a regression
5005 /// that dropped the resolver hop, probed the wrong closed-set
5006 /// arm, or inverted the projection fails HERE at ONE narrow
5007 /// substrate site before drifting through every unadorned
5008 /// ephemeral spec's plane-baseline answer.
5009 ///
5010 /// # Compounding — opens the substrate axis on the ephemeral surface
5011 ///
5012 /// The ephemeral require-tag classifier composes this primitive
5013 /// as a fixed tag `resource-substrate` on
5014 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5015 /// surface's `resource-substrate` fixed tag on
5016 /// `POINT_FIXED_TAG_ARMS` via
5017 /// [`Classification::substrate_is_resource`] directly. The two-
5018 /// surface parity contract holds by construction: both surfaces
5019 /// route through the SAME
5020 /// [`Classification::substrate_is_resource`] primitive after the
5021 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
5022 /// surface peer on the `substrate` axis — future sibling
5023 /// projections [`crate::classification::SubstrateType::is_policy`]
5024 /// and [`crate::classification::SubstrateType::is_telemetry`]
5025 /// compose byte-identically as future tenth + eleventh peers,
5026 /// closing the axis into a proven-repeatable three-peer sub-
5027 /// corner exactly as the `point_type` axis was closed on this
5028 /// surface by
5029 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
5030 ///
5031 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5032 /// preserves proofs; the classification-`substrate`-axis derived-
5033 /// nullary-boolean probe body composes ONE resolver primitive
5034 /// ([`Self::resolved_classification`]) with ONE
5035 /// [`Classification`] primitive
5036 /// ([`Classification::substrate_is_resource`]) so every
5037 /// downstream (`resource-substrate` fixed tags on both surfaces
5038 /// in tatara-check, future plane-baseline / compliance-baseline
5039 /// selectors, future variant additions on
5040 /// [`crate::classification::SubstrateType`]) binds through the
5041 /// SAME `substrate_is_resource()` shape rather than restating
5042 /// either the resolver walk or the closed-set projection
5043 /// composition at the callsite. THEORY.md §VI.1 — generation
5044 /// over composition; a future
5045 /// [`crate::classification::SubstrateType`] variant lands at ONE
5046 /// `ALL` entry + ONE `is_resource` arm on the closed set and
5047 /// both surfaces pick it up mechanically.
5048 #[must_use]
5049 pub fn substrate_is_resource(&self) -> bool {
5050 self.resolved_classification().substrate_is_resource()
5051 }
5052
5053 /// Derived-boolean predicate — does this ephemeral spec's
5054 /// resolved [`Classification`]'s
5055 /// [`crate::classification::SubstrateType`] project to `true`
5056 /// under [`crate::classification::SubstrateType::is_policy`]?
5057 /// Byte-for-byte peer of
5058 /// [`Classification::substrate_is_policy`] wrapped through the
5059 /// [`Self::resolved_classification`] resolver so an operator-
5060 /// omitted `:classification` slot on `(defephemeral …)` still
5061 /// answers via the substrate default. The ONE ephemeral-surface
5062 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
5063 /// derived-nullary-boolean walk on the policy-plane bucket
5064 /// question over the classification-`substrate` axis.
5065 ///
5066 /// # Tenth derived-nullary-boolean peer on the ephemeral surface
5067 ///
5068 /// Peer of [`Self::horizon_terminates`],
5069 /// [`Self::horizon_requires_metric_axes`],
5070 /// [`Self::calm_requires_coordination`],
5071 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
5072 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
5073 /// [`Self::point_is_convergent`], and
5074 /// [`Self::substrate_is_resource`] on the ephemeral surface's
5075 /// (resolver-hop × derived-nullary-bool) shape — the TENTH peer
5076 /// overall and the SECOND peer threading the classification-
5077 /// `substrate` axis, promoting that axis on this surface from a
5078 /// proven-repeatable one-off to a proven-repeatable pair.
5079 /// FIRST ephemeral-surface substrate-axis corner-peer pair
5080 /// carrying a non-trivial closed-set-internal MUTEX relationship
5081 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`), structural
5082 /// twin of the sibling `point_type`-axis MUTEX pair sealed on
5083 /// this surface by
5084 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
5085 /// The resolver-hop shape is byte-identical across all ten peers.
5086 ///
5087 /// # Semantics — resolver hop + derived-nullary-boolean
5088 ///
5089 /// `substrate_is_policy()` returns `true` iff
5090 /// `self.resolved_classification().substrate_is_policy()`. The
5091 /// resolver returns the authored [`Classification`] when present
5092 /// and the substrate default [`Classification::gate_compute`] on
5093 /// absence. Because [`Classification::gate_compute`] carries
5094 /// [`crate::classification::SubstrateType::Compute`] (the
5095 /// canonical resource-plane substrate, NOT a policy plane), a
5096 /// bare ephemeral spec with no `:classification` slot answers
5097 /// `false` — a regression that dropped the resolver hop, probed
5098 /// the wrong closed-set arm, or inverted the projection fails
5099 /// HERE at ONE narrow substrate site before drifting through
5100 /// every unadorned ephemeral spec's plane-baseline answer.
5101 ///
5102 /// # Compounding — second substrate-axis peer on the ephemeral surface
5103 ///
5104 /// The ephemeral require-tag classifier composes this primitive
5105 /// as a fixed tag `policy-substrate` on
5106 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5107 /// surface's `policy-substrate` fixed tag on
5108 /// `POINT_FIXED_TAG_ARMS` via
5109 /// [`Classification::substrate_is_policy`] directly. The two-
5110 /// surface parity contract holds by construction: both surfaces
5111 /// route through the SAME
5112 /// [`Classification::substrate_is_policy`] primitive after the
5113 /// ephemeral surface pays ONE resolver hop. SECOND ephemeral-
5114 /// surface peer on the `substrate` axis — sibling projection
5115 /// [`crate::classification::SubstrateType::is_telemetry`]
5116 /// composes byte-identically as a future eleventh peer, closing
5117 /// the axis into a proven-repeatable three-peer sub-corner
5118 /// exactly as the `point_type` axis was closed on this surface
5119 /// by
5120 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
5121 ///
5122 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5123 /// preserves proofs; the classification-`substrate`-axis derived-
5124 /// nullary-boolean probe body composes ONE resolver primitive
5125 /// ([`Self::resolved_classification`]) with ONE
5126 /// [`Classification`] primitive
5127 /// ([`Classification::substrate_is_policy`]) so every
5128 /// downstream (`policy-substrate` fixed tags on both surfaces
5129 /// in tatara-check, future plane-baseline / compliance-baseline
5130 /// selectors, future variant additions on
5131 /// [`crate::classification::SubstrateType`]) binds through the
5132 /// SAME `substrate_is_policy()` shape rather than restating
5133 /// either the resolver walk or the closed-set projection
5134 /// composition at the callsite. THEORY.md §VI.1 — generation
5135 /// over composition; a future
5136 /// [`crate::classification::SubstrateType`] variant lands at ONE
5137 /// `ALL` entry + ONE `is_policy` arm on the closed set and
5138 /// both surfaces pick it up mechanically.
5139 #[must_use]
5140 pub fn substrate_is_policy(&self) -> bool {
5141 self.resolved_classification().substrate_is_policy()
5142 }
5143
5144 /// Derived-boolean predicate — does this ephemeral spec's
5145 /// resolved [`Classification`]'s
5146 /// [`crate::classification::SubstrateType`] project to `true`
5147 /// under [`crate::classification::SubstrateType::is_telemetry`]?
5148 /// Byte-for-byte peer of
5149 /// [`Classification::substrate_is_telemetry`] wrapped through
5150 /// the [`Self::resolved_classification`] resolver so an operator-
5151 /// omitted `:classification` slot on `(defephemeral …)` still
5152 /// answers via the substrate default. The ONE ephemeral-surface
5153 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
5154 /// derived-nullary-boolean walk on the telemetry-plane bucket
5155 /// question over the classification-`substrate` axis.
5156 ///
5157 /// # Eleventh derived-nullary-boolean peer on the ephemeral surface — CLOSES the substrate axis
5158 ///
5159 /// Peer of [`Self::horizon_terminates`],
5160 /// [`Self::horizon_requires_metric_axes`],
5161 /// [`Self::calm_requires_coordination`],
5162 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
5163 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
5164 /// [`Self::point_is_convergent`], [`Self::substrate_is_resource`],
5165 /// and [`Self::substrate_is_policy`] on the ephemeral surface's
5166 /// (resolver-hop × derived-nullary-bool) shape — the ELEVENTH
5167 /// peer overall and the THIRD peer threading the classification-
5168 /// `substrate` axis. This peer CLOSES the substrate axis on the
5169 /// ephemeral surface into the FULL three-way XOR partition
5170 /// contract `substrate_is_resource ⊕ substrate_is_policy ⊕
5171 /// substrate_is_telemetry` — sealed on this surface by
5172 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
5173 /// the resolver-hop peer of the parent-composed
5174 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`.
5175 /// Structural twin of the sibling `point_type`-axis ternary lift
5176 /// sealed on this surface by
5177 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
5178 /// The resolver-hop shape is byte-identical across all eleven
5179 /// peers.
5180 ///
5181 /// # Semantics — resolver hop + derived-nullary-boolean
5182 ///
5183 /// `substrate_is_telemetry()` returns `true` iff
5184 /// `self.resolved_classification().substrate_is_telemetry()`.
5185 /// The resolver returns the authored [`Classification`] when
5186 /// present and the substrate default [`Classification::gate_compute`]
5187 /// on absence. Because [`Classification::gate_compute`] carries
5188 /// [`crate::classification::SubstrateType::Compute`] (the
5189 /// canonical resource-plane substrate, NOT a telemetry plane),
5190 /// a bare ephemeral spec with no `:classification` slot answers
5191 /// `false` — a regression that dropped the resolver hop, probed
5192 /// the wrong closed-set arm, or inverted the projection fails
5193 /// HERE at ONE narrow substrate site before drifting through
5194 /// every unadorned ephemeral spec's plane-baseline answer.
5195 ///
5196 /// # Compounding — CLOSES the substrate axis on the ephemeral surface
5197 ///
5198 /// The ephemeral require-tag classifier composes this primitive
5199 /// as a fixed tag `telemetry-substrate` on
5200 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5201 /// surface's `telemetry-substrate` fixed tag on
5202 /// `POINT_FIXED_TAG_ARMS` via
5203 /// [`Classification::substrate_is_telemetry`] directly. The two-
5204 /// surface parity contract holds by construction: both surfaces
5205 /// route through the SAME
5206 /// [`Classification::substrate_is_telemetry`] primitive after the
5207 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
5208 /// surface peer on the `substrate` axis — closes the axis into a
5209 /// proven-repeatable three-peer sub-corner exactly as the
5210 /// `point_type` axis was closed on this surface by
5211 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
5212 ///
5213 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5214 /// preserves proofs; the classification-`substrate`-axis derived-
5215 /// nullary-boolean probe body composes ONE resolver primitive
5216 /// ([`Self::resolved_classification`]) with ONE
5217 /// [`Classification`] primitive
5218 /// ([`Classification::substrate_is_telemetry`]) so every
5219 /// downstream (`telemetry-substrate` fixed tags on both surfaces
5220 /// in tatara-check, future plane-baseline / compliance-baseline
5221 /// selectors, future variant additions on
5222 /// [`crate::classification::SubstrateType`]) binds through the
5223 /// SAME `substrate_is_telemetry()` shape rather than restating
5224 /// either the resolver walk or the closed-set projection
5225 /// composition at the callsite. THEORY.md §VI.1 — generation
5226 /// over composition; a future
5227 /// [`crate::classification::SubstrateType`] variant lands at ONE
5228 /// `ALL` entry + ONE `is_telemetry` arm on the closed set and
5229 /// both surfaces pick it up mechanically.
5230 #[must_use]
5231 pub fn substrate_is_telemetry(&self) -> bool {
5232 self.resolved_classification().substrate_is_telemetry()
5233 }
5234
5235 /// Derived-boolean predicate — does this ephemeral spec's
5236 /// resolved [`Classification`]'s
5237 /// [`crate::classification::CalmClassification`] project to `true`
5238 /// under [`crate::classification::CalmClassification::is_monotone`]?
5239 /// Byte-for-byte peer of [`Classification::calm_is_monotone`]
5240 /// wrapped through the [`Self::resolved_classification`] resolver
5241 /// so an operator-omitted `:classification` slot on
5242 /// `(defephemeral …)` still answers via the substrate default.
5243 /// The ONE ephemeral-surface substrate primitive that owns the
5244 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5245 /// CALM-monotone-plane question — the positive framing peer of
5246 /// [`Self::calm_requires_coordination`].
5247 ///
5248 /// # Twelfth derived-nullary-boolean peer on the ephemeral surface — CLOSES the calm axis
5249 ///
5250 /// Peer of [`Self::horizon_terminates`],
5251 /// [`Self::horizon_requires_metric_axes`],
5252 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5253 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5254 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5255 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5256 /// and [`Self::substrate_is_telemetry`] on the ephemeral
5257 /// surface's (resolver-hop × derived-nullary-bool) shape — the
5258 /// TWELFTH peer overall and the SECOND peer threading the
5259 /// classification-`calm` axis. This peer CLOSES the calm axis
5260 /// on the ephemeral surface into the FULL binary XOR partition
5261 /// contract `calm_is_monotone ⊕ calm_requires_coordination` —
5262 /// sealed on this surface by
5263 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
5264 /// the resolver-hop peer of the parent-composed
5265 /// `classification_calm_probes_form_binary_xor_partition_over_all`.
5266 /// Structural twin of the sibling horizon-axis binary XOR
5267 /// sealed on the closed set by
5268 /// `horizon_kind_terminate_xor_requires_metric_axes`, lifted
5269 /// through the resolver hop to the ephemeral surface. The
5270 /// resolver-hop shape is byte-identical across all twelve peers.
5271 ///
5272 /// # Semantics — resolver hop + derived-nullary-boolean
5273 ///
5274 /// `calm_is_monotone()` returns `true` iff
5275 /// `self.resolved_classification().calm_is_monotone()`. The
5276 /// resolver returns the authored [`Classification`] when present
5277 /// and the substrate default [`Classification::gate_compute`] on
5278 /// absence. Because [`Classification::gate_compute`] carries
5279 /// [`crate::classification::CalmClassification::default =
5280 /// Monotone`] via `#[default]`, a bare ephemeral spec with no
5281 /// `:classification` slot answers `true` — every unadorned
5282 /// `(defephemeral …)` reads as gossip-eligible under the
5283 /// positive CALM framing, safe under Hellerstein's theorem
5284 /// (monotone operations distribute without coordination). A
5285 /// regression that dropped the resolver hop, probed the wrong
5286 /// closed-set arm, or inverted the projection fails HERE at ONE
5287 /// narrow substrate site before drifting through every
5288 /// unadorned ephemeral spec's positive-CALM-framing answer.
5289 /// Mirror-inverted from the sibling
5290 /// `calm_requires_coordination_probes_false_on_absent_classification`
5291 /// (both walk the SAME defaulted `calm` field, so
5292 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
5293 /// closed set's disjoint XOR partition).
5294 ///
5295 /// # Compounding — CLOSES the calm axis on the ephemeral surface
5296 ///
5297 /// The ephemeral require-tag classifier composes this primitive
5298 /// as a fixed tag `monotone-calm` on `EPHEMERAL_FIXED_TAG_ARMS`
5299 /// — byte-for-byte peer of the point surface's `monotone-calm`
5300 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
5301 /// [`Classification::calm_is_monotone`] directly. The two-
5302 /// surface parity contract holds by construction: both surfaces
5303 /// route through the SAME [`Classification::calm_is_monotone`]
5304 /// primitive after the ephemeral surface pays ONE resolver hop.
5305 /// SECOND ephemeral-surface peer on the `calm` axis — CLOSES the
5306 /// axis into a proven-repeatable two-peer sub-corner exactly as
5307 /// the `horizon` axis is closed on the closed-set layer by
5308 /// `horizon_kind_terminate_xor_requires_metric_axes`.
5309 ///
5310 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5311 /// preserves proofs; the classification-`calm`-axis derived-
5312 /// nullary-boolean probe body composes ONE resolver primitive
5313 /// ([`Self::resolved_classification`]) with ONE
5314 /// [`Classification`] primitive
5315 /// ([`Classification::calm_is_monotone`]) so every downstream
5316 /// (`monotone-calm` fixed tags on both surfaces in tatara-check,
5317 /// future scheduler / gossip-eligibility validators reading the
5318 /// positive CALM framing, future variant additions on
5319 /// [`crate::classification::CalmClassification`]) binds through
5320 /// the SAME `calm_is_monotone()` shape rather than restating
5321 /// either the resolver walk or the closed-set projection
5322 /// composition at the callsite. THEORY.md §VI.1 — generation
5323 /// over composition; a future
5324 /// [`crate::classification::CalmClassification`] variant lands
5325 /// at ONE `ALL` entry + ONE `is_monotone` arm on the closed set
5326 /// and both surfaces pick it up mechanically.
5327 #[must_use]
5328 pub fn calm_is_monotone(&self) -> bool {
5329 self.resolved_classification().calm_is_monotone()
5330 }
5331
5332 /// Derived-boolean predicate — does this ephemeral spec's
5333 /// resolved [`Classification`]'s
5334 /// [`crate::classification::DataClassification`] project to `true`
5335 /// under [`crate::classification::DataClassification::is_public`]?
5336 /// Byte-for-byte peer of [`Classification::data_is_public`]
5337 /// wrapped through the [`Self::resolved_classification`] resolver
5338 /// so an operator-omitted `:classification` slot on
5339 /// `(defephemeral …)` still answers via the substrate default.
5340 /// The ONE ephemeral-surface substrate primitive that owns the
5341 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5342 /// freely-distributable-data question — the positive framing peer
5343 /// of [`Self::data_is_restricted`].
5344 ///
5345 /// # Thirteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the data axis
5346 ///
5347 /// Peer of [`Self::horizon_terminates`],
5348 /// [`Self::horizon_requires_metric_axes`],
5349 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5350 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5351 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5352 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5353 /// [`Self::substrate_is_telemetry`], and [`Self::calm_is_monotone`]
5354 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
5355 /// shape — the THIRTEENTH peer overall and the THIRD peer
5356 /// threading the classification-`data_classification` axis. This
5357 /// peer CLOSES the data axis on the ephemeral surface into the
5358 /// FULL binary XOR partition contract
5359 /// `data_is_public ⊕ data_is_restricted` — sealed on this surface
5360 /// by `ephemeral_data_probes_form_binary_xor_partition_over_all`,
5361 /// the resolver-hop peer of the parent-composed
5362 /// `classification_data_probes_form_binary_xor_partition_over_all`.
5363 /// Structural twin of the sibling calm-axis binary XOR sealed on
5364 /// this surface by
5365 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
5366 /// lifted through the resolver hop from the six-variant data-axis
5367 /// closed set to the ephemeral surface. The resolver-hop shape is
5368 /// byte-identical across all thirteen peers.
5369 ///
5370 /// # Semantics — resolver hop + derived-nullary-boolean
5371 ///
5372 /// `data_is_public()` returns `true` iff
5373 /// `self.resolved_classification().data_is_public()`. The
5374 /// resolver returns the authored [`Classification`] when present
5375 /// and the substrate default [`Classification::gate_compute`] on
5376 /// absence. Because [`Classification::gate_compute`] carries
5377 /// [`crate::classification::DataClassification::default =
5378 /// Internal`] via `#[default]`, a bare ephemeral spec with no
5379 /// `:classification` slot answers `false` — every unadorned
5380 /// `(defephemeral …)` reads as access-controlled by default (safe
5381 /// under compliance baseline: an operator must deliberately opt
5382 /// the dataset into public distribution rather than the substrate
5383 /// silently promoting an unadorned Process onto the freely-
5384 /// distributable path). A regression that dropped the resolver
5385 /// hop, probed the wrong closed-set arm, or inverted the
5386 /// projection fails HERE at ONE narrow substrate site before
5387 /// drifting through every unadorned ephemeral spec's positive-
5388 /// distribution-framing answer. Mirror-inverted from the sibling
5389 /// `data_is_restricted_probes_true_on_absent_classification`
5390 /// (both walk the SAME defaulted `data_classification` field, so
5391 /// `is_restricted = true` ⇒ `is_public = false` on the closed
5392 /// set's disjoint XOR partition).
5393 ///
5394 /// # Compounding — CLOSES the data axis on the ephemeral surface
5395 ///
5396 /// The ephemeral require-tag classifier composes this primitive
5397 /// as a fixed tag `public-data` on `EPHEMERAL_FIXED_TAG_ARMS`
5398 /// — byte-for-byte peer of the point surface's `public-data`
5399 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
5400 /// [`Classification::data_is_public`] directly. The two-
5401 /// surface parity contract holds by construction: both surfaces
5402 /// route through the SAME [`Classification::data_is_public`]
5403 /// primitive after the ephemeral surface pays ONE resolver hop.
5404 /// THIRD ephemeral-surface peer on the `data_classification` axis
5405 /// — CLOSES the axis into a proven-repeatable three-peer sub-
5406 /// corner (data_is_regulated, data_is_restricted, data_is_public)
5407 /// whose complementary XOR partition seals on the closed set by
5408 /// `data_classification_public_xor_restricted` and composes
5409 /// through the resolver hop as a substrate-wide theorem.
5410 ///
5411 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5412 /// preserves proofs; the classification-`data_classification`-axis
5413 /// derived-nullary-boolean probe body composes ONE resolver
5414 /// primitive ([`Self::resolved_classification`]) with ONE
5415 /// [`Classification`] primitive
5416 /// ([`Classification::data_is_public`]) so every downstream
5417 /// (`public-data` fixed tags on both surfaces in tatara-check,
5418 /// future compliance-baseline / audit-log-optional validators
5419 /// reading the positive distribution framing, future variant
5420 /// additions on
5421 /// [`crate::classification::DataClassification`]) binds through
5422 /// the SAME `data_is_public()` shape rather than restating either
5423 /// the resolver walk or the closed-set projection composition at
5424 /// the callsite. THEORY.md §VI.1 — generation over composition; a
5425 /// future [`crate::classification::DataClassification`] variant
5426 /// lands at ONE `ALL` entry + ONE `is_public` arm on the closed
5427 /// set and both surfaces pick it up mechanically.
5428 #[must_use]
5429 pub fn data_is_public(&self) -> bool {
5430 self.resolved_classification().data_is_public()
5431 }
5432
5433 /// Derived-boolean predicate — does this ephemeral spec's resolved
5434 /// [`Classification`]'s
5435 /// [`crate::classification::Horizon::direction`] slot (defaulted
5436 /// through [`crate::classification::OptimizationDirection::default =
5437 /// Minimize`] on absence) project to `true` under
5438 /// [`crate::classification::OptimizationDirection::prefers_lower`]?
5439 /// Byte-for-byte peer of
5440 /// [`crate::classification::Classification::direction_prefers_lower`]
5441 /// wrapped through the [`Self::resolved_classification`] resolver so
5442 /// an operator-omitted `:classification` slot on
5443 /// `(defephemeral …)` still answers via the substrate default. The
5444 /// ONE ephemeral-surface substrate primitive that owns the
5445 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5446 /// lower-is-better optimization-polarity question.
5447 ///
5448 /// # Fourteenth derived-nullary-boolean peer on the ephemeral surface — opens the optimization-direction axis
5449 ///
5450 /// Peer of the thirteen prior nullary-boolean substrate primitives
5451 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5452 /// [`Self::horizon_requires_metric_axes`],
5453 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5454 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5455 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5456 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5457 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5458 /// [`Self::data_is_public`]) on the ephemeral surface's
5459 /// (resolver-hop × derived-nullary-bool) shape — the FOURTEENTH
5460 /// peer overall and the FIRST peer threading the classification-
5461 /// `horizon.direction` axis on this surface. Opens the SIXTH
5462 /// classification axis into the ephemeral fixed-tag algebra after
5463 /// the horizon, calm, data, point, and substrate axes. The
5464 /// resolver-hop shape is byte-identical across all fourteen peers.
5465 ///
5466 /// # Semantics — resolver hop + derived-nullary-boolean
5467 ///
5468 /// `direction_prefers_lower()` returns `true` iff
5469 /// `self.resolved_classification().direction_prefers_lower()`. The
5470 /// resolver returns the authored [`Classification`] when present
5471 /// and the substrate default [`Classification::gate_compute`] on
5472 /// absence. Because [`Classification::gate_compute`] carries
5473 /// `horizon: Horizon::default()` whose `direction` field is `None`,
5474 /// and [`crate::classification::OptimizationDirection::default =
5475 /// Minimize`] projects `prefers_lower = true`, a bare ephemeral
5476 /// spec with no `:classification` slot answers `true` — every
5477 /// unadorned `(defephemeral …)` reads as lower-is-better under the
5478 /// substrate polarity default (safe under the asymptotic-health
5479 /// rate-window evaluator's convention: an operator must
5480 /// deliberately opt into Maximize polarity rather than the
5481 /// substrate silently flipping every unadorned Process onto the
5482 /// higher-is-better path). A regression that dropped the resolver
5483 /// hop, probed the wrong closed-set arm, or inverted the projection
5484 /// fails HERE at ONE narrow substrate site before drifting through
5485 /// every unadorned ephemeral spec's rate-window evaluator polarity.
5486 ///
5487 /// # Compounding — opens the optimization-direction axis on the ephemeral surface
5488 ///
5489 /// The ephemeral require-tag classifier composes this primitive as
5490 /// a fixed tag `prefers-lower-direction` on
5491 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5492 /// surface's `prefers-lower-direction` fixed tag on
5493 /// `POINT_FIXED_TAG_ARMS` via
5494 /// [`Classification::direction_prefers_lower`] directly. The
5495 /// two-surface parity contract holds by construction: both surfaces
5496 /// route through the SAME [`Classification::direction_prefers_lower`]
5497 /// primitive after the ephemeral surface pays ONE resolver hop.
5498 /// A future antisymmetric peer (`direction_prefers_higher`) closes
5499 /// the binary XOR partition on this axis — mirror of the calm-axis
5500 /// (`monotone-calm ⊕ coordination-required`) and data-axis
5501 /// (`public-data ⊕ data-restricted`) closures on this surface.
5502 ///
5503 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5504 /// preserves proofs; the classification-`horizon.direction`-axis
5505 /// derived-nullary-boolean probe body composes ONE resolver
5506 /// primitive ([`Self::resolved_classification`]) with ONE
5507 /// [`Classification`] primitive
5508 /// ([`Classification::direction_prefers_lower`]) so every
5509 /// downstream (the `prefers-lower-direction` fixed tags on both
5510 /// surfaces in tatara-check, future asymptotic-health rate-window
5511 /// / regression-detector evaluators, future variant additions on
5512 /// [`crate::classification::OptimizationDirection`]) binds through
5513 /// the SAME `direction_prefers_lower()` shape rather than restating
5514 /// either the resolver walk or the closed-set projection
5515 /// composition at the callsite. THEORY.md §VI.1 — generation over
5516 /// composition; a future
5517 /// [`crate::classification::OptimizationDirection`] variant lands
5518 /// at ONE `ALL` entry + ONE `prefers_lower` arm on the closed set
5519 /// and both surfaces pick it up mechanically.
5520 #[must_use]
5521 pub fn direction_prefers_lower(&self) -> bool {
5522 self.resolved_classification().direction_prefers_lower()
5523 }
5524
5525 /// POSITIVE-FRAMING PEER of [`Self::direction_prefers_lower`] —
5526 /// does this ephemeral spec's resolved [`Classification`]'s
5527 /// [`crate::classification::Horizon::direction`] slot (defaulted
5528 /// through [`crate::classification::OptimizationDirection::default =
5529 /// Minimize`] on absence) project to `true` under
5530 /// [`crate::classification::OptimizationDirection::prefers_higher`]?
5531 /// Byte-for-byte peer of
5532 /// [`crate::classification::Classification::direction_prefers_higher`]
5533 /// wrapped through the [`Self::resolved_classification`] resolver
5534 /// so an operator-omitted `:classification` slot on
5535 /// `(defephemeral …)` still answers via the substrate default. The
5536 /// ONE ephemeral-surface substrate primitive that owns the
5537 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5538 /// higher-is-better optimization-polarity question.
5539 ///
5540 /// # Fifteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the optimization-direction axis
5541 ///
5542 /// Peer of the fourteen prior nullary-boolean substrate primitives
5543 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5544 /// [`Self::horizon_requires_metric_axes`],
5545 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5546 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5547 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5548 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5549 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5550 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`]) on
5551 /// the ephemeral surface's (resolver-hop × derived-nullary-bool)
5552 /// shape — the FIFTEENTH peer overall and the SECOND peer
5553 /// threading the classification-`horizon.direction` axis on this
5554 /// surface. CLOSES the SIXTH classification axis into a binary XOR
5555 /// partition on the ephemeral surface after the horizon, calm,
5556 /// data, point, and substrate axes — completing the axis-coverage
5557 /// milestone on this surface: ALL SIX classification axes now
5558 /// have their partitions closed at the ephemeral-surface derived-
5559 /// nullary corner. The resolver-hop shape is byte-identical across
5560 /// all fifteen peers.
5561 ///
5562 /// # Semantics — resolver hop + derived-nullary-boolean
5563 ///
5564 /// `direction_prefers_higher()` returns `true` iff
5565 /// `self.resolved_classification().direction_prefers_higher()`.
5566 /// The resolver returns the authored [`Classification`] when
5567 /// present and the substrate default
5568 /// [`Classification::gate_compute`] on absence. Because
5569 /// [`Classification::gate_compute`] carries `horizon:
5570 /// Horizon::default()` whose `direction` field is `None`, and
5571 /// [`crate::classification::OptimizationDirection::default =
5572 /// Minimize`] projects `prefers_higher = false`, a bare ephemeral
5573 /// spec with no `:classification` slot answers `false` — every
5574 /// unadorned `(defephemeral …)` reads as lower-is-better under the
5575 /// substrate polarity default (safe under the asymptotic-health
5576 /// rate-window evaluator's convention: an operator must
5577 /// deliberately opt into Maximize polarity rather than the
5578 /// substrate silently flipping every unadorned Process onto the
5579 /// higher-is-better path). A regression that dropped the resolver
5580 /// hop, probed the wrong closed-set arm, or inverted the
5581 /// projection fails HERE at ONE narrow substrate site before
5582 /// drifting through every unadorned ephemeral spec's rate-window
5583 /// evaluator polarity.
5584 ///
5585 /// # Compounding — CLOSES the optimization-direction axis on the ephemeral surface
5586 ///
5587 /// The ephemeral require-tag classifier composes this primitive as
5588 /// a fixed tag `prefers-higher-direction` on
5589 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5590 /// surface's `prefers-higher-direction` fixed tag on
5591 /// `POINT_FIXED_TAG_ARMS` via
5592 /// [`Classification::direction_prefers_higher`] directly. The
5593 /// two-surface parity contract holds by construction: both
5594 /// surfaces route through the SAME
5595 /// [`Classification::direction_prefers_higher`] primitive after
5596 /// the ephemeral surface pays ONE resolver hop. SECOND
5597 /// optimization-direction-axis peer CLOSES the axis into the FULL
5598 /// binary XOR partition contract on this surface — the resolver-
5599 /// hop peer of the parent-composed
5600 /// `classification_direction_probes_form_binary_xor_partition_over_all`,
5601 /// mirror of the calm-axis (`monotone-calm ⊕ coordination-required`)
5602 /// and data-axis (`public-data ⊕ data-restricted`) closures on
5603 /// this surface.
5604 ///
5605 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5606 /// preserves proofs; the classification-`horizon.direction`-axis
5607 /// derived-nullary-boolean probe body composes ONE resolver
5608 /// primitive ([`Self::resolved_classification`]) with ONE
5609 /// [`Classification`] primitive
5610 /// ([`Classification::direction_prefers_higher`]) so every
5611 /// downstream (the `prefers-higher-direction` fixed tags on both
5612 /// surfaces in tatara-check, future asymptotic-health rate-window
5613 /// / regression-detector evaluators, future variant additions on
5614 /// [`crate::classification::OptimizationDirection`]) binds through
5615 /// the SAME `direction_prefers_higher()` shape rather than
5616 /// restating either the resolver walk or the closed-set projection
5617 /// composition at the callsite. THEORY.md §VI.1 — generation over
5618 /// composition; a future
5619 /// [`crate::classification::OptimizationDirection`] variant lands
5620 /// at ONE `ALL` entry + ONE `prefers_higher` arm on the closed set
5621 /// and both surfaces pick it up mechanically.
5622 #[must_use]
5623 pub fn direction_prefers_higher(&self) -> bool {
5624 self.resolved_classification().direction_prefers_higher()
5625 }
5626
5627 /// Derived-boolean predicate — does this ephemeral spec's resolved
5628 /// [`Classification`]'s `point_type` slot project to `Arity::One`
5629 /// under
5630 /// [`crate::classification::ConvergencePointType::input_arity`]?
5631 /// Byte-for-byte peer of
5632 /// [`crate::classification::Classification::input_arity_is_one`]
5633 /// wrapped through the [`Self::resolved_classification`] resolver
5634 /// so an operator-omitted `:classification` slot on
5635 /// `(defephemeral …)` still answers via the substrate default. The
5636 /// ONE ephemeral-surface substrate primitive that owns the
5637 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5638 /// single-input side of the DAG-composition input-arity projection.
5639 ///
5640 /// # Sixteenth derived-nullary-boolean peer on the ephemeral surface — opens the input-arity axis
5641 ///
5642 /// Peer of the fifteen prior nullary-boolean substrate primitives
5643 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5644 /// [`Self::horizon_requires_metric_axes`],
5645 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5646 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5647 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5648 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5649 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5650 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5651 /// [`Self::direction_prefers_higher`]) on the ephemeral surface's
5652 /// (resolver-hop × derived-nullary-bool) shape — the SIXTEENTH
5653 /// peer overall and the FIRST peer threading the classification-
5654 /// `point_type`-derived input-arity axis on this surface. Opens
5655 /// the SEVENTH classification axis into the ephemeral fixed-tag
5656 /// algebra after the horizon, calm, data, point-type, substrate,
5657 /// and optimization-direction axes. First peer on the derived-
5658 /// typed-projection stratum of the ephemeral surface — composes
5659 /// an extra closed-set-level projection hop
5660 /// ([`crate::classification::ConvergencePointType::input_arity`])
5661 /// compared to the sibling `point_is_*` triple that walks the raw
5662 /// `point_type` slot through the resolver. The resolver-hop shape
5663 /// is byte-identical across all sixteen peers.
5664 ///
5665 /// # Semantics — resolver hop + derived-nullary-boolean
5666 ///
5667 /// `input_arity_is_one()` returns `true` iff
5668 /// `self.resolved_classification().input_arity_is_one()`. The
5669 /// resolver returns the authored [`Classification`] when present
5670 /// and the substrate default [`Classification::gate_compute`] on
5671 /// absence. Because [`Classification::gate_compute`] carries
5672 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
5673 /// ephemeral spec with no `:classification` slot answers `false` —
5674 /// every unadorned `(defephemeral …)` lands in the multi-input
5675 /// bucket under the substrate default (`Gate` gates a
5676 /// many-to-one bucket dispatch, so the single-input bucket only
5677 /// applies to operator-authored specs on the `Transform | Fork |
5678 /// Broadcast | Observe` arms). A regression that dropped the
5679 /// resolver hop, probed the wrong closed-set arm, or crossed the
5680 /// wires with the sibling
5681 /// [`crate::classification::ConvergencePointType::output_arity`]
5682 /// projection (which disagrees on six of the eight variants) fails
5683 /// HERE at ONE narrow substrate site before drifting through
5684 /// every unadorned ephemeral spec's DAG-composition input-arity
5685 /// audit.
5686 ///
5687 /// # Compounding — opens the input-arity axis on the ephemeral surface
5688 ///
5689 /// The ephemeral require-tag classifier will compose this
5690 /// primitive as a fixed tag `single-input-arity` on
5691 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5692 /// surface's `single-input-arity` fixed tag on
5693 /// `POINT_FIXED_TAG_ARMS` via
5694 /// [`Classification::input_arity_is_one`] directly. The
5695 /// two-surface parity contract holds by construction: both
5696 /// surfaces route through the SAME
5697 /// [`Classification::input_arity_is_one`] primitive after the
5698 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
5699 /// peer ([`Self::input_arity_is_many`]) closes the binary XOR
5700 /// partition on this axis — mirror of the calm-axis
5701 /// (`monotone-calm ⊕ coordination-required`), data-axis
5702 /// (`public-data ⊕ data-restricted`), and optimization-direction-
5703 /// axis (`prefers-lower-direction ⊕ prefers-higher-direction`)
5704 /// closures on this surface.
5705 ///
5706 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5707 /// preserves proofs; the classification-`point_type`-derived
5708 /// input-arity-axis derived-nullary-boolean probe body composes
5709 /// ONE resolver primitive ([`Self::resolved_classification`])
5710 /// with ONE [`Classification`] primitive
5711 /// ([`Classification::input_arity_is_one`]) so every downstream
5712 /// (the future `single-input-arity` fixed tag on the ephemeral
5713 /// surface in tatara-check, future DAG-composition input-arity
5714 /// validators keying on the single-input framing, future variant
5715 /// additions on
5716 /// [`crate::classification::ConvergencePointType`]) binds through
5717 /// the SAME `input_arity_is_one()` shape rather than restating
5718 /// either the resolver walk or the two-hop closed-set projection
5719 /// composition at the callsite. THEORY.md §VI.1 — generation over
5720 /// composition; a future
5721 /// [`crate::classification::ConvergencePointType`] variant lands
5722 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
5723 /// and both surfaces pick it up mechanically.
5724 #[must_use]
5725 pub fn input_arity_is_one(&self) -> bool {
5726 self.resolved_classification().input_arity_is_one()
5727 }
5728
5729 /// ANTISYMMETRIC PEER of [`Self::input_arity_is_one`] — does
5730 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
5731 /// slot project to `Arity::Many` under
5732 /// [`crate::classification::ConvergencePointType::input_arity`]?
5733 /// Byte-for-byte peer of
5734 /// [`crate::classification::Classification::input_arity_is_many`]
5735 /// wrapped through the [`Self::resolved_classification`] resolver
5736 /// so an operator-omitted `:classification` slot on
5737 /// `(defephemeral …)` still answers via the substrate default. The
5738 /// ONE ephemeral-surface substrate primitive that owns the
5739 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5740 /// multi-input side of the DAG-composition input-arity projection.
5741 ///
5742 /// # Seventeenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the input-arity axis
5743 ///
5744 /// Peer of the sixteen prior nullary-boolean substrate primitives
5745 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5746 /// [`Self::horizon_requires_metric_axes`],
5747 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5748 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5749 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5750 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5751 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5752 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5753 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`])
5754 /// on the ephemeral surface's (resolver-hop × derived-nullary-
5755 /// bool) shape — the SEVENTEENTH peer overall and the SECOND peer
5756 /// threading the classification-`point_type`-derived input-arity
5757 /// axis on this surface. CLOSES the SEVENTH classification axis
5758 /// into the FULL binary XOR partition contract
5759 /// `input_arity_is_one ⊕ input_arity_is_many` on the ephemeral
5760 /// surface — the resolver-hop peer of the parent-composed
5761 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`.
5762 /// The resolver-hop shape is byte-identical across all seventeen
5763 /// peers.
5764 ///
5765 /// # Semantics — resolver hop + derived-nullary-boolean
5766 ///
5767 /// `input_arity_is_many()` returns `true` iff
5768 /// `self.resolved_classification().input_arity_is_many()`. The
5769 /// resolver returns the authored [`Classification`] when present
5770 /// and the substrate default [`Classification::gate_compute`] on
5771 /// absence. Because [`Classification::gate_compute`] carries
5772 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
5773 /// ephemeral spec with no `:classification` slot answers `true` —
5774 /// every unadorned `(defephemeral …)` lands in the multi-input
5775 /// bucket under the substrate default. Direct antisymmetric
5776 /// mirror of [`Self::input_arity_is_one`] on the SAME resolver
5777 /// walk + SAME projection through the SAME closed set.
5778 ///
5779 /// # Compounding — CLOSES the input-arity axis on the ephemeral surface
5780 ///
5781 /// The ephemeral require-tag classifier will compose this
5782 /// primitive as a fixed tag `multi-input-arity` on
5783 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5784 /// surface's `multi-input-arity` fixed tag on
5785 /// `POINT_FIXED_TAG_ARMS` via
5786 /// [`Classification::input_arity_is_many`] directly. The
5787 /// two-surface parity contract holds by construction: both
5788 /// surfaces route through the SAME
5789 /// [`Classification::input_arity_is_many`] primitive after the
5790 /// ephemeral surface pays ONE resolver hop. SECOND input-arity-
5791 /// axis peer CLOSES the axis into the FULL binary XOR partition
5792 /// contract on this surface — the resolver-hop peer of the
5793 /// parent-composed
5794 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`,
5795 /// mirror of the calm-axis (`monotone-calm ⊕
5796 /// coordination-required`), data-axis (`public-data ⊕
5797 /// data-restricted`), and optimization-direction-axis
5798 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
5799 /// closures on this surface — the SEVENTH classification axis to
5800 /// reach the closed XOR partition landmark on the ephemeral
5801 /// resolver-hop surface, opening the derived-typed-projection
5802 /// stratum on this surface for the first time.
5803 ///
5804 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5805 /// preserves proofs; the classification-`point_type`-derived
5806 /// input-arity-axis derived-nullary-boolean probe body composes
5807 /// ONE resolver primitive ([`Self::resolved_classification`])
5808 /// with ONE [`Classification`] primitive
5809 /// ([`Classification::input_arity_is_many`]) so every downstream
5810 /// (the future `multi-input-arity` fixed tag on the ephemeral
5811 /// surface in tatara-check, future DAG-composition input-arity
5812 /// validators keying on the multi-input framing, future variant
5813 /// additions on
5814 /// [`crate::classification::ConvergencePointType`]) binds through
5815 /// the SAME `input_arity_is_many()` shape rather than restating
5816 /// either `!self.input_arity_is_one()` or the two-hop
5817 /// `self.resolved_classification().point_type.input_arity().is_many()`
5818 /// chain at each callsite. THEORY.md §VI.1 — generation over
5819 /// composition; a future
5820 /// [`crate::classification::ConvergencePointType`] variant lands
5821 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
5822 /// and both surfaces pick it up mechanically.
5823 #[must_use]
5824 pub fn input_arity_is_many(&self) -> bool {
5825 self.resolved_classification().input_arity_is_many()
5826 }
5827
5828 /// Derived-boolean predicate — does this ephemeral spec's resolved
5829 /// [`Classification`]'s `point_type` slot project to `Arity::One`
5830 /// under
5831 /// [`crate::classification::ConvergencePointType::output_arity`]?
5832 /// Byte-for-byte peer of
5833 /// [`crate::classification::Classification::output_arity_is_one`]
5834 /// wrapped through the [`Self::resolved_classification`] resolver
5835 /// so an operator-omitted `:classification` slot on
5836 /// `(defephemeral …)` still answers via the substrate default. The
5837 /// ONE ephemeral-surface substrate primitive that owns the
5838 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5839 /// single-output side of the DAG-composition output-arity projection.
5840 ///
5841 /// # Eighteenth derived-nullary-boolean peer on the ephemeral surface — opens the output-arity axis
5842 ///
5843 /// Peer of the seventeen prior nullary-boolean substrate primitives
5844 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5845 /// [`Self::horizon_requires_metric_axes`],
5846 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5847 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5848 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5849 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5850 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5851 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5852 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
5853 /// [`Self::input_arity_is_many`]) on the ephemeral surface's
5854 /// (resolver-hop × derived-nullary-bool) shape — the EIGHTEENTH
5855 /// peer overall and the FIRST peer threading the classification-
5856 /// `point_type`-derived OUTPUT-arity axis on this surface. Opens
5857 /// the EIGHTH classification axis into the ephemeral fixed-tag
5858 /// algebra after the horizon, calm, data, point-type, substrate,
5859 /// optimization-direction, and input-arity axes. SECOND peer on
5860 /// the derived-typed-projection stratum of the ephemeral surface
5861 /// (after [`Self::input_arity_is_one`]) — composes an extra
5862 /// closed-set-level projection hop
5863 /// ([`crate::classification::ConvergencePointType::output_arity`])
5864 /// compared to the sibling `point_is_*` triple that walks the raw
5865 /// `point_type` slot through the resolver. The resolver-hop shape
5866 /// is byte-identical across all eighteen peers.
5867 ///
5868 /// # Distinctness from the input-arity axis
5869 ///
5870 /// The input-arity and output-arity axes carve the eight-variant
5871 /// [`crate::classification::ConvergencePointType`] closed set into
5872 /// DISTINCT partitions — six of the eight variants (`Fork |
5873 /// Broadcast | Join | Gate | Select | Reduce`) DISAGREE between the
5874 /// two projections, and only the two endomorphic variants
5875 /// (`Transform | Observe` — both `(One, One)`) agree. The ephemeral
5876 /// resolver-hop surface inherits this distinctness verbatim: the
5877 /// absent-classification baseline (`gate_compute` → `point_type:
5878 /// Gate`) FLIPS between the two axes — `input_arity_is_one` is
5879 /// `false` on the baseline but `output_arity_is_one` is `true`.
5880 /// So `output_arity_is_one` is NOT a redundant restatement of
5881 /// `input_arity_is_one` even after both wrap through the SAME
5882 /// resolver.
5883 ///
5884 /// # Semantics — resolver hop + derived-nullary-boolean
5885 ///
5886 /// `output_arity_is_one()` returns `true` iff
5887 /// `self.resolved_classification().output_arity_is_one()`. The
5888 /// resolver returns the authored [`Classification`] when present
5889 /// and the substrate default [`Classification::gate_compute`] on
5890 /// absence. Because [`Classification::gate_compute`] carries
5891 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5892 /// ephemeral spec with no `:classification` slot answers `true` —
5893 /// every unadorned `(defephemeral …)` lands in the single-output
5894 /// bucket under the substrate default (`Gate` gates a many-to-one
5895 /// bucket dispatch, so the multi-output bucket only applies to
5896 /// operator-authored specs on the `Fork | Broadcast` arms). A
5897 /// regression that dropped the resolver hop, probed the wrong
5898 /// closed-set arm, or crossed the wires with the sibling
5899 /// [`crate::classification::ConvergencePointType::input_arity`]
5900 /// projection (which disagrees on six of the eight variants) fails
5901 /// HERE at ONE narrow substrate site before drifting through every
5902 /// unadorned ephemeral spec's DAG-composition output-arity audit.
5903 ///
5904 /// # Compounding — opens the output-arity axis on the ephemeral surface
5905 ///
5906 /// The ephemeral require-tag classifier will compose this
5907 /// primitive as a fixed tag `single-output-arity` on
5908 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5909 /// surface's `single-output-arity` fixed tag on
5910 /// `POINT_FIXED_TAG_ARMS` via
5911 /// [`Classification::output_arity_is_one`] directly. The
5912 /// two-surface parity contract holds by construction: both
5913 /// surfaces route through the SAME
5914 /// [`Classification::output_arity_is_one`] primitive after the
5915 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
5916 /// peer ([`Self::output_arity_is_many`]) closes the binary XOR
5917 /// partition on this axis — mirror of the input-arity-axis
5918 /// (`input_arity_is_one ⊕ input_arity_is_many`), the calm-axis
5919 /// (`monotone-calm ⊕ coordination-required`), the data-axis
5920 /// (`public-data ⊕ data-restricted`), and the optimization-
5921 /// direction-axis (`prefers-lower-direction ⊕
5922 /// prefers-higher-direction`) closures on this surface,
5923 /// completing the DAG-composition arity PAIR on the ephemeral
5924 /// derived-typed-projection stratum.
5925 ///
5926 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5927 /// preserves proofs; the classification-`point_type`-derived
5928 /// output-arity-axis derived-nullary-boolean probe body composes
5929 /// ONE resolver primitive ([`Self::resolved_classification`])
5930 /// with ONE [`Classification`] primitive
5931 /// ([`Classification::output_arity_is_one`]) so every downstream
5932 /// (the future `single-output-arity` fixed tag on the ephemeral
5933 /// surface in tatara-check, future DAG-composition output-arity
5934 /// validators keying on the single-output framing, future variant
5935 /// additions on
5936 /// [`crate::classification::ConvergencePointType`]) binds through
5937 /// the SAME `output_arity_is_one()` shape rather than restating
5938 /// either the resolver walk or the two-hop closed-set projection
5939 /// composition at the callsite. THEORY.md §VI.1 — generation over
5940 /// composition; a future
5941 /// [`crate::classification::ConvergencePointType`] variant lands
5942 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
5943 /// and both surfaces pick it up mechanically.
5944 #[must_use]
5945 pub fn output_arity_is_one(&self) -> bool {
5946 self.resolved_classification().output_arity_is_one()
5947 }
5948
5949 /// ANTISYMMETRIC PEER of [`Self::output_arity_is_one`] — does
5950 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
5951 /// slot project to `Arity::Many` under
5952 /// [`crate::classification::ConvergencePointType::output_arity`]?
5953 /// Byte-for-byte peer of
5954 /// [`crate::classification::Classification::output_arity_is_many`]
5955 /// wrapped through the [`Self::resolved_classification`] resolver
5956 /// so an operator-omitted `:classification` slot on
5957 /// `(defephemeral …)` still answers via the substrate default. The
5958 /// ONE ephemeral-surface substrate primitive that owns the
5959 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5960 /// multi-output side of the DAG-composition output-arity projection.
5961 ///
5962 /// # Nineteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the output-arity axis
5963 ///
5964 /// Peer of the eighteen prior nullary-boolean substrate primitives
5965 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5966 /// [`Self::horizon_requires_metric_axes`],
5967 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5968 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5969 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5970 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5971 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5972 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5973 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
5974 /// [`Self::input_arity_is_many`], [`Self::output_arity_is_one`])
5975 /// on the ephemeral surface's (resolver-hop × derived-nullary-
5976 /// bool) shape — the NINETEENTH peer overall and the SECOND peer
5977 /// threading the classification-`point_type`-derived OUTPUT-arity
5978 /// axis on this surface. CLOSES the EIGHTH classification axis
5979 /// into the FULL binary XOR partition contract
5980 /// `output_arity_is_one ⊕ output_arity_is_many` on the ephemeral
5981 /// surface — the resolver-hop peer of the parent-composed
5982 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`.
5983 /// The resolver-hop shape is byte-identical across all nineteen
5984 /// peers. Completes the DAG-composition arity PAIR on the
5985 /// ephemeral derived-typed-projection stratum
5986 /// (`input_arity_is_{one,many}` + `output_arity_is_{one,many}` on
5987 /// the SAME resolver walk through the SAME closed set).
5988 ///
5989 /// # Semantics — resolver hop + derived-nullary-boolean
5990 ///
5991 /// `output_arity_is_many()` returns `true` iff
5992 /// `self.resolved_classification().output_arity_is_many()`. The
5993 /// resolver returns the authored [`Classification`] when present
5994 /// and the substrate default [`Classification::gate_compute`] on
5995 /// absence. Because [`Classification::gate_compute`] carries
5996 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5997 /// ephemeral spec with no `:classification` slot answers `false` —
5998 /// every unadorned `(defephemeral …)` lands in the single-output
5999 /// bucket under the substrate default. Direct antisymmetric
6000 /// mirror of [`Self::output_arity_is_one`] on the SAME resolver
6001 /// walk + SAME projection through the SAME closed set.
6002 ///
6003 /// # Compounding — CLOSES the output-arity axis on the ephemeral surface
6004 ///
6005 /// The ephemeral require-tag classifier will compose this
6006 /// primitive as a fixed tag `multi-output-arity` on
6007 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
6008 /// surface's `multi-output-arity` fixed tag on
6009 /// `POINT_FIXED_TAG_ARMS` via
6010 /// [`Classification::output_arity_is_many`] directly. The
6011 /// two-surface parity contract holds by construction: both
6012 /// surfaces route through the SAME
6013 /// [`Classification::output_arity_is_many`] primitive after the
6014 /// ephemeral surface pays ONE resolver hop. SECOND output-arity-
6015 /// axis peer CLOSES the axis into the FULL binary XOR partition
6016 /// contract on this surface — the resolver-hop peer of the
6017 /// parent-composed
6018 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`,
6019 /// mirror of the input-arity-axis (`input_arity_is_one ⊕
6020 /// input_arity_is_many`), the calm-axis (`monotone-calm ⊕
6021 /// coordination-required`), the data-axis (`public-data ⊕
6022 /// data-restricted`), and the optimization-direction-axis
6023 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
6024 /// closures on this surface — the EIGHTH classification axis to
6025 /// reach the closed XOR partition landmark on the ephemeral
6026 /// resolver-hop surface, completing the DAG-composition arity
6027 /// PAIR on the derived-typed-projection stratum of this surface.
6028 ///
6029 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
6030 /// preserves proofs; the classification-`point_type`-derived
6031 /// output-arity-axis derived-nullary-boolean probe body composes
6032 /// ONE resolver primitive ([`Self::resolved_classification`])
6033 /// with ONE [`Classification`] primitive
6034 /// ([`Classification::output_arity_is_many`]) so every downstream
6035 /// (the future `multi-output-arity` fixed tag on the ephemeral
6036 /// surface in tatara-check, future DAG-composition output-arity
6037 /// validators keying on the multi-output framing, future variant
6038 /// additions on
6039 /// [`crate::classification::ConvergencePointType`]) binds through
6040 /// the SAME `output_arity_is_many()` shape rather than restating
6041 /// either `!self.output_arity_is_one()` or the two-hop
6042 /// `self.resolved_classification().point_type.output_arity().is_many()`
6043 /// chain at each callsite. THEORY.md §VI.1 — generation over
6044 /// composition; a future
6045 /// [`crate::classification::ConvergencePointType`] variant lands
6046 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
6047 /// and both surfaces pick it up mechanically.
6048 #[must_use]
6049 pub fn output_arity_is_many(&self) -> bool {
6050 self.resolved_classification().output_arity_is_many()
6051 }
6052
6053 /// True iff this ephemeral spec's [`Self::routing`] slot is
6054 /// populated AND the inner [`RoutingSpec`]'s derived
6055 /// [`RoutingForm`] equals `kind` — the substrate primitive that
6056 /// owns the (`&EphemeralSpec`, [`RoutingForm`]) → `bool` presence-
6057 /// probe shape on the sugar-surface type.
6058 ///
6059 /// # Peer to [`crate::routing::RoutingSpec::has_form`]
6060 ///
6061 /// [`RoutingSpec::has_form`] carries the same `(&self, RoutingForm)
6062 /// -> bool` signature on the inner routing carrier reached through
6063 /// the Option gate; this peer composes byte-identical semantics on
6064 /// [`EphemeralSpec`]'s direct `routing: Option<RoutingSpec>` slot,
6065 /// so both surfaces' `routing-form-<kind>` require-tag families
6066 /// route through the SAME `RoutingSpec::has_form` primitive. A
6067 /// future normalization at the probe shape (a widened return
6068 /// carrying the derived [`RoutingForm`] variant, a debug-build
6069 /// assertion on operator-set vs defaulted overrides on the
6070 /// `stable_name_claim` bool, a fleet-wide warn on `Stable`
6071 /// combined with content-hashed hostnames) lands at ONE site per
6072 /// surface and every downstream `routing-form-<kind>` require-tag
6073 /// family + closed-set audit dispatcher picks it up mechanically.
6074 ///
6075 /// # Semantics — Option-gated derived-scalar match
6076 ///
6077 /// [`EphemeralSpec::routing`] is an `Option<RoutingSpec>`: `None`
6078 /// on an in-cluster-only ephemeral env (no per-instance edges
6079 /// declared), `Some(_)` when the operator authored the
6080 /// `:routing (…)` slot. `has_routing_form(kind)` returns `true`
6081 /// iff the slot is `Some(spec)` AND `spec.has_form(kind)` — the
6082 /// Option-parent gate short-circuits `false` on `None` regardless
6083 /// of `kind`, and the reachable arm reads the DERIVED
6084 /// [`RoutingForm`] through the ONE substrate composer
6085 /// [`RoutingForm::from_is_stable`] over the child
6086 /// `stable_name_claim` bool (a `false` default projects to
6087 /// [`RoutingForm::Instance`], a `true` operator override projects
6088 /// to [`RoutingForm::Stable`]).
6089 ///
6090 /// # Corner — (Option-parent × derived-scalar-child)
6091 ///
6092 /// SAME corner as the point surface's `routing-form-<kind>`
6093 /// family (via [`crate::routing::RoutingSpec::has_form`] reached
6094 /// through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`)
6095 /// — both surfaces' Option-parent hop threads through the SAME
6096 /// `Option<RoutingSpec>` field name on their respective sugar
6097 /// structs. The [`From<EphemeralSpec>`] lowering copies
6098 /// `e.routing → ProcessSpec::routing` byte-for-byte at the
6099 /// [`From`] impl in this module (see the `routing: e.routing`
6100 /// line), so the SAME `Option<RoutingSpec>` reaches both
6101 /// surfaces' `routing-form-<kind>` families through the SAME
6102 /// [`RoutingSpec::has_form`] walk. Distinct from
6103 /// [`Self::has_teardown_policy`] on this same surface, which
6104 /// walks a required-scalar-child through no Option-parent hop.
6105 ///
6106 /// # Compounding
6107 ///
6108 /// The ephemeral require-tag classifier composes this primitive
6109 /// with the closed-set `FromStr` autoderived on [`RoutingForm`]
6110 /// through the `strip_and_classify_prefixed_kind` substrate to
6111 /// publish a `routing-form-<kind>` prefix family byte-for-byte
6112 /// symmetrical with the point surface's family via
6113 /// [`crate::routing::RoutingSpec::has_form`]. A future third
6114 /// [`RoutingForm`] variant added to `ALL` (a hypothetical
6115 /// `Anchored` for "hold the claim only for a specific
6116 /// generation") reaches BOTH surfaces' `routing-form-<kind>`
6117 /// prefix families through the SAME closed-set walk with no
6118 /// per-caller edit — the two-surface symmetry means adding a
6119 /// variant on the closed set publishes it in lockstep across
6120 /// every downstream consumer.
6121 ///
6122 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
6123 /// preserves proofs — the Option-gated derived-scalar-carrier
6124 /// presence-probe body lives at ONE substrate site per surface
6125 /// so every downstream (`routing-form-<kind>` require-tag families
6126 /// on both surfaces in tatara-check, closed-set audit dispatchers,
6127 /// future variant additions on [`RoutingForm`]) binds through the
6128 /// SAME `has(kind)` shape rather than restating the
6129 /// `spec.routing.as_ref().is_some_and(|r| r.has_form(kind))`
6130 /// closure body at each call site). THEORY.md §VI.1 (generation
6131 /// over composition — a future variant lands at ONE `ALL` entry +
6132 /// one `as_str` arm on the closed set and the probe picks it up
6133 /// mechanically without further per-consumer edits).
6134 #[must_use]
6135 pub fn has_routing_form(&self, kind: RoutingForm) -> bool {
6136 self.routing.as_ref().is_some_and(|r| r.has_form(kind))
6137 }
6138
6139 /// True iff at least one declared export in `self.exports` would
6140 /// fire on the given terminal-reached [`ProcessPhase`] — the peer
6141 /// of [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6142 /// on the [`EphemeralSpec`] surface.
6143 ///
6144 /// # Semantics — byte-identical to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6145 ///
6146 /// Both surfaces walk the SAME slice-level substrate primitive
6147 /// [`ExportSpecSliceExt::has_applicable_at`] on their respective
6148 /// `Vec<ExportSpec>` slot: [`EphemeralSpec`]'s `exports` field is
6149 /// copied byte-for-byte into `EphemeralLifetime::exports` at the
6150 /// `From<EphemeralSpec>` lowering, so a `has_applicable_exports_at`
6151 /// query on the authored ephemeral spec answers identically to a
6152 /// `has_applicable_exports` query on the lowered `EphemeralLifetime`.
6153 /// A regression at the compound `(when, phase) → fires_on(phase)`
6154 /// walk fails at [`ExportSpecSliceExt::has_applicable_at`]'s tests
6155 /// rather than as silent drift at either surface's inherent method.
6156 ///
6157 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6158 ///
6159 /// Same shape, same axis, same body — the point-domain surface
6160 /// composes through `spec.lifetime.resolved_ephemeral().is_some_and(
6161 /// |e| e.exports.has_applicable_at(phase))`; the ephemeral sugar
6162 /// surface reads `self.exports.has_applicable_at(phase)` directly
6163 /// because `EphemeralSpec` stores `exports: Vec<ExportSpec>` as a
6164 /// top-level field. Both routes bind through THIS ONE slice-level
6165 /// primitive so a future normalization (widening the trigger from
6166 /// a stored discriminator to a computed predicate, adding a phase
6167 /// that composes across multiple trigger arms, threading a
6168 /// per-export justification back for editor tooltips) lands at ONE
6169 /// site and every downstream inherits the shift by construction.
6170 ///
6171 /// # Compounding
6172 ///
6173 /// The ephemeral require-tag classifier composes this primitive
6174 /// with the closed-set [`ProcessPhase`]'s autoderived `FromStr`
6175 /// through the `strip_and_classify_prefixed_kind` substrate to
6176 /// publish an `exports-fire-on-<phase>` closed-set prefix family
6177 /// byte-for-byte symmetrical with the point surface's family via
6178 /// `spec.lifetime.resolved_ephemeral().is_some_and(|e|
6179 /// e.exports.has_applicable_at(phase))`. A future twelfth
6180 /// [`ProcessPhase`] variant reaches BOTH surfaces' prefix families
6181 /// through the ONE [`crate::export::ExportTrigger::fires_on`]
6182 /// exhaustive match — either the new phase inherits a per-trigger
6183 /// fire rule at that single substrate site or it collapses to
6184 /// `false` for every trigger (the current non-terminal tail),
6185 /// without a per-caller edit anywhere else.
6186 ///
6187 /// A future normalization at the compound `(when, phase) →
6188 /// fires_on(phase)` walk (a widening that returns the applicable
6189 /// exports themselves rather than a bool, a debug-build assertion
6190 /// on redundant `Always`-triggered exports coexisting with an
6191 /// `OnAttested` peer, a fleet-wide warn on empty-export ephemerals
6192 /// declaring `OnAttested` postconditions) lands at the ONE
6193 /// slice-level substrate primitive [`ExportSpecSliceExt::has_applicable_at`]
6194 /// both this method and [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6195 /// compose against — so the two struct-level union methods stay
6196 /// symmetric by construction.
6197 ///
6198 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
6199 /// proofs — the walk composes the SAME slice-level substrate
6200 /// primitive on both this ephemeral surface and the
6201 /// [`crate::lifetime::EphemeralLifetime`] surface, so a regression
6202 /// at the compound `(when, phase) → fires_on(phase)` chain fails
6203 /// at ONE site rather than as silent drift between the two peers).
6204 /// THEORY.md §VI.1 (generation over composition — a future
6205 /// [`ProcessPhase`] variant or a future [`crate::export::ExportTrigger`]
6206 /// variant reaches both `exports-fire-on-<phase>` require-tag
6207 /// surfaces mechanically through the SAME closed-set walk).
6208 #[must_use]
6209 pub fn has_applicable_exports_at(&self, phase: ProcessPhase) -> bool {
6210 self.exports.has_applicable_at(phase)
6211 }
6212}
6213
6214impl From<EphemeralSpec> for ProcessSpec {
6215 fn from(e: EphemeralSpec) -> Self {
6216 let classification = e.classification.unwrap_or_else(default_ephemeral_class);
6217 let mut spec = Self {
6218 identity: crate::spec::IdentitySpec {
6219 parent: e.parent,
6220 name_override: None,
6221 },
6222 classification,
6223 intent: Intent {
6224 aplicacao: Some(e.aplicacao),
6225 ..Intent::default()
6226 },
6227 boundary: Boundary {
6228 preconditions: e.preconditions,
6229 postconditions: e.postconditions,
6230 timeout: e.verify_timeout,
6231 },
6232 compliance: Default::default(),
6233 depends_on: vec![],
6234 signals: Default::default(),
6235 // Routes through the ONE substrate composer
6236 // [`Lifetime::ephemeral`] — pre-lift this was one of
6237 // ELEVEN+ hand-authored `Lifetime { ephemeral: Some(<e>),
6238 // .. }` sites past the ★★ PRIME-DIRECTIVE ≥ 2 threshold.
6239 // See the composer's doc-comment for the full migration
6240 // rationale.
6241 lifetime: Lifetime::ephemeral(EphemeralLifetime {
6242 ttl: e.ttl,
6243 teardown_policy: e.teardown,
6244 max_concurrent: e.max_concurrent,
6245 exports: e.exports,
6246 }),
6247 // R5 — propagate routing template (None = no edges).
6248 routing: e.routing,
6249 // EncapsulatesSpec isn't exposed via EphemeralSpec sugar;
6250 // operators wanting Adopt/Observe author the full
6251 // (defpoint …) form. Sugar path stays greenfield-Manage.
6252 encapsulates: None,
6253 suspended: false,
6254 };
6255 // Belt-and-suspenders: make sure exactly-one Intent invariant holds.
6256 spec.intent.nix = None;
6257 spec.intent.flux = None;
6258 spec.intent.lisp = None;
6259 spec.intent.container = None;
6260 spec.intent.guest = None;
6261 spec
6262 }
6263}
6264
6265fn default_ephemeral_class() -> Classification {
6266 // Delegates through the substrate `(Gate, Compute)` baseline owner
6267 // so the shape lives at ONE workspace-wide site — see
6268 // [`Classification::gate_compute`] for the pre-lift ten-callsite
6269 // duplication history and the sibling-default correspondence
6270 // pinned there.
6271 Classification::gate_compute()
6272}
6273
6274/// Compile a `(defephemeral …)` Lisp source into named `EphemeralSpec` values.
6275pub fn compile_ephemeral_source(
6276 src: &str,
6277) -> tatara_lisp::Result<Vec<tatara_lisp::NamedDefinition<EphemeralSpec>>> {
6278 tatara_lisp::compile_named::<EphemeralSpec>(src)
6279}
6280
6281#[cfg(test)]
6282mod tests {
6283 use super::*;
6284 use crate::boundary::{assert_slice_refinement_composition_laws, ConditionKind};
6285 use crate::classification::{
6286 Arity, CalmClassification, ConvergencePointType, DataClassification, Horizon, HorizonKind,
6287 OptimizationDirection, SubstrateType,
6288 };
6289 use crate::intent::IntentVariant;
6290 use crate::lifetime::LifetimeVariant;
6291
6292 /// LANDMARK PIN — the (ephemeral-surface test-fixture ×
6293 /// [`Classification::gate_compute_with_axis`] on horizon-nested
6294 /// axes) sweep equivalence. Nine ephemeral-surface probe-sweep
6295 /// tests in this module (`has_horizon_kind_*`,
6296 /// `has_optimization_direction_*`, `horizon_terminates_*`,
6297 /// `horizon_requires_metric_axes_*`, `horizon_terminates_xor_*`)
6298 /// pre-sweep restated the SAME `let mut c =
6299 /// Classification::gate_compute(); c.horizon = Horizon { <slot>:
6300 /// populated, ..Horizon::default() }` five-line fixture at each
6301 /// callsite, mutating exactly ONE horizon-nested slot to
6302 /// `populated`; post-sweep each callsite reads
6303 /// [`Classification::gate_compute_with_axis(populated)`] — one
6304 /// line — and the four-baseline-slot restatement lives at ONE
6305 /// substrate primitive. This pin asserts byte-parity between the
6306 /// pre-sweep hand-authored `Horizon` struct-literal shape (both
6307 /// the [`HorizonKind::kind`] mutation shape AND the
6308 /// [`OptimizationDirection`]-into-`Some(_)` mutation shape) and
6309 /// the post-sweep composer output on every variant of each closed
6310 /// set, so a regression that either (a) changed
6311 /// [`ClassificationAxis for HorizonKind`] to stomp a non-`kind`
6312 /// sub-slot, (b) changed [`ClassificationAxis for OptimizationDirection`]
6313 /// to drop the `Some(...)` wrap, or (c) reintroduced a whole-
6314 /// `Horizon`-reset shape that dropped a sibling sub-slot would
6315 /// fail HERE at ONE landmark site before landing at the peer
6316 /// probe-sweep pins that use the composer.
6317 ///
6318 /// Byte-for-byte peer of the sibling landmark
6319 /// `with_axis_optimization_direction_overlay_wraps_variant_in_some`
6320 /// on the point-surface classification-module tests — this pin
6321 /// carries the same substrate contract through to the ephemeral-
6322 /// surface tests that consume the composer.
6323 #[test]
6324 fn gate_compute_with_axis_on_horizon_nested_axes_matches_hand_authored_shape() {
6325 for kind in HorizonKind::ALL {
6326 let via_composer = Classification::gate_compute_with_axis(kind);
6327 let mut via_hand_authored = Classification::gate_compute();
6328 via_hand_authored.horizon = Horizon {
6329 kind,
6330 ..Horizon::default()
6331 };
6332 assert_eq!(
6333 via_composer, via_hand_authored,
6334 "HorizonKind::{kind:?}: composer vs pre-sweep hand-authored struct-literal drift",
6335 );
6336 }
6337 for direction in OptimizationDirection::ALL {
6338 let via_composer = Classification::gate_compute_with_axis(direction);
6339 let mut via_hand_authored = Classification::gate_compute();
6340 via_hand_authored.horizon = Horizon {
6341 direction: Some(direction),
6342 ..Horizon::default()
6343 };
6344 assert_eq!(
6345 via_composer, via_hand_authored,
6346 "OptimizationDirection::{direction:?}: composer vs pre-sweep hand-authored struct-literal drift",
6347 );
6348 }
6349 }
6350
6351 /// Primitive-owner pin — `EphemeralSpec::with_classification_axis`
6352 /// on a `classification: None` carrier produces an ephemeral spec
6353 /// whose `classification` slot is
6354 /// `Some(Classification::gate_compute_with_axis(axis))` byte-for-
6355 /// byte on every axis-variant, and preserves every non-
6356 /// classification slot at its pre-call value. A regression that
6357 /// (a) failed to wrap the composed [`Classification`] in `Some(_)`
6358 /// on the `None`-arm, (b) mutated a sibling slot on `EphemeralSpec`
6359 /// through the axis overlay, or (c) picked a different `None`-arm
6360 /// fill-through than the sibling
6361 /// [`Self::resolved_classification`] resolver would fail HERE.
6362 #[test]
6363 fn with_classification_axis_on_none_arm_fills_through_gate_compute() {
6364 fn baseline() -> EphemeralSpec {
6365 EphemeralSpec {
6366 aplicacao: demo_overlay(),
6367 ttl: "2h".into(),
6368 teardown: TeardownPolicy::OnAttested,
6369 max_concurrent: 3,
6370 postconditions: vec![],
6371 preconditions: vec![],
6372 verify_timeout: Some("30m".into()),
6373 classification: None,
6374 parent: Some("seph.1".into()),
6375 exports: vec![],
6376 routing: None,
6377 }
6378 }
6379 // Direct-scalar axes: composer output matches
6380 // `Classification::gate_compute_with_axis(axis)` byte-for-byte,
6381 // wrapped in `Some(_)`.
6382 for kind in ConvergencePointType::ALL {
6383 let via_composer = baseline().with_classification_axis(kind);
6384 assert_eq!(
6385 via_composer.classification,
6386 Some(Classification::gate_compute_with_axis(kind)),
6387 "ConvergencePointType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6388 );
6389 }
6390 for kind in SubstrateType::ALL {
6391 let via_composer = baseline().with_classification_axis(kind);
6392 assert_eq!(
6393 via_composer.classification,
6394 Some(Classification::gate_compute_with_axis(kind)),
6395 "SubstrateType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6396 );
6397 }
6398 for kind in CalmClassification::ALL {
6399 let via_composer = baseline().with_classification_axis(kind);
6400 assert_eq!(
6401 via_composer.classification,
6402 Some(Classification::gate_compute_with_axis(kind)),
6403 "CalmClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6404 );
6405 }
6406 for kind in DataClassification::ALL {
6407 let via_composer = baseline().with_classification_axis(kind);
6408 assert_eq!(
6409 via_composer.classification,
6410 Some(Classification::gate_compute_with_axis(kind)),
6411 "DataClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6412 );
6413 }
6414 // Horizon-nested axes: same shape through the trait's
6415 // sub-slot overlay.
6416 for kind in HorizonKind::ALL {
6417 let via_composer = baseline().with_classification_axis(kind);
6418 assert_eq!(
6419 via_composer.classification,
6420 Some(Classification::gate_compute_with_axis(kind)),
6421 "HorizonKind::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6422 );
6423 }
6424 for direction in OptimizationDirection::ALL {
6425 let via_composer = baseline().with_classification_axis(direction);
6426 assert_eq!(
6427 via_composer.classification,
6428 Some(Classification::gate_compute_with_axis(direction)),
6429 "OptimizationDirection::{direction:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6430 );
6431 }
6432 // Non-classification slots: every one preserved byte-for-byte
6433 // across the overlay on every axis. Compare through JSON
6434 // round-trip since `AplicacaoIntent` / `ExportSpec` /
6435 // `RoutingSpec` do not carry `PartialEq`.
6436 for kind in ConvergencePointType::ALL {
6437 let via_composer = baseline().with_classification_axis(kind);
6438 let baseline_ref = baseline();
6439 assert_eq!(
6440 serde_json::to_string(&via_composer.aplicacao).unwrap(),
6441 serde_json::to_string(&baseline_ref.aplicacao).unwrap(),
6442 "aplicacao slot drifted under axis overlay for kind={kind:?}",
6443 );
6444 assert_eq!(via_composer.ttl, baseline_ref.ttl);
6445 assert_eq!(via_composer.teardown, baseline_ref.teardown);
6446 assert_eq!(via_composer.max_concurrent, baseline_ref.max_concurrent);
6447 assert_eq!(
6448 via_composer.postconditions.len(),
6449 baseline_ref.postconditions.len()
6450 );
6451 assert_eq!(
6452 via_composer.preconditions.len(),
6453 baseline_ref.preconditions.len()
6454 );
6455 assert_eq!(via_composer.verify_timeout, baseline_ref.verify_timeout);
6456 assert_eq!(via_composer.parent, baseline_ref.parent);
6457 assert_eq!(via_composer.exports.len(), baseline_ref.exports.len());
6458 assert!(via_composer.routing.is_none());
6459 }
6460 }
6461
6462 /// Primitive-owner pin —
6463 /// `EphemeralSpec::with_classification_axis` on a
6464 /// `classification: Some(prior)` carrier composes the axis
6465 /// overlay onto `prior` via [`ClassificationAxis::overlay`],
6466 /// preserving every OTHER axis slot on `prior`. Distinct from the
6467 /// `None`-arm pin above: the `Some(prior)` arm does NOT reset
6468 /// through [`Classification::gate_compute`], and consecutive
6469 /// `.with_classification_axis(...)` calls compose arbitrary
6470 /// N-axis conjunctions on the ephemeral surface with the same
6471 /// order-independence guarantee [`Classification::with_axis`]
6472 /// carries on distinct-slot axes.
6473 #[test]
6474 fn with_classification_axis_on_some_arm_chains_onto_prior() {
6475 fn baseline() -> EphemeralSpec {
6476 EphemeralSpec {
6477 aplicacao: demo_overlay(),
6478 ttl: "1h".into(),
6479 teardown: TeardownPolicy::Always,
6480 max_concurrent: 0,
6481 postconditions: vec![],
6482 preconditions: vec![],
6483 verify_timeout: None,
6484 classification: None,
6485 parent: None,
6486 exports: vec![],
6487 routing: None,
6488 }
6489 }
6490 // Prior authored point_type = Fork; overlay substrate = Storage
6491 // preserves the Fork point_type on the composed classification.
6492 let seeded = baseline().with_classification_axis(ConvergencePointType::Fork);
6493 let composed = seeded.with_classification_axis(SubstrateType::Storage);
6494 let classification = composed
6495 .classification
6496 .as_ref()
6497 .expect("with_classification_axis populates Some(_)");
6498 assert_eq!(classification.point_type, ConvergencePointType::Fork);
6499 assert_eq!(classification.substrate, SubstrateType::Storage);
6500 // Order independence on distinct-slot axes: swapping the axis
6501 // chain reads the SAME final classification.
6502 let forward = baseline()
6503 .with_classification_axis(ConvergencePointType::Fork)
6504 .with_classification_axis(SubstrateType::Storage)
6505 .with_classification_axis(CalmClassification::NonMonotone)
6506 .with_classification_axis(DataClassification::Pii)
6507 .classification
6508 .unwrap();
6509 let reverse = baseline()
6510 .with_classification_axis(DataClassification::Pii)
6511 .with_classification_axis(CalmClassification::NonMonotone)
6512 .with_classification_axis(SubstrateType::Storage)
6513 .with_classification_axis(ConvergencePointType::Fork)
6514 .classification
6515 .unwrap();
6516 assert_eq!(
6517 forward, reverse,
6518 "with_classification_axis chain must be order-independent on distinct-slot axes",
6519 );
6520 // Nested horizon-sub-slot overlays compose onto the same
6521 // carrier without stomping each other: the (kind, direction)
6522 // pair rides both chains.
6523 let paired = baseline()
6524 .with_classification_axis(HorizonKind::Asymptotic)
6525 .with_classification_axis(OptimizationDirection::Maximize)
6526 .classification
6527 .unwrap();
6528 assert_eq!(paired.horizon.kind, HorizonKind::Asymptotic);
6529 assert_eq!(
6530 paired.horizon.direction,
6531 Some(OptimizationDirection::Maximize)
6532 );
6533 }
6534
6535 /// Primitive-owner pin —
6536 /// `EphemeralSpec::with_classification_axis` composes byte-for-
6537 /// byte with the pre-sweep hand-authored two-shape callsite
6538 /// pattern that recurred at ~36 sites in
6539 /// `tatara-reconciler::bin::tatara-check`: either
6540 /// `let mut c = Classification::gate_compute(); c.<axis> =
6541 /// populated; EphemeralSpec { classification: Some(c), ..
6542 /// baseline }`, or the newer `let c =
6543 /// Classification::gate_compute_with_axis(populated); EphemeralSpec
6544 /// { classification: Some(c), ..baseline }`. Both restated
6545 /// pre-sweep shapes classify identically to
6546 /// `baseline.with_classification_axis(populated)` on every
6547 /// [`ClassificationAxis`] impl. A regression that drifted the
6548 /// composer body away from the pre-sweep shape (a stray reset of a
6549 /// non-classification slot, a stomping of a nested horizon sub-
6550 /// slot on the direct-scalar axes) fails HERE at ONE landmark site
6551 /// before drifting through the ~36 swept callsites in tatara-
6552 /// check.rs.
6553 #[test]
6554 fn with_classification_axis_matches_pre_sweep_hand_authored_shape() {
6555 fn baseline() -> EphemeralSpec {
6556 EphemeralSpec {
6557 aplicacao: demo_overlay(),
6558 ttl: "1h".into(),
6559 teardown: TeardownPolicy::Always,
6560 max_concurrent: 0,
6561 postconditions: vec![],
6562 preconditions: vec![],
6563 verify_timeout: None,
6564 classification: None,
6565 parent: None,
6566 exports: vec![],
6567 routing: None,
6568 }
6569 }
6570 // Direct-scalar axes: `<eph>.with_classification_axis(kind)`
6571 // matches the pre-sweep two-shape callsite pattern on every
6572 // ConvergencePointType variant.
6573 for kind in ConvergencePointType::ALL {
6574 let via_composer = baseline().with_classification_axis(kind);
6575 let mut hand_classification = Classification::gate_compute();
6576 hand_classification.point_type = kind;
6577 let via_hand = EphemeralSpec {
6578 classification: Some(hand_classification),
6579 ..baseline()
6580 };
6581 assert_eq!(
6582 via_composer.classification, via_hand.classification,
6583 "ConvergencePointType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6584 );
6585 }
6586 for kind in SubstrateType::ALL {
6587 let via_composer = baseline().with_classification_axis(kind);
6588 let mut hand_classification = Classification::gate_compute();
6589 hand_classification.substrate = kind;
6590 let via_hand = EphemeralSpec {
6591 classification: Some(hand_classification),
6592 ..baseline()
6593 };
6594 assert_eq!(
6595 via_composer.classification, via_hand.classification,
6596 "SubstrateType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6597 );
6598 }
6599 for kind in CalmClassification::ALL {
6600 let via_composer = baseline().with_classification_axis(kind);
6601 let mut hand_classification = Classification::gate_compute();
6602 hand_classification.calm = kind;
6603 let via_hand = EphemeralSpec {
6604 classification: Some(hand_classification),
6605 ..baseline()
6606 };
6607 assert_eq!(
6608 via_composer.classification, via_hand.classification,
6609 "CalmClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6610 );
6611 }
6612 for kind in DataClassification::ALL {
6613 let via_composer = baseline().with_classification_axis(kind);
6614 let mut hand_classification = Classification::gate_compute();
6615 hand_classification.data_classification = kind;
6616 let via_hand = EphemeralSpec {
6617 classification: Some(hand_classification),
6618 ..baseline()
6619 };
6620 assert_eq!(
6621 via_composer.classification, via_hand.classification,
6622 "DataClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6623 );
6624 }
6625 // Horizon-nested axes: composer matches the newer
6626 // `gate_compute_with_axis` shape used on the horizon-nested
6627 // sweep sites in tatara-check.rs.
6628 for kind in HorizonKind::ALL {
6629 let via_composer = baseline().with_classification_axis(kind);
6630 let via_hand = EphemeralSpec {
6631 classification: Some(Classification::gate_compute_with_axis(kind)),
6632 ..baseline()
6633 };
6634 assert_eq!(
6635 via_composer.classification, via_hand.classification,
6636 "HorizonKind::{kind:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
6637 );
6638 }
6639 for direction in OptimizationDirection::ALL {
6640 let via_composer = baseline().with_classification_axis(direction);
6641 let via_hand = EphemeralSpec {
6642 classification: Some(Classification::gate_compute_with_axis(direction)),
6643 ..baseline()
6644 };
6645 assert_eq!(
6646 via_composer.classification, via_hand.classification,
6647 "OptimizationDirection::{direction:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
6648 );
6649 }
6650 }
6651
6652 fn demo_overlay() -> AplicacaoIntent {
6653 AplicacaoIntent {
6654 chart_ref: "oci://ghcr.io/pleme-io/charts/lareira-demo-app".into(),
6655 version: "0.5.5".into(),
6656 profile: "all-in-one".into(),
6657 values_overlay: serde_json::json!({
6658 "cluster": { "name": "ephemeral-test-01", "namespace": "demo-test" },
6659 "data": { "mysql": { "persistence": { "enabled": false } } },
6660 "compliance": { "overlays": [] }
6661 }),
6662 release_name: Some("demo-app-consolidated".into()),
6663 target_namespace: Some("demo-test".into()),
6664 install_timeout: Some("25m".into()),
6665 }
6666 }
6667
6668 #[test]
6669 fn defaults_resolve_for_ephemeral_spec() {
6670 let e = EphemeralSpec {
6671 aplicacao: demo_overlay(),
6672 ttl: crate::lifetime::default_ephemeral_ttl(),
6673 teardown: TeardownPolicy::default(),
6674 max_concurrent: crate::lifetime::default_ephemeral_max_concurrent(),
6675 postconditions: vec![],
6676 preconditions: vec![],
6677 verify_timeout: None,
6678 classification: None,
6679 parent: None,
6680 exports: vec![],
6681 routing: None,
6682 };
6683 let ps: ProcessSpec = e.into();
6684 // Intent must resolve to Aplicacao.
6685 match ps.intent.variant().unwrap() {
6686 IntentVariant::Aplicacao(a) => {
6687 assert_eq!(a.profile, "all-in-one");
6688 assert_eq!(a.install_timeout.as_deref(), Some("25m"));
6689 }
6690 other => panic!("expected Aplicacao, got {other:?}"),
6691 }
6692 // Lifetime must resolve to Ephemeral with defaults.
6693 match ps.lifetime.variant().unwrap() {
6694 LifetimeVariant::Ephemeral(e) => {
6695 assert_eq!(e.ttl, "1h");
6696 assert_eq!(e.teardown_policy, TeardownPolicy::Always);
6697 }
6698 other => panic!("expected ephemeral, got {other:?}"),
6699 }
6700 // Default classification gates the Process at Compute/Internal.
6701 assert_eq!(ps.classification.point_type, ConvergencePointType::Gate);
6702 assert_eq!(ps.classification.substrate, SubstrateType::Compute);
6703 }
6704
6705 #[test]
6706 fn ephemeral_lisp_round_trip() {
6707 let src = r#"
6708 (defephemeral closed-loop-attest
6709 :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
6710 :version "0.5.5"
6711 :profile "all-in-one"
6712 :values-overlay (:cluster (:name "ephemeral-test-01")
6713 :data (:mysql (:persistence (:enabled #f)))
6714 :compliance (:overlays []))
6715 :release-name "demo-app-consolidated"
6716 :target-namespace "demo-test"
6717 :install-timeout "25m")
6718 :ttl "1h"
6719 :teardown OnAttested
6720 :max-concurrent 1
6721 :postconditions
6722 ((:kind HelmReleaseReleased
6723 :params (:name "demo-app-consolidated"
6724 :namespace "demo-test"))
6725 (:kind ClosedLoopAuth
6726 :params (:issuer (:service "demo-app-issuer" :port 8080)
6727 :consumer (:service "demo-app-gateway" :port 8000)
6728 :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
6729 "#;
6730 let defs = compile_ephemeral_source(src).expect("compile");
6731 assert_eq!(defs.len(), 1);
6732 let d = &defs[0];
6733 assert_eq!(d.name, "closed-loop-attest");
6734
6735 // Aplicacao body landed correctly.
6736 assert_eq!(
6737 d.spec.aplicacao.chart_ref,
6738 "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
6739 );
6740 assert_eq!(d.spec.aplicacao.profile, "all-in-one");
6741 assert_eq!(
6742 d.spec.aplicacao.target_namespace.as_deref(),
6743 Some("demo-test")
6744 );
6745 // values-overlay JSON is preserved.
6746 assert_eq!(
6747 d.spec.aplicacao.values_overlay["cluster"]["name"],
6748 "ephemeral-test-01"
6749 );
6750 // Boolean #f is preserved as a typed JSON bool (not the string "false").
6751 // tatara-lisp uses Scheme syntax for bools — `#t` / `#f`.
6752 assert_eq!(
6753 d.spec.aplicacao.values_overlay["data"]["mysql"]["persistence"]["enabled"],
6754 false
6755 );
6756
6757 // Lifetime knobs.
6758 assert_eq!(d.spec.ttl, "1h");
6759 assert_eq!(d.spec.teardown, TeardownPolicy::OnAttested);
6760 assert_eq!(d.spec.max_concurrent, 1);
6761
6762 // Two postconditions, both typed.
6763 assert_eq!(d.spec.postconditions.len(), 2);
6764 assert_eq!(
6765 d.spec.postconditions[0].kind,
6766 ConditionKind::HelmReleaseReleased
6767 );
6768 assert_eq!(d.spec.postconditions[1].kind, ConditionKind::ClosedLoopAuth);
6769
6770 // Lowers to ProcessSpec with the right shape.
6771 let ps: ProcessSpec = d.spec.clone().into();
6772 assert!(matches!(
6773 ps.intent.variant().unwrap(),
6774 IntentVariant::Aplicacao(_)
6775 ));
6776 assert!(matches!(
6777 ps.lifetime.variant().unwrap(),
6778 LifetimeVariant::Ephemeral(_)
6779 ));
6780 assert_eq!(ps.boundary.postconditions.len(), 2);
6781 }
6782
6783 /// End-to-end: the `:exports` slot on `(defephemeral …)` compiles
6784 /// into typed `ExportSpec` values via the Universal-Deserialize
6785 /// fallthrough — no per-domain keyword handlers needed.
6786 ///
6787 /// Receipts (empty-body source) is exercised via the Rust serde
6788 /// path only (see `export::tests::export_spec_serde_round_trip`).
6789 /// tatara-lisp's empty-kw-form `(:)` currently parses as a single-
6790 /// element array rather than a JSON `{}`; the same limitation
6791 /// affects `(:permanent)` on Lifetime. Tracked: extend the reader
6792 /// to accept `(:foo (:))` ⇒ `{"foo": {}}` as a typed-empty form,
6793 /// then re-enable Receipts here.
6794 #[test]
6795 fn exports_lisp_round_trip() {
6796 use crate::export::{ArtifactVariant, ChannelVariant, ExportTrigger, ReportFormat};
6797 let src = r#"
6798 (defephemeral closed-loop-attest
6799 :aplicacao (:chart-ref "oci://x"
6800 :version "1.0.0"
6801 :profile "minimal"
6802 :values-overlay ())
6803 :ttl "30m"
6804 :teardown OnAttested
6805 :exports
6806 ((:source (:test-report (:configmap "junit-results"
6807 :key "junit.xml"
6808 :format Junit))
6809 :channel (:nats-subject (:subject "pleme.pleme-dev.ephemeral.r1.test-report"
6810 :stream "EPHEMERAL_TEST_REPORTS"))
6811 :when OnAttested)
6812 (:source (:test-report (:configmap "junit-results"
6813 :key "junit.xml"
6814 :format Junit))
6815 :channel (:http-event (:signal-type "test-report"))
6816 :when Always)
6817 (:source (:run-marker (:labels (:run-id "r1" :phase "end")))
6818 :channel (:http-event (:signal-type "ephemeral-marker"))
6819 :when Always)))
6820 "#;
6821 let defs = compile_ephemeral_source(src).expect("compile");
6822 assert_eq!(defs.len(), 1);
6823 let d = &defs[0];
6824 assert_eq!(d.spec.exports.len(), 3);
6825
6826 // First export — TestReport → NATS subject + OnAttested
6827 let r = &d.spec.exports[0];
6828 match r.source.variant().unwrap() {
6829 ArtifactVariant::TestReport(tr) => {
6830 assert_eq!(tr.configmap, "junit-results");
6831 assert_eq!(tr.format, ReportFormat::Junit);
6832 }
6833 other => panic!("expected TestReport, got {other:?}"),
6834 }
6835 match r.channel.variant().unwrap() {
6836 ChannelVariant::NatsSubject(n) => {
6837 assert_eq!(n.subject, "pleme.pleme-dev.ephemeral.r1.test-report");
6838 assert_eq!(n.stream, "EPHEMERAL_TEST_REPORTS");
6839 }
6840 other => panic!("expected NatsSubject, got {other:?}"),
6841 }
6842 assert_eq!(r.when, ExportTrigger::OnAttested);
6843
6844 // Second export — TestReport → HTTP + Always
6845 let t = &d.spec.exports[1];
6846 match t.channel.variant().unwrap() {
6847 ChannelVariant::HttpEvent(h) => assert_eq!(h.signal_type, "test-report"),
6848 other => panic!("expected HttpEvent, got {other:?}"),
6849 }
6850 assert_eq!(t.when, ExportTrigger::Always);
6851
6852 // Third export — RunMarker (BTreeMap<String,String> round-trip).
6853 // tatara-lisp lowercases + normalizes keyword keys before
6854 // handing off to serde_json — kebab `:run-id` may land as
6855 // either `run-id` or `runId` depending on the reader path.
6856 // Accept either; the round-trip property under test is
6857 // "label survives compile" not "exact case-form".
6858 let m = &d.spec.exports[2];
6859 match m.source.variant().unwrap() {
6860 ArtifactVariant::RunMarker(rm) => {
6861 assert_eq!(rm.labels.len(), 2);
6862 let run_id = rm
6863 .labels
6864 .get("run-id")
6865 .or_else(|| rm.labels.get("runId"))
6866 .or_else(|| rm.labels.get("run_id"))
6867 .expect("run-id label present under some normalization");
6868 assert_eq!(run_id, "r1");
6869 assert_eq!(rm.labels.get("phase").map(String::as_str), Some("end"));
6870 }
6871 other => panic!("expected RunMarker, got {other:?}"),
6872 }
6873
6874 // Lowered ProcessSpec carries the exports through unchanged.
6875 let ps: ProcessSpec = d.spec.clone().into();
6876 assert_eq!(ps.lifetime.ephemeral.as_ref().unwrap().exports.len(), 3);
6877 }
6878
6879 // ── EphemeralSpec::has_condition_kind substrate pins ─────────────
6880 //
6881 // Fail-before-pass-after granularity:
6882 // `EphemeralSpec::has_condition_kind` did not exist before this
6883 // commit — the (preconditions ∪ postconditions .iter().any(|c|
6884 // c.kind == K)) union-probe shape lived at ONE struct-level site
6885 // (`Boundary::has_condition_kind` on the point surface's nested
6886 // [`Boundary`] slot). The lift adds the peer inherent method on the
6887 // [`EphemeralSpec`] sugar-surface so both struct-level union
6888 // callers compose against the SAME slice-level substrate primitive
6889 // [`ConditionSliceExt::has_kind`] in lockstep. A regression that
6890 // (a) hard-coded the arm to a single kind, (b) dropped the pre-
6891 // condition side of the OR (a re-inheritance of the pre-lift
6892 // ephemeral `closed-loop-auth` post-only shape at the union-tag
6893 // level), or (c) probed the wrong slot fails HERE at the substrate
6894 // primitive rather than as silent operator-facing drift at the
6895 // ephemeral `condition-<kind>` require-tag surface.
6896
6897 fn empty_ephemeral() -> EphemeralSpec {
6898 EphemeralSpec {
6899 aplicacao: AplicacaoIntent::chart_only("oci://ghcr.io/x", "1"),
6900 ttl: "1h".into(),
6901 teardown: TeardownPolicy::Always,
6902 max_concurrent: 0,
6903 postconditions: vec![],
6904 preconditions: vec![],
6905 verify_timeout: None,
6906 classification: None,
6907 parent: None,
6908 exports: vec![],
6909 routing: None,
6910 }
6911 }
6912
6913 fn cond(kind: ConditionKind) -> Condition {
6914 Condition {
6915 kind,
6916 params: serde_json::json!({}),
6917 }
6918 }
6919
6920 /// EMPTY-SPEC pin — a default [`EphemeralSpec`] (empty
6921 /// preconditions, empty postconditions) returns `false` for EVERY
6922 /// [`ConditionKind`]. Sweep `ConditionKind::ALL` so a new variant
6923 /// added without a matching arm in the presence probe surfaces at
6924 /// rustc's exhaustiveness gate on the ALL literal (arity forced by
6925 /// `[Self; 8]`) rather than as a silent false-positive at every
6926 /// downstream `condition-<kind>` ephemeral require-tag callsite.
6927 /// Byte-for-byte peer of
6928 /// `has_condition_kind_returns_false_on_empty_boundary_for_every_kind`
6929 /// on the [`Boundary`] surface.
6930 #[test]
6931 fn has_condition_kind_returns_false_on_empty_ephemeral_for_every_kind() {
6932 let spec = empty_ephemeral();
6933 for kind in ConditionKind::ALL {
6934 assert!(
6935 !spec.has_condition_kind(kind),
6936 "empty ephemeral spec must return false for {kind:?}",
6937 );
6938 }
6939 }
6940
6941 /// POSTCONDITION-only pin — an ephemeral spec that carries the
6942 /// kind on ONLY postconditions returns `true` for that kind,
6943 /// `false` for every other variant. Sweep the ALL × ALL cross so
6944 /// a regression that hard-coded the arm to a single kind or
6945 /// probed the wrong slot fails HERE at the substrate primitive.
6946 #[test]
6947 fn has_condition_kind_reads_ephemeral_postconditions_per_kind() {
6948 for populated in ConditionKind::ALL {
6949 let mut spec = empty_ephemeral();
6950 spec.postconditions.push(cond(populated));
6951 for query in ConditionKind::ALL {
6952 let expected = query == populated;
6953 assert_eq!(
6954 spec.has_condition_kind(query),
6955 expected,
6956 "ephemeral postcondition populated={populated:?}: \
6957 query {query:?} drifted",
6958 );
6959 }
6960 }
6961 }
6962
6963 /// PRECONDITION-only pin — mirrors the postcondition sweep on the
6964 /// other half of the union. Locks the union semantics on both
6965 /// halves separately so a regression that dropped the pre-
6966 /// condition side of the OR fails here even though the
6967 /// postcondition-side pin above passes.
6968 #[test]
6969 fn has_condition_kind_reads_ephemeral_preconditions_per_kind() {
6970 for populated in ConditionKind::ALL {
6971 let mut spec = empty_ephemeral();
6972 spec.preconditions.push(cond(populated));
6973 for query in ConditionKind::ALL {
6974 let expected = query == populated;
6975 assert_eq!(
6976 spec.has_condition_kind(query),
6977 expected,
6978 "ephemeral precondition populated={populated:?}: \
6979 query {query:?} drifted",
6980 );
6981 }
6982 }
6983 }
6984
6985 /// UNION pin — a kind that appears on preconditions returns
6986 /// `true` even when postconditions carries a DIFFERENT kind, and
6987 /// vice versa. Pins the OR-composition of the two halves so a
6988 /// regression that collapsed the union to an intersection (AND)
6989 /// silently reclassifies pre-only or post-only kinds as absent.
6990 /// Byte-for-byte peer of
6991 /// `has_condition_kind_unions_pre_and_post_condition_arms` on the
6992 /// [`Boundary`] surface.
6993 #[test]
6994 fn has_condition_kind_unions_pre_and_post_ephemeral_condition_arms() {
6995 let mut spec = empty_ephemeral();
6996 spec.preconditions
6997 .push(cond(ConditionKind::KustomizationHealthy));
6998 spec.postconditions
6999 .push(cond(ConditionKind::ClosedLoopAuth));
7000 assert!(
7001 spec.has_condition_kind(ConditionKind::KustomizationHealthy),
7002 "pre-only kind must resolve through the union",
7003 );
7004 assert!(
7005 spec.has_condition_kind(ConditionKind::ClosedLoopAuth),
7006 "post-only kind must resolve through the union",
7007 );
7008 assert!(
7009 !spec.has_condition_kind(ConditionKind::PromQL),
7010 "an absent kind must return false even with populated halves",
7011 );
7012 }
7013
7014 /// COMPOSITION pin — [`EphemeralSpec::has_condition_kind`] equals
7015 /// the OR of the two slice-level probes on the pre/post fields.
7016 /// The struct-level union body composes ONLY [`ConditionSliceExt::has_kind`]
7017 /// on each half; a regression that inlined a wide-net predicate
7018 /// (`.iter().any(|c| c.kind != kind).not()`, an `all` instead of
7019 /// `any`) drifts from the slice-level primitive here. Byte-for-
7020 /// byte peer of the
7021 /// `boundary_has_condition_kind_equals_or_of_half_slice_probes`
7022 /// composition pin on the [`Boundary`] surface.
7023 #[test]
7024 fn ephemeral_has_condition_kind_equals_or_of_half_slice_probes() {
7025 // Sweep every ConditionKind on both halves independently so the
7026 // cross of half-slice probes reaches the OR-composition body
7027 // exhaustively.
7028 for populated in ConditionKind::ALL {
7029 let mut spec = empty_ephemeral();
7030 spec.preconditions.push(cond(populated));
7031 spec.postconditions.push(cond(ConditionKind::PromQL));
7032 for query in ConditionKind::ALL {
7033 let via_or_of_halves =
7034 spec.preconditions.has_kind(query) || spec.postconditions.has_kind(query);
7035 assert_eq!(
7036 spec.has_condition_kind(query),
7037 via_or_of_halves,
7038 "populated={populated:?} query={query:?}: struct-level \
7039 union drifted from OR of slice-level probes",
7040 );
7041 }
7042 }
7043 }
7044
7045 // ── EphemeralSpec::has_(pre|post)condition_kind substrate pins ──
7046 //
7047 // Fail-before-pass-after granularity: the two half-slice arms did
7048 // not exist on the ephemeral surface before this commit — the
7049 // ephemeral require-tag classifier in `tatara-check` and the
7050 // `closed-loop-auth` fixed-tag arm reached
7051 // `spec.postconditions.has_kind(K)` through direct field access,
7052 // asymmetric with the union-arm [`EphemeralSpec::has_condition_kind`]
7053 // that already routed through the named struct method. The lift
7054 // closes the (precondition, postcondition, union) triad on the
7055 // ephemeral sugar surface so a future normalization at the
7056 // presence-probe shape lands at ONE site per surface for all
7057 // three arms.
7058
7059 /// EMPTY-SPEC pin — an ephemeral spec with no preconditions and
7060 /// no postconditions returns `false` for EVERY [`ConditionKind`]
7061 /// on both half-slice arms. Sweep `ConditionKind::ALL` so a new
7062 /// variant added without a matching arm surfaces at rustc's
7063 /// exhaustiveness gate on the ALL literal (arity forced by the
7064 /// closed-set array) rather than as a silent false-positive at
7065 /// every downstream require-tag callsite on the ephemeral
7066 /// surface.
7067 #[test]
7068 fn ephemeral_has_precondition_and_postcondition_kind_return_false_on_empty_spec() {
7069 let spec = empty_ephemeral();
7070 for kind in ConditionKind::ALL {
7071 assert!(
7072 !spec.has_precondition_kind(kind),
7073 "empty ephemeral must return false on precondition arm for {kind:?}",
7074 );
7075 assert!(
7076 !spec.has_postcondition_kind(kind),
7077 "empty ephemeral must return false on postcondition arm for {kind:?}",
7078 );
7079 }
7080 }
7081
7082 /// SLICE-SELECTIVITY pin (precondition arm) — an ephemeral spec
7083 /// with a kind on the precondition side ONLY resolves `true` at
7084 /// [`EphemeralSpec::has_precondition_kind`] and `false` at
7085 /// [`EphemeralSpec::has_postcondition_kind`]. Locks the (side-
7086 /// select, kind-select) partition so a regression that pointed
7087 /// the precondition arm at `self.postconditions` (a copy-paste
7088 /// from the sibling arm during the lift) surfaces HERE.
7089 #[test]
7090 fn ephemeral_has_precondition_kind_reads_preconditions_slice_only() {
7091 for populated in ConditionKind::ALL {
7092 let mut spec = empty_ephemeral();
7093 spec.preconditions.push(cond(populated));
7094 for query in ConditionKind::ALL {
7095 let expected_pre = query == populated;
7096 assert_eq!(
7097 spec.has_precondition_kind(query),
7098 expected_pre,
7099 "precondition-only populated={populated:?}: query {query:?} \
7100 drifted on ephemeral precondition arm",
7101 );
7102 assert!(
7103 !spec.has_postcondition_kind(query),
7104 "precondition-only populated={populated:?}: query {query:?} must \
7105 return false on ephemeral postcondition arm (postconditions is empty)",
7106 );
7107 }
7108 }
7109 }
7110
7111 /// SLICE-SELECTIVITY pin (postcondition arm) — mirror of the
7112 /// precondition-only sweep on the other half. Locks the
7113 /// postcondition arm's binding to `self.postconditions` so a
7114 /// regression that pointed it at `self.preconditions` fails HERE
7115 /// even though the precondition-arm pin above passes.
7116 #[test]
7117 fn ephemeral_has_postcondition_kind_reads_postconditions_slice_only() {
7118 for populated in ConditionKind::ALL {
7119 let mut spec = empty_ephemeral();
7120 spec.postconditions.push(cond(populated));
7121 for query in ConditionKind::ALL {
7122 let expected_post = query == populated;
7123 assert_eq!(
7124 spec.has_postcondition_kind(query),
7125 expected_post,
7126 "postcondition-only populated={populated:?}: query {query:?} \
7127 drifted on ephemeral postcondition arm",
7128 );
7129 assert!(
7130 !spec.has_precondition_kind(query),
7131 "postcondition-only populated={populated:?}: query {query:?} must \
7132 return false on ephemeral precondition arm (preconditions is empty)",
7133 );
7134 }
7135 }
7136 }
7137
7138 /// COMPOSITION-LAW pin — [`EphemeralSpec::has_condition_kind`]
7139 /// equals `has_precondition_kind(k) || has_postcondition_kind(k)`
7140 /// at EVERY (pre-populated, post-populated, query) triple on
7141 /// `ConditionKind::ALL`. Byte-for-byte peer of the
7142 /// `boundary_has_condition_kind_composes_precondition_and_postcondition_arms`
7143 /// composition-law pin on the [`Boundary`] surface — the
7144 /// two-surface parity contract binds the ephemeral sugar type
7145 /// and the point-domain boundary type through the SAME
7146 /// (`condition_kind = precondition_kind ∨ postcondition_kind`)
7147 /// composition, so every downstream `condition-<K>` require-tag
7148 /// classifier on either surface inherits the composition
7149 /// mechanically.
7150 #[test]
7151 fn ephemeral_has_condition_kind_composes_precondition_and_postcondition_arms() {
7152 for pre_kind in ConditionKind::ALL {
7153 for post_kind in ConditionKind::ALL {
7154 let mut spec = empty_ephemeral();
7155 spec.preconditions.push(cond(pre_kind));
7156 spec.postconditions.push(cond(post_kind));
7157 for query in ConditionKind::ALL {
7158 let via_arms =
7159 spec.has_precondition_kind(query) || spec.has_postcondition_kind(query);
7160 assert_eq!(
7161 spec.has_condition_kind(query),
7162 via_arms,
7163 "ephemeral union arm drifted from OR of half-slice arms: \
7164 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7165 );
7166 }
7167 }
7168 }
7169 }
7170
7171 /// SUBSTRATE-DELEGATION pin — the two half-slice arms on the
7172 /// ephemeral surface delegate verbatim to
7173 /// [`crate::boundary::ConditionSliceExt::has_kind`] on the
7174 /// underlying [`Vec<Condition>`] slice, no inline reimplementation.
7175 /// Sweep the full `ConditionKind::ALL` × `ConditionKind::ALL`
7176 /// cross so a regression that inlined a divergent walk at either
7177 /// arm surfaces HERE at the substrate boundary rather than as
7178 /// silent skew between the struct-level arm and the slice-level
7179 /// primitive.
7180 #[test]
7181 fn ephemeral_has_precondition_and_postcondition_kind_delegate_to_slice_has_kind() {
7182 for populated in ConditionKind::ALL {
7183 let mut spec = empty_ephemeral();
7184 spec.preconditions.push(cond(populated));
7185 spec.postconditions.push(cond(populated));
7186 for query in ConditionKind::ALL {
7187 assert_eq!(
7188 spec.has_precondition_kind(query),
7189 spec.preconditions.has_kind(query),
7190 "ephemeral precondition arm must delegate to preconditions.has_kind: \
7191 populated={populated:?} query={query:?}",
7192 );
7193 assert_eq!(
7194 spec.has_postcondition_kind(query),
7195 spec.postconditions.has_kind(query),
7196 "ephemeral postcondition arm must delegate to postconditions.has_kind: \
7197 populated={populated:?} query={query:?}",
7198 );
7199 }
7200 }
7201 }
7202
7203 // ── EphemeralSpec::find_(pre|post|)condition_kind widened triad ──
7204 //
7205 // Fail-before-pass-after granularity: the three widened
7206 // `find_*_kind` arms did not exist on the ephemeral surface before
7207 // this commit — the (widened `Option<&Condition>` return) axis
7208 // lived at ONE struct-level site (`Boundary::find_condition_kind`
7209 // on the point surface's nested [`Boundary`] slot). The lift adds
7210 // the peer inherent methods on the [`EphemeralSpec`] sugar-surface
7211 // so both struct-level widened callers compose against the SAME
7212 // slice-level substrate primitive
7213 // [`crate::boundary::ConditionSliceExt::find_kind`] in lockstep.
7214 // A regression that (a) hard-coded the arm to a single kind, (b)
7215 // reversed the walk order on the union (postcondition first), or
7216 // (c) collapsed `or_else` to `and_then` (silently narrowing the
7217 // union to an intersection) fails HERE at the substrate primitive
7218 // rather than as silent operator-facing drift at the ephemeral
7219 // require-tag surface.
7220
7221 /// EMPTY-SPEC pin (find-triad) — a default [`EphemeralSpec`]
7222 /// (empty preconditions, empty postconditions) returns `None`
7223 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
7224 /// `ConditionKind::ALL` × three-arm cross so a new variant added
7225 /// without a matching arm surfaces at rustc's exhaustiveness gate
7226 /// on the ALL literal (arity forced by the closed-set array)
7227 /// rather than as a silent false-`Some` at every downstream
7228 /// widened callsite on the ephemeral surface.
7229 #[test]
7230 fn ephemeral_find_condition_kind_triad_returns_none_on_empty_spec() {
7231 let spec = empty_ephemeral();
7232 for kind in ConditionKind::ALL {
7233 assert!(
7234 spec.find_precondition_kind(kind).is_none(),
7235 "empty ephemeral must return None on precondition find arm for {kind:?}",
7236 );
7237 assert!(
7238 spec.find_postcondition_kind(kind).is_none(),
7239 "empty ephemeral must return None on postcondition find arm for {kind:?}",
7240 );
7241 assert!(
7242 spec.find_condition_kind(kind).is_none(),
7243 "empty ephemeral must return None on union find arm for {kind:?}",
7244 );
7245 }
7246 }
7247
7248 /// SUBSTRATE-DELEGATION pin (ephemeral find-triad) — the three
7249 /// widened `find_*_kind` methods on [`EphemeralSpec`] delegate
7250 /// verbatim to [`crate::boundary::ConditionSliceExt::find_kind`]
7251 /// on the underlying [`Vec<Condition>`] slices, no inline
7252 /// reimplementation. The `find_condition_kind` union walks
7253 /// preconditions first then postconditions via `Option::or_else`.
7254 /// Sweep `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
7255 /// so a regression that (a) inlined a divergent walk at either
7256 /// half-slice arm, (b) reversed the union walk order on the
7257 /// ephemeral surface only (breaking two-surface parity with
7258 /// [`crate::boundary::Boundary::find_condition_kind`]), or (c)
7259 /// collapsed `or_else` to `and_then` surfaces HERE at the substrate
7260 /// boundary. Byte-for-byte peer of the point-domain
7261 /// `find_condition_kind_triad_delegates_to_slice_find_kind` pin.
7262 #[test]
7263 fn ephemeral_find_condition_kind_triad_delegates_to_slice_find_kind() {
7264 for pre_kind in ConditionKind::ALL {
7265 for post_kind in ConditionKind::ALL {
7266 let mut spec = empty_ephemeral();
7267 spec.preconditions.push(cond(pre_kind));
7268 spec.postconditions.push(cond(post_kind));
7269 for query in ConditionKind::ALL {
7270 let via_pre = spec.preconditions.find_kind(query);
7271 let via_post = spec.postconditions.find_kind(query);
7272 assert_eq!(
7273 spec.find_precondition_kind(query).map(|c| c.kind),
7274 via_pre.map(|c| c.kind),
7275 "ephemeral precondition find arm must delegate: \
7276 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7277 );
7278 assert_eq!(
7279 spec.find_postcondition_kind(query).map(|c| c.kind),
7280 via_post.map(|c| c.kind),
7281 "ephemeral postcondition find arm must delegate: \
7282 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7283 );
7284 let expected_union = via_pre.or(via_post).map(|c| c.kind);
7285 assert_eq!(
7286 spec.find_condition_kind(query).map(|c| c.kind),
7287 expected_union,
7288 "ephemeral union find arm must equal precondition.or_else(postcondition): \
7289 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7290 );
7291 }
7292 }
7293 }
7294 }
7295
7296 /// PRECONDITION-PRECEDENCE pin (ephemeral) — a kind authored on
7297 /// BOTH sides returns the precondition-side [`Condition`] from
7298 /// `find_condition_kind`. Byte-for-byte peer of the point-domain
7299 /// `find_condition_kind_returns_precondition_side_on_dual_populated`
7300 /// pin, so the two-surface parity contract binds the walk order
7301 /// on both surfaces through ONE composition law. Uses two params-
7302 /// distinguishable [`Condition`]s so a regression on the ephemeral
7303 /// surface only that reversed the walk order surfaces at the
7304 /// returned params payload rather than silently at the presence
7305 /// bit.
7306 #[test]
7307 fn ephemeral_find_condition_kind_returns_precondition_side_on_dual_populated() {
7308 let mut spec = empty_ephemeral();
7309 spec.preconditions.push(Condition {
7310 kind: ConditionKind::ClosedLoopAuth,
7311 params: serde_json::json!({ "side": "pre" }),
7312 });
7313 spec.postconditions.push(Condition {
7314 kind: ConditionKind::ClosedLoopAuth,
7315 params: serde_json::json!({ "side": "post" }),
7316 });
7317 let hit = spec
7318 .find_condition_kind(ConditionKind::ClosedLoopAuth)
7319 .expect("dual-populated ephemeral spec must resolve Some");
7320 assert_eq!(
7321 hit.params.get("side").and_then(serde_json::Value::as_str),
7322 Some("pre"),
7323 "ephemeral find_condition_kind must walk preconditions first",
7324 );
7325 }
7326
7327 /// STRUCT-LEVEL DELEGATION pin (ephemeral has ↔ find) — the three
7328 /// [`EphemeralSpec`] `has_*_kind` arms equal their widened peers'
7329 /// `.is_some()` projection at EVERY (pre-populated, post-populated,
7330 /// query) triple on `ConditionKind::ALL`. Byte-for-byte peer of
7331 /// the point-domain
7332 /// `boundary_has_triad_equals_find_triad_is_some_projection` pin,
7333 /// so both surfaces' has/find refinement bridge stays symmetric by
7334 /// construction — a future consumer that reads
7335 /// `spec.has_condition_kind(k)` as sugar for
7336 /// `spec.find_condition_kind(k).is_some()` on either surface stays
7337 /// typed against the SAME truth table across the two-surface
7338 /// parity contract.
7339 #[test]
7340 fn ephemeral_has_triad_equals_find_triad_is_some_projection() {
7341 for pre_kind in ConditionKind::ALL {
7342 for post_kind in ConditionKind::ALL {
7343 let mut spec = empty_ephemeral();
7344 spec.preconditions.push(cond(pre_kind));
7345 spec.postconditions.push(cond(post_kind));
7346 for query in ConditionKind::ALL {
7347 assert_eq!(
7348 spec.has_precondition_kind(query),
7349 spec.find_precondition_kind(query).is_some(),
7350 "ephemeral precondition has/find bridge drifted: \
7351 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7352 );
7353 assert_eq!(
7354 spec.has_postcondition_kind(query),
7355 spec.find_postcondition_kind(query).is_some(),
7356 "ephemeral postcondition has/find bridge drifted: \
7357 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7358 );
7359 assert_eq!(
7360 spec.has_condition_kind(query),
7361 spec.find_condition_kind(query).is_some(),
7362 "ephemeral union has/find bridge drifted: \
7363 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7364 );
7365 }
7366 }
7367 }
7368 }
7369
7370 // ── EphemeralSpec::iter_(pre|post|)condition_kind widened triad ──
7371 //
7372 // Fail-before-pass-after granularity: the three widened
7373 // `iter_*_kind` arms did not exist on the ephemeral surface before
7374 // this commit — the (widened `impl Iterator<Item = &Condition>`
7375 // stream) axis lived at ONE struct-level site
7376 // (`Boundary::iter_condition_kind` on the point surface's nested
7377 // [`Boundary`] slot). The lift adds the peer inherent methods on
7378 // the [`EphemeralSpec`] sugar-surface so both struct-level widened
7379 // callers compose against the SAME slice-level substrate primitive
7380 // [`crate::boundary::ConditionSliceExt::iter_kind`] in lockstep.
7381 // A regression that (a) hard-coded the arm to a single kind, (b)
7382 // reversed the chain order on the union (postcondition first), or
7383 // (c) collapsed the chain to a `.zip(...)` (silently narrowing the
7384 // union to an intersection-by-position) fails HERE at the
7385 // substrate primitive rather than as silent operator-facing drift
7386 // at the ephemeral require-tag surface.
7387
7388 /// EMPTY-SPEC pin (iter-triad) — a default [`EphemeralSpec`]
7389 /// (empty preconditions, empty postconditions) yields nothing
7390 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
7391 /// `ConditionKind::ALL` × three-arm cross so a new variant added
7392 /// without a matching arm surfaces at rustc's exhaustiveness gate
7393 /// on the ALL literal rather than as a silent phantom-yield at
7394 /// every downstream widened callsite on the ephemeral surface.
7395 #[test]
7396 fn ephemeral_iter_condition_kind_triad_yields_nothing_on_empty_spec() {
7397 let spec = empty_ephemeral();
7398 for kind in ConditionKind::ALL {
7399 assert_eq!(
7400 spec.iter_precondition_kind(kind).count(),
7401 0,
7402 "empty ephemeral must yield nothing on precondition iter arm for {kind:?}",
7403 );
7404 assert_eq!(
7405 spec.iter_postcondition_kind(kind).count(),
7406 0,
7407 "empty ephemeral must yield nothing on postcondition iter arm for {kind:?}",
7408 );
7409 assert_eq!(
7410 spec.iter_condition_kind(kind).count(),
7411 0,
7412 "empty ephemeral must yield nothing on union iter arm for {kind:?}",
7413 );
7414 }
7415 }
7416
7417 /// SUBSTRATE-DELEGATION pin (ephemeral iter-triad) — the three
7418 /// widened `iter_*_kind` methods on [`EphemeralSpec`] delegate
7419 /// verbatim to [`crate::boundary::ConditionSliceExt::iter_kind`]
7420 /// on the underlying [`Vec<Condition>`] slices, no inline
7421 /// reimplementation. The `iter_condition_kind` union chains
7422 /// preconditions first then postconditions via
7423 /// [`Iterator::chain`]. Sweep
7424 /// `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
7425 /// so a regression that (a) inlined a divergent walk at either
7426 /// half-slice arm, (b) reversed the chain order on the ephemeral
7427 /// surface only (breaking two-surface parity with
7428 /// [`crate::boundary::Boundary::iter_condition_kind`]), or (c)
7429 /// collapsed the chain to a `.zip(...)` surfaces HERE at the
7430 /// substrate boundary. Byte-for-byte peer of the point-domain
7431 /// `iter_condition_kind_triad_delegates_to_slice_iter_kind` pin.
7432 #[test]
7433 fn ephemeral_iter_condition_kind_triad_delegates_to_slice_iter_kind() {
7434 for pre_kind in ConditionKind::ALL {
7435 for post_kind in ConditionKind::ALL {
7436 let mut spec = empty_ephemeral();
7437 spec.preconditions.push(cond(pre_kind));
7438 spec.postconditions.push(cond(post_kind));
7439 for query in ConditionKind::ALL {
7440 let via_pre: Vec<_> = spec
7441 .preconditions
7442 .iter_kind(query)
7443 .map(|c| c.kind)
7444 .collect();
7445 let via_post: Vec<_> = spec
7446 .postconditions
7447 .iter_kind(query)
7448 .map(|c| c.kind)
7449 .collect();
7450 assert_eq!(
7451 spec.iter_precondition_kind(query)
7452 .map(|c| c.kind)
7453 .collect::<Vec<_>>(),
7454 via_pre,
7455 "ephemeral precondition iter arm must delegate: \
7456 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7457 );
7458 assert_eq!(
7459 spec.iter_postcondition_kind(query)
7460 .map(|c| c.kind)
7461 .collect::<Vec<_>>(),
7462 via_post,
7463 "ephemeral postcondition iter arm must delegate: \
7464 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7465 );
7466 let mut expected_union = via_pre.clone();
7467 expected_union.extend(via_post.iter().copied());
7468 assert_eq!(
7469 spec.iter_condition_kind(query)
7470 .map(|c| c.kind)
7471 .collect::<Vec<_>>(),
7472 expected_union,
7473 "ephemeral union iter arm must chain precondition ⨟ postcondition: \
7474 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7475 );
7476 }
7477 }
7478 }
7479 }
7480
7481 /// PRECONDITION-PRECEDENCE pin (ephemeral iter) — a kind
7482 /// authored on BOTH sides yields precondition-side matches
7483 /// FIRST in the union chain. Byte-for-byte peer of the
7484 /// point-domain
7485 /// `iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated`
7486 /// pin — the two-surface parity contract binds the chain order
7487 /// on both surfaces through ONE composition law. Uses two
7488 /// params-distinguishable [`Condition`]s so a regression on the
7489 /// ephemeral surface only that reversed the chain order surfaces
7490 /// at the returned params payload rather than silently at the
7491 /// count.
7492 #[test]
7493 fn ephemeral_iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated()
7494 {
7495 let mut spec = empty_ephemeral();
7496 spec.preconditions.push(Condition {
7497 kind: ConditionKind::ClosedLoopAuth,
7498 params: serde_json::json!({ "side": "pre-1" }),
7499 });
7500 spec.postconditions.push(Condition {
7501 kind: ConditionKind::ClosedLoopAuth,
7502 params: serde_json::json!({ "side": "post-1" }),
7503 });
7504 spec.postconditions.push(Condition {
7505 kind: ConditionKind::ClosedLoopAuth,
7506 params: serde_json::json!({ "side": "post-2" }),
7507 });
7508 let sides: Vec<_> = spec
7509 .iter_condition_kind(ConditionKind::ClosedLoopAuth)
7510 .map(|c| {
7511 c.params
7512 .get("side")
7513 .and_then(serde_json::Value::as_str)
7514 .unwrap_or_default()
7515 .to_owned()
7516 })
7517 .collect();
7518 assert_eq!(
7519 sides,
7520 vec!["pre-1".to_owned(), "post-1".to_owned(), "post-2".to_owned(),],
7521 "ephemeral iter_condition_kind must yield every precondition-side match before \
7522 any postcondition-side match (chain order pinned by two-surface parity)",
7523 );
7524 }
7525
7526 /// STRUCT-LEVEL DELEGATION pin (find ↔ iter on EphemeralSpec) —
7527 /// the three [`EphemeralSpec`] `find_*_kind` arms equal their
7528 /// widened peers' `.next()` projection at EVERY (pre-populated,
7529 /// post-populated, query) triple on `ConditionKind::ALL`.
7530 /// Byte-for-byte peer of the point-domain
7531 /// `boundary_find_triad_equals_iter_triad_next_projection` pin,
7532 /// so both surfaces' find/iter refinement bridge stays symmetric
7533 /// by construction across the two-surface parity contract.
7534 #[test]
7535 fn ephemeral_find_triad_equals_iter_triad_next_projection() {
7536 for pre_kind in ConditionKind::ALL {
7537 for post_kind in ConditionKind::ALL {
7538 let mut spec = empty_ephemeral();
7539 spec.preconditions.push(cond(pre_kind));
7540 spec.postconditions.push(cond(post_kind));
7541 for query in ConditionKind::ALL {
7542 assert_eq!(
7543 spec.find_precondition_kind(query).map(|c| c.kind),
7544 spec.iter_precondition_kind(query).next().map(|c| c.kind),
7545 "ephemeral precondition find/iter bridge drifted: \
7546 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7547 );
7548 assert_eq!(
7549 spec.find_postcondition_kind(query).map(|c| c.kind),
7550 spec.iter_postcondition_kind(query).next().map(|c| c.kind),
7551 "ephemeral postcondition find/iter bridge drifted: \
7552 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7553 );
7554 assert_eq!(
7555 spec.find_condition_kind(query).map(|c| c.kind),
7556 spec.iter_condition_kind(query).next().map(|c| c.kind),
7557 "ephemeral union find/iter bridge drifted: \
7558 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7559 );
7560 }
7561 }
7562 }
7563 }
7564
7565 // ── EphemeralSpec count triad — scalar cardinality peers ─────────
7566 //
7567 // Byte-for-byte peers of the point-domain `Boundary`
7568 // `count_(pre|post|)condition_kind` triad, tested at the ephemeral
7569 // sugar surface. Same SUM composition on the union arm, same
7570 // slice-level substrate delegation, same composition-law bridge
7571 // against the widened iter refinement.
7572
7573 /// EMPTY-SPEC pin (count-triad) — a default [`EphemeralSpec`]
7574 /// counts `0` from every arm of the count triad for EVERY
7575 /// [`ConditionKind`].
7576 #[test]
7577 fn ephemeral_count_condition_kind_triad_returns_zero_on_empty_spec() {
7578 let spec = empty_ephemeral();
7579 for kind in ConditionKind::ALL {
7580 assert_eq!(
7581 spec.count_precondition_kind(kind),
7582 0,
7583 "empty ephemeral must count 0 on precondition arm for {kind:?}",
7584 );
7585 assert_eq!(
7586 spec.count_postcondition_kind(kind),
7587 0,
7588 "empty ephemeral must count 0 on postcondition arm for {kind:?}",
7589 );
7590 assert_eq!(
7591 spec.count_condition_kind(kind),
7592 0,
7593 "empty ephemeral must count 0 on union arm for {kind:?}",
7594 );
7595 }
7596 }
7597
7598 /// SUBSTRATE-DELEGATION pin (ephemeral count-triad) — the three
7599 /// widened `count_*_kind` methods on [`EphemeralSpec`] delegate
7600 /// verbatim to [`crate::boundary::ConditionSliceExt::count_kind`]
7601 /// on the underlying [`Vec<Condition>`] slices. The
7602 /// `count_condition_kind` union SUMS preconditions and
7603 /// postconditions. Byte-for-byte peer of the point-domain
7604 /// `boundary_count_condition_kind_triad_delegates_and_sums_slice_count_kind`
7605 /// pin; a regression that (a) subtracted rather than summed, (b)
7606 /// collapsed the sum to [`std::cmp::max`], or (c) inlined a
7607 /// divergent count at either half-slice arm on the ephemeral
7608 /// surface only (breaking two-surface parity with [`Boundary`])
7609 /// surfaces HERE.
7610 #[test]
7611 fn ephemeral_count_condition_kind_triad_delegates_and_sums_slice_count_kind() {
7612 for pre_kind in ConditionKind::ALL {
7613 for post_kind in ConditionKind::ALL {
7614 let mut spec = empty_ephemeral();
7615 spec.preconditions.push(cond(pre_kind));
7616 spec.postconditions.push(cond(post_kind));
7617 for query in ConditionKind::ALL {
7618 let via_pre = spec.preconditions.count_kind(query);
7619 let via_post = spec.postconditions.count_kind(query);
7620 assert_eq!(
7621 spec.count_precondition_kind(query),
7622 via_pre,
7623 "ephemeral precondition count arm must delegate: \
7624 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7625 );
7626 assert_eq!(
7627 spec.count_postcondition_kind(query),
7628 via_post,
7629 "ephemeral postcondition count arm must delegate: \
7630 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7631 );
7632 assert_eq!(
7633 spec.count_condition_kind(query),
7634 via_pre + via_post,
7635 "ephemeral union count arm must SUM pre + post: \
7636 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7637 );
7638 }
7639 }
7640 }
7641 }
7642
7643 /// STRUCT-LEVEL DELEGATION pin (count ↔ iter on EphemeralSpec) —
7644 /// the three [`EphemeralSpec`] `count_*_kind` arms equal their
7645 /// widened peers' `.count()` projection at EVERY (pre-populated
7646 /// twice, post-populated, query) triple. Byte-for-byte peer of
7647 /// the point-domain
7648 /// `boundary_count_triad_equals_iter_triad_count_projection`
7649 /// pin. Uses two-preconditions authoring so the union arm's SUM
7650 /// composition witnesses a nontrivial cardinality (rather than
7651 /// coinciding with the presence bit).
7652 #[test]
7653 fn ephemeral_count_triad_equals_iter_triad_count_projection() {
7654 for pre_kind in ConditionKind::ALL {
7655 for post_kind in ConditionKind::ALL {
7656 let mut spec = empty_ephemeral();
7657 spec.preconditions.push(cond(pre_kind));
7658 spec.preconditions.push(cond(pre_kind));
7659 spec.postconditions.push(cond(post_kind));
7660 for query in ConditionKind::ALL {
7661 assert_eq!(
7662 spec.count_precondition_kind(query),
7663 spec.iter_precondition_kind(query).count(),
7664 "ephemeral precondition count/iter bridge drifted: \
7665 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7666 );
7667 assert_eq!(
7668 spec.count_postcondition_kind(query),
7669 spec.iter_postcondition_kind(query).count(),
7670 "ephemeral postcondition count/iter bridge drifted: \
7671 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7672 );
7673 assert_eq!(
7674 spec.count_condition_kind(query),
7675 spec.iter_condition_kind(query).count(),
7676 "ephemeral union count/iter bridge drifted: \
7677 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7678 );
7679 }
7680 }
7681 }
7682 }
7683
7684 // ── EphemeralSpec distinct-set triad — substrate-delegation pin ──
7685 //
7686 // The (precondition, postcondition, condition-union) distinct-set
7687 // triad on [`EphemeralSpec`] delegates to the slice-level substrate
7688 // primitive [`crate::boundary::ConditionSliceExt::distinct_kinds`]
7689 // on each half-slice and composes the union via
7690 // [`Self::has_condition_kind`] over [`ConditionKind::ALL`] — byte-
7691 // for-byte peer of the point-surface distinct-set triad on
7692 // [`crate::boundary::Boundary`]. The two-surface parity contract
7693 // now covers FIVE refinements on the condition axis: the four
7694 // point-probe refinements (has / find / iter / count) AND the ONE
7695 // closed-set-inversion refinement (distinct-set) on both surfaces.
7696
7697 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-kind-count
7698 /// triad) — the three `distinct_*_kind_count` methods on
7699 /// [`EphemeralSpec`] delegate to the slice-level substrate
7700 /// primitive [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
7701 /// over the two `Vec<Condition>` slots and compose the union
7702 /// scalar via `ConditionKind::ALL.filter(|k|
7703 /// has_condition_kind(*k)).count()`. Byte-for-byte peer of the
7704 /// point-surface pin
7705 /// `distinct_condition_kind_count_triad_delegates_to_slice_distinct_kind_count`
7706 /// on [`crate::boundary::Boundary`] — the two-surface parity
7707 /// contract now binds every downstream scalar-cardinality consumer
7708 /// on either surface to the SAME closed-set walk through ONE
7709 /// substrate rather than through per-surface `.distinct_*_kinds().len()`
7710 /// re-materializations that pay for a heap allocation.
7711 #[test]
7712 fn ephemeral_distinct_condition_kind_count_triad_delegates_and_matches_distinct_kinds_len() {
7713 // Empty spec — every arm returns 0.
7714 let spec = empty_ephemeral();
7715 for kind in ConditionKind::ALL {
7716 assert_eq!(
7717 spec.distinct_precondition_kind_count(),
7718 0,
7719 "empty ephemeral spec must return 0 on distinct_precondition_kind_count, kind={kind:?}",
7720 );
7721 assert_eq!(
7722 spec.distinct_postcondition_kind_count(),
7723 0,
7724 "empty ephemeral spec must return 0 on distinct_postcondition_kind_count, kind={kind:?}",
7725 );
7726 assert_eq!(
7727 spec.distinct_condition_kind_count(),
7728 0,
7729 "empty ephemeral spec must return 0 on distinct_condition_kind_count, kind={kind:?}",
7730 );
7731 }
7732
7733 for pre_kind in ConditionKind::ALL {
7734 for post_kind in ConditionKind::ALL {
7735 let mut spec = empty_ephemeral();
7736 spec.preconditions.push(cond(pre_kind));
7737 spec.postconditions.push(cond(post_kind));
7738
7739 assert_eq!(
7740 spec.distinct_precondition_kind_count(),
7741 spec.preconditions.distinct_kind_count(),
7742 "EphemeralSpec::distinct_precondition_kind_count must delegate verbatim to \
7743 preconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7744 );
7745 assert_eq!(
7746 spec.distinct_precondition_kind_count(),
7747 spec.distinct_precondition_kinds().len(),
7748 "EphemeralSpec::distinct_precondition_kind_count must equal \
7749 distinct_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7750 );
7751 assert_eq!(
7752 spec.distinct_postcondition_kind_count(),
7753 spec.postconditions.distinct_kind_count(),
7754 "EphemeralSpec::distinct_postcondition_kind_count must delegate verbatim to \
7755 postconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7756 );
7757 assert_eq!(
7758 spec.distinct_postcondition_kind_count(),
7759 spec.distinct_postcondition_kinds().len(),
7760 "EphemeralSpec::distinct_postcondition_kind_count must equal \
7761 distinct_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7762 );
7763 let expected_union_count = if pre_kind == post_kind { 1 } else { 2 };
7764 assert_eq!(
7765 spec.distinct_condition_kind_count(),
7766 expected_union_count,
7767 "EphemeralSpec::distinct_condition_kind_count must count distinct union kinds \
7768 for pre={pre_kind:?} post={post_kind:?}",
7769 );
7770 assert_eq!(
7771 spec.distinct_condition_kind_count(),
7772 spec.distinct_condition_kinds().len(),
7773 "EphemeralSpec::distinct_condition_kind_count must equal \
7774 distinct_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7775 );
7776 }
7777 }
7778 }
7779
7780 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-set triad)
7781 /// — the three `distinct_*_kinds` methods on [`EphemeralSpec`]
7782 /// delegate to the slice-level substrate primitive over the two
7783 /// `Vec<Condition>` slots and compose the union via
7784 /// `ConditionKind::ALL.filter(|k| has_condition_kind(*k))`. Byte-
7785 /// for-byte peer of the point-surface pin
7786 /// `distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds`
7787 /// on [`crate::boundary::Boundary`] — the two-surface parity
7788 /// contract binds every downstream distinct-set consumer on either
7789 /// surface to the SAME closed-set-inversion primitive through ONE
7790 /// substrate rather than through per-surface re-authored sweeps.
7791 #[test]
7792 fn ephemeral_distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds() {
7793 for pre_kind in ConditionKind::ALL {
7794 for post_kind in ConditionKind::ALL {
7795 let mut spec = empty_ephemeral();
7796 spec.preconditions.push(cond(pre_kind));
7797 spec.postconditions.push(cond(post_kind));
7798
7799 assert_eq!(
7800 spec.distinct_precondition_kinds(),
7801 spec.preconditions.distinct_kinds(),
7802 "EphemeralSpec::distinct_precondition_kinds must delegate verbatim to \
7803 preconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
7804 );
7805 assert_eq!(
7806 spec.distinct_postcondition_kinds(),
7807 spec.postconditions.distinct_kinds(),
7808 "EphemeralSpec::distinct_postcondition_kinds must delegate verbatim to \
7809 postconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
7810 );
7811 let expected_union: Vec<_> = ConditionKind::ALL
7812 .into_iter()
7813 .filter(|k| pre_kind == *k || post_kind == *k)
7814 .collect();
7815 assert_eq!(
7816 spec.distinct_condition_kinds(),
7817 expected_union,
7818 "EphemeralSpec::distinct_condition_kinds must equal ConditionKind::ALL-ordered \
7819 set-union of the two half-slice distinct-sets for pre={pre_kind:?} post={post_kind:?}",
7820 );
7821 }
7822 }
7823 }
7824
7825 /// SUBSTRATE-DELEGATION pin (EphemeralSpec distinct-set ITERATOR
7826 /// triad) — the three `iter_distinct_*_condition_kinds` methods on
7827 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7828 /// [`crate::boundary::ConditionSliceExt::iter_distinct_kinds`] over
7829 /// the two `Vec<Condition>` slots and compose the union via
7830 /// `ConditionKind::ALL.iter().copied().filter(|&k|
7831 /// has_condition_kind(k))`. Byte-for-byte peer of
7832 /// `iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
7833 /// on the point-domain [`crate::boundary::Boundary`] surface — both
7834 /// peers compose against the SAME slice-level iterator substrate.
7835 #[test]
7836 fn ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds() {
7837 for pre_kind in ConditionKind::ALL {
7838 for post_kind in ConditionKind::ALL {
7839 let mut spec = empty_ephemeral();
7840 spec.preconditions.push(cond(pre_kind));
7841 spec.postconditions.push(cond(post_kind));
7842
7843 let pre_via_iter: Vec<_> = spec.iter_distinct_precondition_kinds().collect();
7844 assert_eq!(
7845 pre_via_iter,
7846 spec.distinct_precondition_kinds(),
7847 "EphemeralSpec::iter_distinct_precondition_kinds().collect() drifted from \
7848 distinct_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7849 );
7850 let post_via_iter: Vec<_> = spec.iter_distinct_postcondition_kinds().collect();
7851 assert_eq!(
7852 post_via_iter,
7853 spec.distinct_postcondition_kinds(),
7854 "EphemeralSpec::iter_distinct_postcondition_kinds().collect() drifted from \
7855 distinct_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7856 );
7857 let union_via_iter: Vec<_> = spec.iter_distinct_condition_kinds().collect();
7858 assert_eq!(
7859 union_via_iter,
7860 spec.distinct_condition_kinds(),
7861 "EphemeralSpec::iter_distinct_condition_kinds().collect() drifted from \
7862 distinct_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7863 );
7864 }
7865 }
7866 }
7867
7868 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set ITERATOR
7869 /// triad) — the three `iter_missing_*_condition_kinds` methods on
7870 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7871 /// [`crate::boundary::ConditionSliceExt::iter_missing_kinds`] over
7872 /// the two `Vec<Condition>` slots and compose the union via
7873 /// `ConditionKind::ALL.iter().copied().filter(|&k|
7874 /// !has_condition_kind(k))`. Peer of
7875 /// `ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
7876 /// on the missing side under a NEGATED point-probe.
7877 #[test]
7878 fn ephemeral_iter_missing_condition_kinds_triad_delegates_to_slice_iter_missing_kinds() {
7879 let empty = empty_ephemeral();
7880 let all: Vec<_> = ConditionKind::ALL.to_vec();
7881 assert_eq!(
7882 empty.iter_missing_precondition_kinds().collect::<Vec<_>>(),
7883 all,
7884 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_precondition_kinds",
7885 );
7886 assert_eq!(
7887 empty.iter_missing_postcondition_kinds().collect::<Vec<_>>(),
7888 all,
7889 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_postcondition_kinds",
7890 );
7891 assert_eq!(
7892 empty.iter_missing_condition_kinds().collect::<Vec<_>>(),
7893 all,
7894 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_condition_kinds",
7895 );
7896
7897 for pre_kind in ConditionKind::ALL {
7898 for post_kind in ConditionKind::ALL {
7899 let mut spec = empty_ephemeral();
7900 spec.preconditions.push(cond(pre_kind));
7901 spec.postconditions.push(cond(post_kind));
7902
7903 let pre_via_iter: Vec<_> = spec.iter_missing_precondition_kinds().collect();
7904 assert_eq!(
7905 pre_via_iter,
7906 spec.missing_precondition_kinds(),
7907 "EphemeralSpec::iter_missing_precondition_kinds().collect() drifted from \
7908 missing_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7909 );
7910 let post_via_iter: Vec<_> = spec.iter_missing_postcondition_kinds().collect();
7911 assert_eq!(
7912 post_via_iter,
7913 spec.missing_postcondition_kinds(),
7914 "EphemeralSpec::iter_missing_postcondition_kinds().collect() drifted from \
7915 missing_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7916 );
7917 let union_via_iter: Vec<_> = spec.iter_missing_condition_kinds().collect();
7918 assert_eq!(
7919 union_via_iter,
7920 spec.missing_condition_kinds(),
7921 "EphemeralSpec::iter_missing_condition_kinds().collect() drifted from \
7922 missing_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7923 );
7924 }
7925 }
7926 }
7927
7928 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set triad) —
7929 /// the three `missing_*_kinds` methods on [`EphemeralSpec`]
7930 /// delegate to the slice-level substrate primitive
7931 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over the
7932 /// two `Vec<Condition>` slots and compose the union via
7933 /// `ConditionKind::ALL.filter(|k| !has_condition_kind(*k))`. Sweep
7934 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
7935 /// `missing_condition_kinds_triad_delegates_to_slice_missing_kinds`
7936 /// on the point-domain [`crate::boundary::Boundary`] surface —
7937 /// both peers compose against the SAME slice-level substrate
7938 /// primitive so a regression at the per-slice complement walk
7939 /// fails at that primitive's tests rather than as silent drift at
7940 /// either struct-level arm.
7941 #[test]
7942 fn ephemeral_missing_condition_kinds_triad_delegates_to_slice_missing_kinds() {
7943 // Empty ephemeral spec — every arm returns ConditionKind::ALL.
7944 let empty = empty_ephemeral();
7945 let all_kinds = ConditionKind::ALL.to_vec();
7946 assert_eq!(
7947 empty.missing_precondition_kinds(),
7948 all_kinds,
7949 "empty ephemeral spec must return ConditionKind::ALL on missing_precondition_kinds",
7950 );
7951 assert_eq!(
7952 empty.missing_postcondition_kinds(),
7953 all_kinds,
7954 "empty ephemeral spec must return ConditionKind::ALL on missing_postcondition_kinds",
7955 );
7956 assert_eq!(
7957 empty.missing_condition_kinds(),
7958 all_kinds,
7959 "empty ephemeral spec must return ConditionKind::ALL on missing_condition_kinds",
7960 );
7961
7962 for pre_kind in ConditionKind::ALL {
7963 for post_kind in ConditionKind::ALL {
7964 let mut spec = empty_ephemeral();
7965 spec.preconditions.push(cond(pre_kind));
7966 spec.postconditions.push(cond(post_kind));
7967
7968 assert_eq!(
7969 spec.missing_precondition_kinds(),
7970 spec.preconditions.missing_kinds(),
7971 "EphemeralSpec::missing_precondition_kinds must delegate verbatim to \
7972 preconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7973 );
7974 assert_eq!(
7975 spec.missing_postcondition_kinds(),
7976 spec.postconditions.missing_kinds(),
7977 "EphemeralSpec::missing_postcondition_kinds must delegate verbatim to \
7978 postconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7979 );
7980 // Union: a kind is missing from the union iff it is
7981 // missing from BOTH half-slices (SET-INTERSECTION).
7982 let expected_union: Vec<_> = ConditionKind::ALL
7983 .into_iter()
7984 .filter(|k| pre_kind != *k && post_kind != *k)
7985 .collect();
7986 assert_eq!(
7987 spec.missing_condition_kinds(),
7988 expected_union,
7989 "EphemeralSpec::missing_condition_kinds must equal ConditionKind::ALL-ordered \
7990 set-INTERSECTION of the two half-slice missing-sets for pre={pre_kind:?} post={post_kind:?}",
7991 );
7992 // Partition invariant (distinct ∪ missing == ALL, disjoint).
7993 let distinct = spec.distinct_condition_kinds();
7994 let missing = spec.missing_condition_kinds();
7995 for kind in ConditionKind::ALL {
7996 assert!(
7997 distinct.contains(&kind) ^ missing.contains(&kind),
7998 "EphemeralSpec (distinct, missing) partition violated on {kind:?} for pre={pre_kind:?} post={post_kind:?}",
7999 );
8000 }
8001 assert_eq!(
8002 distinct.len() + missing.len(),
8003 ConditionKind::ALL.len(),
8004 "EphemeralSpec (distinct, missing) cardinality partition drift for pre={pre_kind:?} post={post_kind:?}",
8005 );
8006 }
8007 }
8008 }
8009
8010 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-kind-count triad)
8011 /// — the three `missing_*_kind_count` methods on [`EphemeralSpec`]
8012 /// delegate to the slice-level substrate primitive
8013 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
8014 /// the two `Vec<Condition>` slots and compose the union scalar via
8015 /// `ConditionKind::ALL.iter().filter(|k|
8016 /// !has_condition_kind(**k)).count()`. Sweep
8017 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
8018 /// `missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count`
8019 /// on the point-domain [`crate::boundary::Boundary`] surface —
8020 /// both peers compose against the SAME slice-level substrate
8021 /// primitive so a regression at the per-slice negated closed-set
8022 /// walk fails at that primitive's tests rather than as silent drift
8023 /// at either struct-level scalar-cardinality arm. Also pins the
8024 /// scalar-partition invariant `distinct_kind_count +
8025 /// missing_kind_count == ConditionKind::ALL.len()` per arrangement.
8026 #[test]
8027 fn ephemeral_missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count() {
8028 // Empty ephemeral spec — every arm returns ConditionKind::ALL.len().
8029 let empty = empty_ephemeral();
8030 let total = ConditionKind::ALL.len();
8031 assert_eq!(
8032 empty.missing_precondition_kind_count(),
8033 total,
8034 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_precondition_kind_count",
8035 );
8036 assert_eq!(
8037 empty.missing_postcondition_kind_count(),
8038 total,
8039 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_postcondition_kind_count",
8040 );
8041 assert_eq!(
8042 empty.missing_condition_kind_count(),
8043 total,
8044 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_condition_kind_count",
8045 );
8046
8047 for pre_kind in ConditionKind::ALL {
8048 for post_kind in ConditionKind::ALL {
8049 let mut spec = empty_ephemeral();
8050 spec.preconditions.push(cond(pre_kind));
8051 spec.postconditions.push(cond(post_kind));
8052
8053 // Half-slice arms delegate byte-for-byte to the slice
8054 // substrate primitive.
8055 assert_eq!(
8056 spec.missing_precondition_kind_count(),
8057 spec.preconditions.missing_kind_count(),
8058 "EphemeralSpec::missing_precondition_kind_count must delegate verbatim to \
8059 preconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
8060 );
8061 assert_eq!(
8062 spec.missing_precondition_kind_count(),
8063 spec.missing_precondition_kinds().len(),
8064 "EphemeralSpec::missing_precondition_kind_count must equal \
8065 missing_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
8066 );
8067 assert_eq!(
8068 spec.missing_postcondition_kind_count(),
8069 spec.postconditions.missing_kind_count(),
8070 "EphemeralSpec::missing_postcondition_kind_count must delegate verbatim to \
8071 postconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
8072 );
8073 assert_eq!(
8074 spec.missing_postcondition_kind_count(),
8075 spec.missing_postcondition_kinds().len(),
8076 "EphemeralSpec::missing_postcondition_kind_count must equal \
8077 missing_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
8078 );
8079 // Union arm equals missing_condition_kinds().len().
8080 assert_eq!(
8081 spec.missing_condition_kind_count(),
8082 spec.missing_condition_kinds().len(),
8083 "EphemeralSpec::missing_condition_kind_count must equal \
8084 missing_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
8085 );
8086 // Scalar-partition invariant: distinct + missing == ALL.
8087 assert_eq!(
8088 spec.distinct_condition_kind_count() + spec.missing_condition_kind_count(),
8089 ConditionKind::ALL.len(),
8090 "EphemeralSpec (distinct, missing) scalar partition drift for pre={pre_kind:?} post={post_kind:?}",
8091 );
8092 }
8093 }
8094 }
8095
8096 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-distinct-kind
8097 /// triad) — the three `first_distinct_*_kind` methods on
8098 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
8099 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] over
8100 /// the two `Vec<Condition>` slots and compose the union via
8101 /// `ConditionKind::ALL.iter().copied().find(|k|
8102 /// has_condition_kind(*k))`. Byte-for-byte peer of
8103 /// `first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind`
8104 /// on the point-domain [`crate::boundary::Boundary`] surface — both
8105 /// peers compose against the SAME slice-level substrate primitive
8106 /// so a regression at the per-slice short-circuit walk fails at
8107 /// that primitive's tests rather than as silent drift at either
8108 /// struct-level earliest-element arm.
8109 #[test]
8110 fn ephemeral_first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind() {
8111 // Empty ephemeral spec — every arm returns None.
8112 let empty = empty_ephemeral();
8113 assert_eq!(
8114 empty.first_distinct_precondition_kind(),
8115 None,
8116 "empty ephemeral spec must return None on first_distinct_precondition_kind",
8117 );
8118 assert_eq!(
8119 empty.first_distinct_postcondition_kind(),
8120 None,
8121 "empty ephemeral spec must return None on first_distinct_postcondition_kind",
8122 );
8123 assert_eq!(
8124 empty.first_distinct_condition_kind(),
8125 None,
8126 "empty ephemeral spec must return None on first_distinct_condition_kind",
8127 );
8128
8129 for pre_kind in ConditionKind::ALL {
8130 for post_kind in ConditionKind::ALL {
8131 let mut spec = empty_ephemeral();
8132 spec.preconditions.push(cond(pre_kind));
8133 spec.postconditions.push(cond(post_kind));
8134
8135 assert_eq!(
8136 spec.first_distinct_precondition_kind(),
8137 spec.preconditions.first_distinct_kind(),
8138 "EphemeralSpec::first_distinct_precondition_kind must delegate verbatim to \
8139 preconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8140 );
8141 assert_eq!(
8142 spec.first_distinct_precondition_kind(),
8143 spec.distinct_precondition_kinds().first().copied(),
8144 "EphemeralSpec::first_distinct_precondition_kind must equal \
8145 distinct_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8146 );
8147 assert_eq!(
8148 spec.first_distinct_postcondition_kind(),
8149 spec.postconditions.first_distinct_kind(),
8150 "EphemeralSpec::first_distinct_postcondition_kind must delegate verbatim to \
8151 postconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8152 );
8153 assert_eq!(
8154 spec.first_distinct_postcondition_kind(),
8155 spec.distinct_postcondition_kinds().first().copied(),
8156 "EphemeralSpec::first_distinct_postcondition_kind must equal \
8157 distinct_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8158 );
8159 let expected_union = ConditionKind::ALL
8160 .into_iter()
8161 .find(|k| pre_kind == *k || post_kind == *k);
8162 assert_eq!(
8163 spec.first_distinct_condition_kind(),
8164 expected_union,
8165 "EphemeralSpec::first_distinct_condition_kind must equal earliest ALL entry \
8166 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8167 );
8168 assert_eq!(
8169 spec.first_distinct_condition_kind(),
8170 spec.distinct_condition_kinds().first().copied(),
8171 "EphemeralSpec::first_distinct_condition_kind must equal \
8172 distinct_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8173 );
8174 }
8175 }
8176 }
8177
8178 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-missing-kind triad)
8179 /// — the three `first_missing_*_kind` methods on [`EphemeralSpec`]
8180 /// delegate to the slice-level substrate primitive
8181 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`] over
8182 /// the two `Vec<Condition>` slots and compose the union via
8183 /// `ConditionKind::ALL.iter().copied().find(|k|
8184 /// !has_condition_kind(*k))`. Byte-for-byte peer of
8185 /// `first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind`
8186 /// on the point-domain [`crate::boundary::Boundary`] surface.
8187 #[test]
8188 fn ephemeral_first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind() {
8189 // Empty ephemeral spec — every arm returns Some(ConditionKind::ALL[0]).
8190 let empty = empty_ephemeral();
8191 let first = Some(ConditionKind::ALL[0]);
8192 assert_eq!(
8193 empty.first_missing_precondition_kind(),
8194 first,
8195 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_precondition_kind",
8196 );
8197 assert_eq!(
8198 empty.first_missing_postcondition_kind(),
8199 first,
8200 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_postcondition_kind",
8201 );
8202 assert_eq!(
8203 empty.first_missing_condition_kind(),
8204 first,
8205 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_condition_kind",
8206 );
8207
8208 for pre_kind in ConditionKind::ALL {
8209 for post_kind in ConditionKind::ALL {
8210 let mut spec = empty_ephemeral();
8211 spec.preconditions.push(cond(pre_kind));
8212 spec.postconditions.push(cond(post_kind));
8213
8214 assert_eq!(
8215 spec.first_missing_precondition_kind(),
8216 spec.preconditions.first_missing_kind(),
8217 "EphemeralSpec::first_missing_precondition_kind must delegate verbatim to \
8218 preconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8219 );
8220 assert_eq!(
8221 spec.first_missing_precondition_kind(),
8222 spec.missing_precondition_kinds().first().copied(),
8223 "EphemeralSpec::first_missing_precondition_kind must equal \
8224 missing_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8225 );
8226 assert_eq!(
8227 spec.first_missing_postcondition_kind(),
8228 spec.postconditions.first_missing_kind(),
8229 "EphemeralSpec::first_missing_postcondition_kind must delegate verbatim to \
8230 postconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8231 );
8232 assert_eq!(
8233 spec.first_missing_postcondition_kind(),
8234 spec.missing_postcondition_kinds().first().copied(),
8235 "EphemeralSpec::first_missing_postcondition_kind must equal \
8236 missing_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8237 );
8238 let expected_union = ConditionKind::ALL
8239 .into_iter()
8240 .find(|k| pre_kind != *k && post_kind != *k);
8241 assert_eq!(
8242 spec.first_missing_condition_kind(),
8243 expected_union,
8244 "EphemeralSpec::first_missing_condition_kind must equal earliest ALL entry \
8245 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8246 );
8247 assert_eq!(
8248 spec.first_missing_condition_kind(),
8249 spec.missing_condition_kinds().first().copied(),
8250 "EphemeralSpec::first_missing_condition_kind must equal \
8251 missing_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8252 );
8253 }
8254 }
8255 }
8256
8257 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-distinct-kind
8258 /// triad) — the three `last_distinct_*_kind` methods on
8259 /// [`EphemeralSpec`] delegate to the slice-level substrate
8260 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
8261 /// over the two `Vec<Condition>` slots and compose the union via
8262 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
8263 /// has_condition_kind(*k))`. Byte-for-byte peer of
8264 /// `last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind`
8265 /// on the point-domain [`crate::boundary::Boundary`] surface —
8266 /// both peers compose against the SAME slice-level substrate
8267 /// primitive so a regression at the per-slice REVERSED short-
8268 /// circuit walk fails at that primitive's tests rather than as
8269 /// silent drift at either struct-level latest-element arm.
8270 #[test]
8271 fn ephemeral_last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind() {
8272 // Empty ephemeral spec — every arm returns None.
8273 let empty = empty_ephemeral();
8274 assert_eq!(
8275 empty.last_distinct_precondition_kind(),
8276 None,
8277 "empty ephemeral spec must return None on last_distinct_precondition_kind",
8278 );
8279 assert_eq!(
8280 empty.last_distinct_postcondition_kind(),
8281 None,
8282 "empty ephemeral spec must return None on last_distinct_postcondition_kind",
8283 );
8284 assert_eq!(
8285 empty.last_distinct_condition_kind(),
8286 None,
8287 "empty ephemeral spec must return None on last_distinct_condition_kind",
8288 );
8289
8290 for pre_kind in ConditionKind::ALL {
8291 for post_kind in ConditionKind::ALL {
8292 let mut spec = empty_ephemeral();
8293 spec.preconditions.push(cond(pre_kind));
8294 spec.postconditions.push(cond(post_kind));
8295
8296 assert_eq!(
8297 spec.last_distinct_precondition_kind(),
8298 spec.preconditions.last_distinct_kind(),
8299 "EphemeralSpec::last_distinct_precondition_kind must delegate verbatim to \
8300 preconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8301 );
8302 assert_eq!(
8303 spec.last_distinct_precondition_kind(),
8304 spec.distinct_precondition_kinds().last().copied(),
8305 "EphemeralSpec::last_distinct_precondition_kind must equal \
8306 distinct_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8307 );
8308 assert_eq!(
8309 spec.last_distinct_postcondition_kind(),
8310 spec.postconditions.last_distinct_kind(),
8311 "EphemeralSpec::last_distinct_postcondition_kind must delegate verbatim to \
8312 postconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8313 );
8314 assert_eq!(
8315 spec.last_distinct_postcondition_kind(),
8316 spec.distinct_postcondition_kinds().last().copied(),
8317 "EphemeralSpec::last_distinct_postcondition_kind must equal \
8318 distinct_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8319 );
8320 let expected_union = ConditionKind::ALL
8321 .into_iter()
8322 .rev()
8323 .find(|k| pre_kind == *k || post_kind == *k);
8324 assert_eq!(
8325 spec.last_distinct_condition_kind(),
8326 expected_union,
8327 "EphemeralSpec::last_distinct_condition_kind must equal latest ALL entry \
8328 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8329 );
8330 assert_eq!(
8331 spec.last_distinct_condition_kind(),
8332 spec.distinct_condition_kinds().last().copied(),
8333 "EphemeralSpec::last_distinct_condition_kind must equal \
8334 distinct_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8335 );
8336 }
8337 }
8338 }
8339
8340 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-missing-kind triad)
8341 /// — the three `last_missing_*_kind` methods on [`EphemeralSpec`]
8342 /// delegate to the slice-level substrate primitive
8343 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] over
8344 /// the two `Vec<Condition>` slots and compose the union via
8345 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
8346 /// !has_condition_kind(*k))`. Byte-for-byte peer of
8347 /// `last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind`
8348 /// on the point-domain [`crate::boundary::Boundary`] surface.
8349 #[test]
8350 fn ephemeral_last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind() {
8351 // Empty ephemeral spec — every arm returns Some(*ConditionKind::ALL.last().unwrap()).
8352 let empty = empty_ephemeral();
8353 let last = ConditionKind::ALL.last().copied();
8354 assert_eq!(
8355 empty.last_missing_precondition_kind(),
8356 last,
8357 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_precondition_kind",
8358 );
8359 assert_eq!(
8360 empty.last_missing_postcondition_kind(),
8361 last,
8362 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_postcondition_kind",
8363 );
8364 assert_eq!(
8365 empty.last_missing_condition_kind(),
8366 last,
8367 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_condition_kind",
8368 );
8369
8370 for pre_kind in ConditionKind::ALL {
8371 for post_kind in ConditionKind::ALL {
8372 let mut spec = empty_ephemeral();
8373 spec.preconditions.push(cond(pre_kind));
8374 spec.postconditions.push(cond(post_kind));
8375
8376 assert_eq!(
8377 spec.last_missing_precondition_kind(),
8378 spec.preconditions.last_missing_kind(),
8379 "EphemeralSpec::last_missing_precondition_kind must delegate verbatim to \
8380 preconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8381 );
8382 assert_eq!(
8383 spec.last_missing_precondition_kind(),
8384 spec.missing_precondition_kinds().last().copied(),
8385 "EphemeralSpec::last_missing_precondition_kind must equal \
8386 missing_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8387 );
8388 assert_eq!(
8389 spec.last_missing_postcondition_kind(),
8390 spec.postconditions.last_missing_kind(),
8391 "EphemeralSpec::last_missing_postcondition_kind must delegate verbatim to \
8392 postconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8393 );
8394 assert_eq!(
8395 spec.last_missing_postcondition_kind(),
8396 spec.missing_postcondition_kinds().last().copied(),
8397 "EphemeralSpec::last_missing_postcondition_kind must equal \
8398 missing_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8399 );
8400 let expected_union = ConditionKind::ALL
8401 .into_iter()
8402 .rev()
8403 .find(|k| pre_kind != *k && post_kind != *k);
8404 assert_eq!(
8405 spec.last_missing_condition_kind(),
8406 expected_union,
8407 "EphemeralSpec::last_missing_condition_kind must equal latest ALL entry \
8408 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8409 );
8410 assert_eq!(
8411 spec.last_missing_condition_kind(),
8412 spec.missing_condition_kinds().last().copied(),
8413 "EphemeralSpec::last_missing_condition_kind must equal \
8414 missing_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8415 );
8416 }
8417 }
8418 }
8419
8420 // ── assert_slice_refinement_composition_laws — mirror invocations ──
8421 //
8422 // The substrate testkit primitive
8423 // [`crate::boundary::assert_slice_refinement_composition_laws`]
8424 // pins the FOUR composition laws that bind the
8425 // [`crate::boundary::ConditionSliceExt`] refinement algebra
8426 // (find ↔ iter, count ↔ iter, has ↔ find, has ↔ count) at ONE
8427 // call site per authored arrangement, sweeping
8428 // [`ConditionKind::ALL`]. The two ephemeral-surface tests below
8429 // dispatch the primitive against the two `Vec<Condition>` slots
8430 // ([`EphemeralSpec::preconditions`] +
8431 // [`EphemeralSpec::postconditions`]) authored through the
8432 // ephemeral-surface test-fixture — byte-for-byte peer of the
8433 // point-surface `slice_refinement_composition_laws_hold_across_authored_arrangements`
8434 // + `slice_refinement_composition_laws_hold_on_interleaved_duplicates`
8435 // pins on the [`crate::boundary::Boundary`] surface. Two-surface
8436 // parity contract: the substrate primitive holds on every slice
8437 // reachable through either the point-surface `.preconditions` /
8438 // `.postconditions` fields OR the ephemeral-surface's
8439 // eponymous field pair.
8440
8441 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate
8442 /// primitive [`assert_slice_refinement_composition_laws`] holds
8443 /// on both [`EphemeralSpec::preconditions`] and
8444 /// [`EphemeralSpec::postconditions`] slices for every populated-
8445 /// pair authored through the ephemeral-surface test-fixture.
8446 /// Byte-for-byte peer of
8447 /// `slice_refinement_composition_laws_hold_across_authored_arrangements`
8448 /// on the point surface.
8449 #[test]
8450 fn ephemeral_slice_refinement_composition_laws_hold_across_authored_arrangements() {
8451 let empty = empty_ephemeral();
8452 assert_slice_refinement_composition_laws(empty.preconditions.as_slice());
8453 assert_slice_refinement_composition_laws(empty.postconditions.as_slice());
8454
8455 for pre_kind in ConditionKind::ALL {
8456 for post_kind in ConditionKind::ALL {
8457 let mut spec = empty_ephemeral();
8458 spec.preconditions.push(cond(pre_kind));
8459 spec.postconditions.push(cond(post_kind));
8460 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
8461 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
8462 }
8463 }
8464
8465 for populated in ConditionKind::ALL {
8466 let mut spec = empty_ephemeral();
8467 spec.preconditions.push(cond(populated));
8468 spec.preconditions.push(cond(populated));
8469 spec.preconditions.push(cond(populated));
8470 spec.postconditions.push(cond(populated));
8471 spec.postconditions.push(cond(populated));
8472 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
8473 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
8474 }
8475 }
8476
8477 // ── assert_surface_union_composition_laws — ephemeral surface ────
8478 //
8479 // The substrate testkit macro
8480 // [`crate::assert_surface_union_composition_laws`] pins the FOUR
8481 // union composition laws (has: OR, find: or_else, iter: chain,
8482 // count: SUM) that bind the (pre, post, union) refinement triads
8483 // on the [`EphemeralSpec`] sugar-surface at ONE call site per
8484 // authored arrangement, sweeping [`ConditionKind::ALL`]. Byte-for-
8485 // byte peer of the point-surface
8486 // `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
8487 // / `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
8488 // pins on the [`crate::boundary::Boundary`] surface — the two-
8489 // surface parity contract binds every downstream `condition-<K>`
8490 // / `precondition-<K>` / `postcondition-<K>` require-tag classifier
8491 // on either surface to the SAME four union-composition operators
8492 // through ONE substrate primitive rather than through per-surface
8493 // author-time re-authored sweeps.
8494
8495 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate macro
8496 /// [`crate::assert_surface_union_composition_laws`] passes on
8497 /// [`EphemeralSpec`] for the four canonical authored arrangements
8498 /// (empty spec, precondition-only populated, postcondition-only
8499 /// populated, dual-populated sweep over `ALL × ALL`). Byte-for-byte
8500 /// peer of the point-surface
8501 /// `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
8502 /// pin — the two-surface parity contract binds every union
8503 /// composition law on both surfaces to the SAME substrate
8504 /// primitive.
8505 #[test]
8506 fn ephemeral_surface_union_composition_laws_hold_across_authored_arrangements() {
8507 let empty = empty_ephemeral();
8508 crate::assert_surface_union_composition_laws!(empty);
8509
8510 for populated in ConditionKind::ALL {
8511 let mut pre_only = empty_ephemeral();
8512 pre_only.preconditions.push(cond(populated));
8513 crate::assert_surface_union_composition_laws!(pre_only);
8514
8515 let mut post_only = empty_ephemeral();
8516 post_only.postconditions.push(cond(populated));
8517 crate::assert_surface_union_composition_laws!(post_only);
8518 }
8519
8520 for pre_kind in ConditionKind::ALL {
8521 for post_kind in ConditionKind::ALL {
8522 let mut dual = empty_ephemeral();
8523 dual.preconditions.push(cond(pre_kind));
8524 dual.postconditions.push(cond(post_kind));
8525 crate::assert_surface_union_composition_laws!(dual);
8526 }
8527 }
8528 }
8529
8530 /// SUBSTRATE PANEL pin (ephemeral surface, params-distinguishable
8531 /// duplicates) — the substrate macro holds on an [`EphemeralSpec`]
8532 /// whose two half-slices each carry duplicates of the same kind at
8533 /// multiple positions interleaved with a distinct kind. Byte-for-
8534 /// byte peer of the point-surface
8535 /// `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
8536 /// pin — the non-degenerate composition of every union arm on the
8537 /// sugar-surface binds against the SAME four monoid operators as
8538 /// the point-surface peer. A regression on the ephemeral surface
8539 /// only that (a) collapsed `find`'s `or_else` to `and_then`, (b)
8540 /// collapsed `iter`'s `chain` to `zip`, or (c) collapsed `count`'s
8541 /// SUM to `max` surfaces HERE, breaking two-surface parity.
8542 #[test]
8543 fn ephemeral_surface_union_composition_laws_hold_on_interleaved_duplicates() {
8544 let mut spec = empty_ephemeral();
8545 spec.preconditions.push(Condition {
8546 kind: ConditionKind::ClosedLoopAuth,
8547 params: serde_json::json!({ "side": "pre-1" }),
8548 });
8549 spec.preconditions.push(Condition {
8550 kind: ConditionKind::PromQL,
8551 params: serde_json::json!({ "query": "up" }),
8552 });
8553 spec.preconditions.push(Condition {
8554 kind: ConditionKind::ClosedLoopAuth,
8555 params: serde_json::json!({ "side": "pre-2" }),
8556 });
8557 spec.postconditions.push(Condition {
8558 kind: ConditionKind::PromQL,
8559 params: serde_json::json!({ "query": "healthy" }),
8560 });
8561 spec.postconditions.push(Condition {
8562 kind: ConditionKind::ClosedLoopAuth,
8563 params: serde_json::json!({ "side": "post-1" }),
8564 });
8565 crate::assert_surface_union_composition_laws!(spec);
8566 }
8567
8568 #[test]
8569 fn from_impl_clears_other_intent_variants() {
8570 // Even if someone constructs an EphemeralSpec by hand and the
8571 // resulting ProcessSpec is later mutated, the From bridge sets
8572 // every non-Aplicacao slot to None explicitly.
8573 let e = EphemeralSpec {
8574 aplicacao: demo_overlay(),
8575 ttl: "10m".into(),
8576 teardown: TeardownPolicy::Never,
8577 max_concurrent: 0,
8578 postconditions: vec![],
8579 preconditions: vec![],
8580 verify_timeout: None,
8581 classification: None,
8582 parent: Some("seph.1".into()),
8583 exports: vec![],
8584 routing: None,
8585 };
8586 let ps: ProcessSpec = e.into();
8587 assert!(ps.intent.nix.is_none());
8588 assert!(ps.intent.flux.is_none());
8589 assert!(ps.intent.lisp.is_none());
8590 assert!(ps.intent.container.is_none());
8591 assert!(ps.intent.guest.is_none());
8592 assert!(ps.intent.aplicacao.is_some());
8593 assert_eq!(ps.identity.parent.as_deref(), Some("seph.1"));
8594 }
8595
8596 // ── EphemeralSpec::has_teardown_policy substrate pins ────────────
8597 //
8598 // Fail-before-pass-after granularity:
8599 // `EphemeralSpec::has_teardown_policy` did not exist before this
8600 // commit — the (`self.teardown == kind`) scalar-carrier probe on
8601 // the sugar-surface [`EphemeralSpec`] lived only implicitly via
8602 // hand-authored comparisons at potential future call sites, with
8603 // no analogue to the peer
8604 // [`crate::lifetime::EphemeralLifetime::has_teardown_policy`] on
8605 // the point-surface carrier. The lift adds the peer inherent
8606 // method on the [`EphemeralSpec`] sugar-surface so both surfaces'
8607 // `teardown-policy-<kind>` require-tag families in
8608 // `tatara-reconciler::bin::tatara-check` compose against the SAME
8609 // scalar `==` shape in lockstep. A regression that (a) hard-coded
8610 // the arm to a single kind, (b) inverted the closed-set match
8611 // (silently returning `true` on non-matching variants), or (c)
8612 // probed the wrong slot (a stray comparison against `ttl` /
8613 // `max_concurrent`) fails HERE at the substrate primitive rather
8614 // than as silent operator-facing drift at the ephemeral
8615 // `teardown-policy-<kind>` require-tag surface.
8616
8617 /// STORED-slot pin — an ephemeral spec that carries a given
8618 /// [`TeardownPolicy`] returns `true` for that kind, `false` for
8619 /// every other variant. Sweep the [`TeardownPolicy::ALL`] × ALL
8620 /// cross so a regression that hard-coded the arm to a single kind
8621 /// or wired the closure to a fixed unrelated field fails HERE at
8622 /// the substrate primitive. Byte-for-byte peer of
8623 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_returns_true_iff_variant_matches`]
8624 /// on the point-surface [`crate::lifetime::EphemeralLifetime`]
8625 /// carrier — the two surfaces publish identical `==` scalar
8626 /// semantics on their respective `teardown` / `teardown_policy`
8627 /// slots.
8628 #[test]
8629 fn has_teardown_policy_returns_true_iff_ephemeral_teardown_matches_per_kind() {
8630 for populated in TeardownPolicy::ALL {
8631 let mut spec = empty_ephemeral();
8632 spec.teardown = populated;
8633 for query in TeardownPolicy::ALL {
8634 let expected = query == populated;
8635 assert_eq!(
8636 spec.has_teardown_policy(query),
8637 expected,
8638 "ephemeral teardown={populated:?}: query {query:?} drifted",
8639 );
8640 }
8641 }
8642 }
8643
8644 /// DEFAULT-SLOT pin — an [`EphemeralSpec`] whose `teardown` slot
8645 /// is [`TeardownPolicy::default`] (`Always`) returns `true` for
8646 /// `Always` and `false` for every other variant. The
8647 /// (required-scalar-child) corner has no absent state — a
8648 /// hand-authored spec that omits `:teardown` from the
8649 /// `(defephemeral …)` form IS configured for `Always`, and this
8650 /// pin locks the corner's default-arm short-circuit as identical
8651 /// to the (Option-parent × defaulted-scalar-child) corner's
8652 /// reachable arm on the point surface (both return `true` on
8653 /// `Always` only). Byte-for-byte peer of
8654 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_default_probes_always_only`]
8655 /// on the point-surface carrier.
8656 #[test]
8657 fn has_teardown_policy_default_probes_always_only_on_ephemeral() {
8658 let spec = EphemeralSpec {
8659 teardown: TeardownPolicy::default(),
8660 ..empty_ephemeral()
8661 };
8662 for kind in TeardownPolicy::ALL {
8663 let expected = kind == TeardownPolicy::Always;
8664 assert_eq!(
8665 spec.has_teardown_policy(kind),
8666 expected,
8667 "default ephemeral (teardown=Always) baseline: query {kind:?} must be {expected}",
8668 );
8669 }
8670 }
8671
8672 // ── derived-bool-predicate presence probe on EphemeralSpec ×
8673 // TeardownPolicy × ProcessPhase ──
8674 //
8675 // Fail-before-pass-after granularity:
8676 // [`EphemeralSpec::has_teardown_firing_on`] did not exist before
8677 // this commit — the ephemeral sugar surface's require-tag algebra
8678 // discriminated the teardown axis only by the RAW authored variant
8679 // (via `teardown-policy-<kind>`), never by the derived
8680 // [`ProcessPhase`] transition the stored policy fires on
8681 // ([`TeardownPolicy::should_teardown_on`]). Post-lift the shape
8682 // lives at ONE inherent method that byte-for-byte parallels
8683 // [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
8684 // on the point-surface carrier, and both surfaces' require-tag
8685 // classifiers publish a symmetric `teardown-fires-on-<phase>`
8686 // family through the SAME predicate.
8687
8688 /// TRUTH-TABLE DIAGONAL — for every [`TeardownPolicy`] variant,
8689 /// an [`EphemeralSpec`] whose `teardown` slot is set to that
8690 /// variant returns `has_teardown_firing_on(phase)` in agreement
8691 /// with [`TeardownPolicy::should_teardown_on`] for every
8692 /// [`ProcessPhase`] variant. Sweep [`TeardownPolicy::ALL`] ×
8693 /// [`ProcessPhase::ALL`] full cross so a regression that hard-
8694 /// coded the arm to a single policy, wired to the wrong field, or
8695 /// inverted the predicate direction fails HERE at the substrate
8696 /// primitive on the sugar surface (byte-for-byte peer of
8697 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase`]
8698 /// on the point carrier).
8699 #[test]
8700 fn has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase_on_ephemeral() {
8701 for populated in TeardownPolicy::ALL {
8702 let spec = EphemeralSpec {
8703 teardown: populated,
8704 ..empty_ephemeral()
8705 };
8706 for phase in ProcessPhase::ALL {
8707 assert_eq!(
8708 spec.has_teardown_firing_on(phase),
8709 populated.should_teardown_on(phase),
8710 "teardown={populated:?}, phase={phase:?}: predicate drift from \
8711 should_teardown_on projection",
8712 );
8713 }
8714 }
8715 }
8716
8717 /// TWO-SURFACE PARITY PIN — for every [`TeardownPolicy`] variant
8718 /// and every [`ProcessPhase`] variant, the sugar-surface probe
8719 /// and the lowered point-surface probe agree. The `EphemeralSpec
8720 /// → ProcessSpec` lowering routes the stored `teardown` slot
8721 /// through the SAME [`TeardownPolicy::should_teardown_on`]
8722 /// projection on both sides, so the sugar caller and the lowered
8723 /// caller can never disagree — a regression that (a) drifted
8724 /// [`Self::teardown`] between sugar and lowered, (b) rewired
8725 /// either probe body to bypass the shared substrate primitive, or
8726 /// (c) skewed the (policy, phase) truth table between the two
8727 /// surfaces fails HERE at the two-surface boundary rather than at
8728 /// the operator-facing require-tag classifier.
8729 #[test]
8730 fn has_teardown_firing_on_matches_point_peer_through_lowered_teardown_policy() {
8731 for populated in TeardownPolicy::ALL {
8732 let sugar = EphemeralSpec {
8733 teardown: populated,
8734 ..empty_ephemeral()
8735 };
8736 let lowered: ProcessSpec = sugar.clone().into();
8737 let lowered_eph = lowered
8738 .lifetime
8739 .resolved_ephemeral()
8740 .expect("lowered spec must be ephemeral");
8741 for phase in ProcessPhase::ALL {
8742 assert_eq!(
8743 sugar.has_teardown_firing_on(phase),
8744 lowered_eph.has_teardown_firing_on(phase),
8745 "sugar-vs-lowered predicate drift for teardown={populated:?}, phase={phase:?}",
8746 );
8747 }
8748 }
8749 }
8750
8751 // ── EphemeralSpec::resolved_classification + has_point_type pins ─────
8752 //
8753 // Fail-before-pass-after granularity: `resolved_classification` and
8754 // `has_point_type` did not exist pre-lift on `impl EphemeralSpec` — every
8755 // caller wanting the resolved [`Classification`] on the ephemeral
8756 // sugar-surface (currently zero; future ephemeral-surface classification-
8757 // axis require-tag families in `tatara-reconciler::bin::tatara-check`,
8758 // typed audit hooks, documentation generators listing the ephemeral
8759 // surface's known require-tag vocabulary) restated the two-line
8760 // `self.classification.as_ref().unwrap_or(&default_ephemeral_class())`
8761 // resolver body at their site. Post-lift both callers of the resolver
8762 // (`Self::has_point_type` and every future classification-axis peer)
8763 // route through ONE inherent method that shares the fill-through with
8764 // the sibling `From<EphemeralSpec> for ProcessSpec` lowering
8765 // byte-for-byte. A regression that (a) inverted the arm (`Some` filled
8766 // through the default), (b) drifted the default from the sibling
8767 // primitive `Classification::gate_compute()`, or (c) shifted the
8768 // `Cow<'_, Classification>` return shape (a stray `.clone()` on the
8769 // populated arm) fails HERE at the substrate primitive rather than as
8770 // silent operator-facing drift at a future
8771 // `point-type-<kind>` ephemeral require-tag surface.
8772
8773 /// AUTHORED-slot pin — an [`EphemeralSpec`] whose
8774 /// [`EphemeralSpec::classification`] slot names a concrete
8775 /// [`Classification`] returns [`Cow::Borrowed`] pointing at that
8776 /// authored value from [`Self::resolved_classification`]. Pins the
8777 /// populated-arm zero-allocation contract: a caller reading past
8778 /// the resolver sees the SAME byte address the operator authored,
8779 /// so the resolver does not silently clone the authored slot on
8780 /// the populated arm.
8781 #[test]
8782 fn resolved_classification_borrows_authored_slot() {
8783 let mut spec = empty_ephemeral();
8784 let mut authored = Classification::gate_compute();
8785 authored.point_type = ConvergencePointType::Fork;
8786 spec.classification = Some(authored.clone());
8787 let resolved = spec.resolved_classification();
8788 assert!(matches!(resolved, Cow::Borrowed(_)));
8789 assert_eq!(&*resolved, &authored);
8790 }
8791
8792 /// ABSENT-slot pin — an [`EphemeralSpec`] whose
8793 /// [`EphemeralSpec::classification`] slot is `None` returns
8794 /// [`Cow::Owned`] with the SAME value the sibling
8795 /// [`default_ephemeral_class`] baseline produces. Pins the
8796 /// two-surface parity contract with `From<EphemeralSpec> for
8797 /// ProcessSpec`: both sites fill through the SAME baseline on
8798 /// `None`, so the ephemeral require-tag surface's future
8799 /// `point-type-<kind>` family reads identically on the authored
8800 /// spec and on the mechanically lowered `ProcessSpec`.
8801 #[test]
8802 fn resolved_classification_fills_default_on_absent_slot() {
8803 let spec = empty_ephemeral();
8804 assert!(spec.classification.is_none());
8805 let resolved = spec.resolved_classification();
8806 assert!(matches!(resolved, Cow::Owned(_)));
8807 assert_eq!(&*resolved, &default_ephemeral_class());
8808 }
8809
8810 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8811 /// [`EphemeralSpec::classification`] slot names a concrete
8812 /// [`Classification`] returns `true` from
8813 /// [`Self::has_point_type`] on the authored
8814 /// [`ConvergencePointType`] slot and `false` for every other
8815 /// variant. Sweep the [`ConvergencePointType::ALL`] × ALL cross so
8816 /// a regression that hard-coded the arm to a single kind or wired
8817 /// the closure to a fixed unrelated slot fails HERE at the
8818 /// substrate primitive. Byte-for-byte peer of
8819 /// [`crate::classification::tests`]'s point-surface
8820 /// [`Classification::has_point_type`] populated-slot sweep on the
8821 /// SAME closed-set primitive.
8822 #[test]
8823 fn has_point_type_returns_true_iff_authored_classification_matches_per_kind() {
8824 for populated in ConvergencePointType::ALL {
8825 let mut classification = Classification::gate_compute();
8826 classification.point_type = populated;
8827 let mut spec = empty_ephemeral();
8828 spec.classification = Some(classification);
8829 for query in ConvergencePointType::ALL {
8830 let expected = query == populated;
8831 assert_eq!(
8832 spec.has_point_type(query),
8833 expected,
8834 "ephemeral classification.point_type={populated:?}: query {query:?} drifted",
8835 );
8836 }
8837 }
8838 }
8839
8840 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8841 /// [`EphemeralSpec::classification`] slot is `None` returns
8842 /// `true` from [`Self::has_point_type`] on
8843 /// [`ConvergencePointType::Gate`] (the `default_ephemeral_class`
8844 /// baseline's `point_type`) and `false` on every other variant.
8845 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
8846 /// default-arm short-circuit: on the ephemeral sugar surface the
8847 /// parent Option is filled through the workspace baseline rather
8848 /// than reading `false` on every variant like the encapsulation-
8849 /// mode / encapsulation-target / routing-form Option-parent
8850 /// corners.
8851 #[test]
8852 fn has_point_type_probes_gate_only_on_absent_classification() {
8853 let spec = empty_ephemeral();
8854 assert!(spec.classification.is_none());
8855 for kind in ConvergencePointType::ALL {
8856 let expected = kind == ConvergencePointType::Gate;
8857 assert_eq!(
8858 spec.has_point_type(kind),
8859 expected,
8860 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8861 );
8862 }
8863 }
8864
8865 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8866 /// identically through [`Self::has_point_type`] AND through
8867 /// `<eph.clone().into::<ProcessSpec>>()`
8868 /// `.classification.has_point_type(kind)` on the mechanically-
8869 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8870 /// classification on every [`ConvergencePointType::ALL`] variant)
8871 /// × ALL queries so a future regression on either side of the
8872 /// resolver (a shift in the ephemeral resolver's default, a
8873 /// shift in the `From<EphemeralSpec>` lowering's fill-through)
8874 /// fails HERE at the parity boundary.
8875 #[test]
8876 fn has_point_type_matches_point_peer_through_lowered_classification() {
8877 // Absent classification: both surfaces resolve through the SAME
8878 // default and agree on every variant.
8879 let eph = empty_ephemeral();
8880 let lowered: ProcessSpec = eph.clone().into();
8881 for query in ConvergencePointType::ALL {
8882 assert_eq!(
8883 eph.has_point_type(query),
8884 lowered.classification.has_point_type(query),
8885 "None-classification parity drift on query {query:?}",
8886 );
8887 }
8888 // Authored classification: both surfaces read the same authored
8889 // value verbatim.
8890 for populated in ConvergencePointType::ALL {
8891 let mut classification = Classification::gate_compute();
8892 classification.point_type = populated;
8893 let mut eph = empty_ephemeral();
8894 eph.classification = Some(classification);
8895 let lowered: ProcessSpec = eph.clone().into();
8896 for query in ConvergencePointType::ALL {
8897 assert_eq!(
8898 eph.has_point_type(query),
8899 lowered.classification.has_point_type(query),
8900 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8901 );
8902 }
8903 }
8904 }
8905
8906 // ── EphemeralSpec::has_substrate pins ────────────────────────────
8907 //
8908 // Fail-before-pass-after granularity: [`Self::has_substrate`] did
8909 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8910 // through `.resolved_classification().substrate == kind` or through
8911 // the lowered `ProcessSpec`'s `spec.classification.has_substrate`.
8912 // Post-lift the SECOND classification-axis peer on the ephemeral
8913 // sugar surface routes through the SAME
8914 // [`Self::resolved_classification`] resolver + the sibling closed-
8915 // set primitive [`Classification::has_substrate`], so a regression
8916 // that dropped the resolver hop, inverted the `Some`/`None`
8917 // fill-through, or wired the closure to a fixed unrelated slot
8918 // fails HERE.
8919
8920 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8921 /// [`EphemeralSpec::classification`] slot names a concrete
8922 /// [`Classification`] returns `true` from
8923 /// [`Self::has_substrate`] on the authored [`SubstrateType`] slot
8924 /// and `false` for every other variant. Sweep the
8925 /// [`SubstrateType::ALL`] × ALL cross so a regression that
8926 /// hard-coded the arm to a single kind or wired the closure to a
8927 /// fixed unrelated slot fails HERE at the substrate primitive.
8928 /// Byte-for-byte peer of the point-surface
8929 /// [`Classification::has_substrate`] populated-slot sweep on the
8930 /// SAME closed-set primitive.
8931 #[test]
8932 fn has_substrate_returns_true_iff_authored_classification_matches_per_kind() {
8933 for populated in SubstrateType::ALL {
8934 let mut classification = Classification::gate_compute();
8935 classification.substrate = populated;
8936 let mut spec = empty_ephemeral();
8937 spec.classification = Some(classification);
8938 for query in SubstrateType::ALL {
8939 let expected = query == populated;
8940 assert_eq!(
8941 spec.has_substrate(query),
8942 expected,
8943 "ephemeral classification.substrate={populated:?}: query {query:?} drifted",
8944 );
8945 }
8946 }
8947 }
8948
8949 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8950 /// [`EphemeralSpec::classification`] slot is `None` returns
8951 /// `true` from [`Self::has_substrate`] on
8952 /// [`SubstrateType::Compute`] (the `default_ephemeral_class`
8953 /// baseline's `substrate`) and `false` on every other variant.
8954 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
8955 /// default-arm short-circuit on the SECOND classification-axis
8956 /// peer: on the ephemeral sugar surface the parent Option is
8957 /// filled through the workspace baseline rather than reading
8958 /// `false` on every variant like the Option-parent encapsulates /
8959 /// routing corners.
8960 #[test]
8961 fn has_substrate_probes_compute_only_on_absent_classification() {
8962 let spec = empty_ephemeral();
8963 assert!(spec.classification.is_none());
8964 for kind in SubstrateType::ALL {
8965 let expected = kind == SubstrateType::Compute;
8966 assert_eq!(
8967 spec.has_substrate(kind),
8968 expected,
8969 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8970 );
8971 }
8972 }
8973
8974 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8975 /// identically through [`Self::has_substrate`] AND through
8976 /// `<eph.clone().into::<ProcessSpec>>()`
8977 /// `.classification.has_substrate(kind)` on the mechanically-
8978 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8979 /// classification on every [`SubstrateType::ALL`] variant) × ALL
8980 /// queries so a future regression on either side of the resolver
8981 /// (a shift in the ephemeral resolver's default, a shift in the
8982 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8983 /// the parity boundary. Byte-for-byte peer of the sibling
8984 /// [`Self::has_point_type`] two-surface parity pin on the SAME
8985 /// `Cow`-resolver carrier — the SECOND classification-axis
8986 /// two-surface parity contract on the ephemeral surface.
8987 #[test]
8988 fn has_substrate_matches_point_peer_through_lowered_classification() {
8989 // Absent classification: both surfaces resolve through the SAME
8990 // default and agree on every variant.
8991 let eph = empty_ephemeral();
8992 let lowered: ProcessSpec = eph.clone().into();
8993 for query in SubstrateType::ALL {
8994 assert_eq!(
8995 eph.has_substrate(query),
8996 lowered.classification.has_substrate(query),
8997 "None-classification parity drift on query {query:?}",
8998 );
8999 }
9000 // Authored classification: both surfaces read the same authored
9001 // value verbatim.
9002 for populated in SubstrateType::ALL {
9003 let mut classification = Classification::gate_compute();
9004 classification.substrate = populated;
9005 let mut eph = empty_ephemeral();
9006 eph.classification = Some(classification);
9007 let lowered: ProcessSpec = eph.clone().into();
9008 for query in SubstrateType::ALL {
9009 assert_eq!(
9010 eph.has_substrate(query),
9011 lowered.classification.has_substrate(query),
9012 "authored classification.substrate={populated:?}: parity drift on query {query:?}",
9013 );
9014 }
9015 }
9016 }
9017
9018 // ── EphemeralSpec::has_calm pins ─────────────────────────────────
9019 //
9020 // Fail-before-pass-after granularity: [`Self::has_calm`] did not
9021 // exist pre-lift on `impl EphemeralSpec` — every callsite went
9022 // through `.resolved_classification().calm == kind` or through the
9023 // lowered `ProcessSpec`'s `spec.classification.has_calm`. Post-
9024 // lift the THIRD classification-axis peer on the ephemeral sugar
9025 // surface routes through the SAME
9026 // [`Self::resolved_classification`] resolver + the sibling closed-
9027 // set primitive [`Classification::has_calm`], so a regression that
9028 // dropped the resolver hop, inverted the `Some`/`None` fill-
9029 // through, or wired the closure to a fixed unrelated slot fails
9030 // HERE. Distinct from the FIRST + SECOND peers on the (Option-
9031 // parent × NON-DEFAULT-scalar-child) corner: the (Option-parent ×
9032 // DEFAULTED-scalar-child) corner this peer opens has BOTH the
9033 // parent fill-through baseline (`default_ephemeral_class`) AND the
9034 // child's own `#[default]` land on the SAME variant
9035 // ([`CalmClassification::Monotone`]), a two-defaults composition
9036 // property the three pins below all exercise.
9037
9038 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
9039 /// [`EphemeralSpec::classification`] slot names a concrete
9040 /// [`Classification`] returns `true` from [`Self::has_calm`] on
9041 /// the authored [`CalmClassification`] slot and `false` for every
9042 /// other variant. Sweep the [`CalmClassification::ALL`] × ALL
9043 /// cross so a regression that hard-coded the arm to a single
9044 /// kind or wired the closure to a fixed unrelated slot fails HERE
9045 /// at the substrate primitive. Byte-for-byte peer of the point-
9046 /// surface [`Classification::has_calm`] populated-slot sweep on
9047 /// the SAME closed-set primitive.
9048 #[test]
9049 fn has_calm_returns_true_iff_authored_classification_matches_per_kind() {
9050 for populated in CalmClassification::ALL {
9051 let mut classification = Classification::gate_compute();
9052 classification.calm = populated;
9053 let mut spec = empty_ephemeral();
9054 spec.classification = Some(classification);
9055 for query in CalmClassification::ALL {
9056 let expected = query == populated;
9057 assert_eq!(
9058 spec.has_calm(query),
9059 expected,
9060 "ephemeral classification.calm={populated:?}: query {query:?} drifted",
9061 );
9062 }
9063 }
9064 }
9065
9066 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9067 /// [`EphemeralSpec::classification`] slot is `None` returns
9068 /// `true` from [`Self::has_calm`] on
9069 /// [`CalmClassification::Monotone`] (the `default_ephemeral_class`
9070 /// baseline's `calm` axis AND the [`CalmClassification`] child's
9071 /// own `#[default]` variant) and `false` on every other variant.
9072 /// Pins the (Option-parent × DEFAULTED-scalar-child ×
9073 /// operator-resolvable-baseline) corner's default-arm short-
9074 /// circuit on the THIRD classification-axis peer — distinct from
9075 /// the FIRST + SECOND peers on the (Option-parent × NON-DEFAULT-
9076 /// scalar-child) corner which default through a specific chosen
9077 /// baseline ([`ConvergencePointType::Gate`],
9078 /// [`SubstrateType::Compute`]) rather than through the child's
9079 /// own `#[default]`. Two-defaults composition property: both the
9080 /// parent fill-through and the child's `#[default]` land on the
9081 /// SAME variant, so the ephemeral sugar surface's `calm-Monotone`
9082 /// require-tag reads `true` on every operator-authored spec that
9083 /// omits both the `:classification` slot AND the `:calm` sub-slot,
9084 /// pinning the workspace's monotone-by-default posture.
9085 #[test]
9086 fn has_calm_probes_monotone_only_on_absent_classification() {
9087 let spec = empty_ephemeral();
9088 assert!(spec.classification.is_none());
9089 for kind in CalmClassification::ALL {
9090 let expected = kind == CalmClassification::Monotone;
9091 assert_eq!(
9092 spec.has_calm(kind),
9093 expected,
9094 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9095 );
9096 }
9097 }
9098
9099 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9100 /// identically through [`Self::has_calm`] AND through
9101 /// `<eph.clone().into::<ProcessSpec>>()`
9102 /// `.classification.has_calm(kind)` on the mechanically-
9103 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
9104 /// classification on every [`CalmClassification::ALL`] variant) ×
9105 /// ALL queries so a future regression on either side of the
9106 /// resolver (a shift in the ephemeral resolver's default, a shift
9107 /// in the `From<EphemeralSpec>` lowering's fill-through) fails
9108 /// HERE at the parity boundary. Byte-for-byte peer of the sibling
9109 /// [`Self::has_point_type`] + [`Self::has_substrate`] two-surface
9110 /// parity pins on the SAME `Cow`-resolver carrier — the THIRD
9111 /// classification-axis two-surface parity contract on the
9112 /// ephemeral surface, and the FIRST on the (Option-parent ×
9113 /// DEFAULTED-scalar-child) corner.
9114 #[test]
9115 fn has_calm_matches_point_peer_through_lowered_classification() {
9116 // Absent classification: both surfaces resolve through the SAME
9117 // default and agree on every variant.
9118 let eph = empty_ephemeral();
9119 let lowered: ProcessSpec = eph.clone().into();
9120 for query in CalmClassification::ALL {
9121 assert_eq!(
9122 eph.has_calm(query),
9123 lowered.classification.has_calm(query),
9124 "None-classification parity drift on query {query:?}",
9125 );
9126 }
9127 // Authored classification: both surfaces read the same authored
9128 // value verbatim.
9129 for populated in CalmClassification::ALL {
9130 let mut classification = Classification::gate_compute();
9131 classification.calm = populated;
9132 let mut eph = empty_ephemeral();
9133 eph.classification = Some(classification);
9134 let lowered: ProcessSpec = eph.clone().into();
9135 for query in CalmClassification::ALL {
9136 assert_eq!(
9137 eph.has_calm(query),
9138 lowered.classification.has_calm(query),
9139 "authored classification.calm={populated:?}: parity drift on query {query:?}",
9140 );
9141 }
9142 }
9143 }
9144
9145 // ── EphemeralSpec::has_data_classification pins ──────────────────
9146 //
9147 // Fail-before-pass-after granularity: [`Self::has_data_classification`]
9148 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
9149 // went through `.resolved_classification().data_classification ==
9150 // kind` or through the lowered `ProcessSpec`'s
9151 // `spec.classification.has_data_classification`. Post-lift the
9152 // FOURTH classification-axis peer on the ephemeral sugar surface
9153 // routes through the SAME [`Self::resolved_classification`]
9154 // resolver + the sibling closed-set primitive
9155 // [`crate::classification::Classification::has_data_classification`],
9156 // so a regression that dropped the resolver hop, inverted the
9157 // `Some`/`None` fill-through, or wired the closure to a fixed
9158 // unrelated slot fails HERE. SECOND occupant on the (Option-parent
9159 // × DEFAULTED-scalar-child × operator-resolvable-baseline) corner
9160 // alongside [`Self::has_calm`]: both the parent fill-through
9161 // baseline (`default_ephemeral_class`) AND the child's own
9162 // `#[default]` land on the SAME variant
9163 // ([`DataClassification::Internal`]), a two-defaults composition
9164 // property the three pins below all exercise.
9165
9166 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
9167 /// [`EphemeralSpec::classification`] slot names a concrete
9168 /// [`Classification`] returns `true` from
9169 /// [`Self::has_data_classification`] on the authored
9170 /// [`DataClassification`] slot and `false` for every other
9171 /// variant. Sweep the [`DataClassification::ALL`] × ALL cross so
9172 /// a regression that hard-coded the arm to a single kind or
9173 /// wired the closure to a fixed unrelated slot fails HERE at the
9174 /// substrate primitive. Byte-for-byte peer of the point-surface
9175 /// [`Classification::has_data_classification`] populated-slot
9176 /// sweep on the SAME closed-set primitive.
9177 #[test]
9178 fn has_data_classification_returns_true_iff_authored_classification_matches_per_kind() {
9179 for populated in DataClassification::ALL {
9180 let mut classification = Classification::gate_compute();
9181 classification.data_classification = populated;
9182 let mut spec = empty_ephemeral();
9183 spec.classification = Some(classification);
9184 for query in DataClassification::ALL {
9185 let expected = query == populated;
9186 assert_eq!(
9187 spec.has_data_classification(query),
9188 expected,
9189 "ephemeral classification.data_classification={populated:?}: query {query:?} drifted",
9190 );
9191 }
9192 }
9193 }
9194
9195 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9196 /// [`EphemeralSpec::classification`] slot is `None` returns
9197 /// `true` from [`Self::has_data_classification`] on
9198 /// [`DataClassification::Internal`] (the `default_ephemeral_class`
9199 /// baseline's `data_classification` axis AND the
9200 /// [`DataClassification`] child's own `#[default]` variant) and
9201 /// `false` on every other variant. Pins the (Option-parent ×
9202 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner's
9203 /// default-arm short-circuit on the FOURTH classification-axis
9204 /// peer — SECOND occupant on that corner after [`Self::has_calm`]
9205 /// opened it. Two-defaults composition property: both the parent
9206 /// fill-through and the child's `#[default]` land on the SAME
9207 /// variant, so the ephemeral sugar surface's
9208 /// `data-classification-Internal` require-tag reads `true` on
9209 /// every operator-authored spec that omits both the
9210 /// `:classification` slot AND the `:data-classification` sub-slot,
9211 /// pinning the workspace's internal-by-default sensitivity posture.
9212 #[test]
9213 fn has_data_classification_probes_internal_only_on_absent_classification() {
9214 let spec = empty_ephemeral();
9215 assert!(spec.classification.is_none());
9216 for kind in DataClassification::ALL {
9217 let expected = kind == DataClassification::Internal;
9218 assert_eq!(
9219 spec.has_data_classification(kind),
9220 expected,
9221 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9222 );
9223 }
9224 }
9225
9226 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9227 /// identically through [`Self::has_data_classification`] AND
9228 /// through `<eph.clone().into::<ProcessSpec>>()`
9229 /// `.classification.has_data_classification(kind)` on the
9230 /// mechanically-lowered `ProcessSpec`. Sweeps (`None`
9231 /// classification, `Some(_)` classification on every
9232 /// [`DataClassification::ALL`] variant) × ALL queries so a
9233 /// future regression on either side of the resolver (a shift in
9234 /// the ephemeral resolver's default, a shift in the
9235 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
9236 /// the parity boundary. Byte-for-byte peer of the sibling
9237 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
9238 /// [`Self::has_calm`] two-surface parity pins on the SAME
9239 /// `Cow`-resolver carrier — the FOURTH classification-axis
9240 /// two-surface parity contract on the ephemeral surface, and the
9241 /// SECOND on the (Option-parent × DEFAULTED-scalar-child) corner.
9242 #[test]
9243 fn has_data_classification_matches_point_peer_through_lowered_classification() {
9244 // Absent classification: both surfaces resolve through the SAME
9245 // default and agree on every variant.
9246 let eph = empty_ephemeral();
9247 let lowered: ProcessSpec = eph.clone().into();
9248 for query in DataClassification::ALL {
9249 assert_eq!(
9250 eph.has_data_classification(query),
9251 lowered.classification.has_data_classification(query),
9252 "None-classification parity drift on query {query:?}",
9253 );
9254 }
9255 // Authored classification: both surfaces read the same authored
9256 // value verbatim.
9257 for populated in DataClassification::ALL {
9258 let mut classification = Classification::gate_compute();
9259 classification.data_classification = populated;
9260 let mut eph = empty_ephemeral();
9261 eph.classification = Some(classification);
9262 let lowered: ProcessSpec = eph.clone().into();
9263 for query in DataClassification::ALL {
9264 assert_eq!(
9265 eph.has_data_classification(query),
9266 lowered.classification.has_data_classification(query),
9267 "authored classification.data_classification={populated:?}: parity drift on query {query:?}",
9268 );
9269 }
9270 }
9271 }
9272
9273 // ── EphemeralSpec::has_horizon_kind pins ─────────────────────────
9274 //
9275 // Fail-before-pass-after granularity: [`Self::has_horizon_kind`]
9276 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
9277 // went through `.resolved_classification().horizon.kind == kind`
9278 // or through the lowered `ProcessSpec`'s
9279 // `spec.classification.has_horizon_kind`. Post-lift the FIFTH
9280 // classification-axis peer on the ephemeral sugar surface routes
9281 // through the SAME [`Self::resolved_classification`] resolver +
9282 // the sibling closed-set primitive
9283 // [`crate::classification::Classification::has_horizon_kind`], so
9284 // a regression that dropped the resolver hop, inverted the
9285 // `Some`/`None` fill-through, or wired the closure to a fixed
9286 // unrelated slot fails HERE. OPENS a fresh (Option-parent ×
9287 // NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
9288 // corner on the ephemeral surface — distinct from the four prior
9289 // scalar-carrier peers on the (Option-parent × NON-DEFAULT-scalar-
9290 // child) and (Option-parent × DEFAULTED-scalar-child) corners, all
9291 // of which reach a discriminator DIRECTLY off a scalar
9292 // [`Classification`] slot. Both the parent Option's fill-through
9293 // baseline (`default_ephemeral_class`, which fills
9294 // `horizon: Horizon::default()`) AND the child's own `#[default]`
9295 // land on the SAME variant ([`HorizonKind::Bounded`]) — a two-
9296 // defaults composition property the three pins below all
9297 // exercise.
9298
9299 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
9300 /// [`EphemeralSpec::classification`] slot names a concrete
9301 /// [`Classification`] returns `true` from
9302 /// [`Self::has_horizon_kind`] on the authored [`HorizonKind`] slot
9303 /// and `false` for every other variant. Sweep the
9304 /// [`HorizonKind::ALL`] × ALL cross so a regression that hard-
9305 /// coded the arm to a single kind or wired the closure to a
9306 /// fixed unrelated slot (e.g. reading `self.classification` as if
9307 /// it were a scalar rather than routing through
9308 /// `resolved_classification().horizon.kind`) fails HERE at the
9309 /// substrate primitive. Byte-for-byte peer of the point-surface
9310 /// [`Classification::has_horizon_kind`] populated-slot sweep on
9311 /// the SAME closed-set primitive.
9312 #[test]
9313 fn has_horizon_kind_returns_true_iff_authored_classification_matches_per_kind() {
9314 for populated in HorizonKind::ALL {
9315 let classification = Classification::gate_compute_with_axis(populated);
9316 let mut spec = empty_ephemeral();
9317 spec.classification = Some(classification);
9318 for query in HorizonKind::ALL {
9319 let expected = query == populated;
9320 assert_eq!(
9321 spec.has_horizon_kind(query),
9322 expected,
9323 "ephemeral classification.horizon.kind={populated:?}: query {query:?} drifted",
9324 );
9325 }
9326 }
9327 }
9328
9329 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9330 /// [`EphemeralSpec::classification`] slot is `None` returns
9331 /// `true` from [`Self::has_horizon_kind`] on
9332 /// [`HorizonKind::Bounded`] (the `default_ephemeral_class`
9333 /// baseline's `horizon.kind` axis AND the [`HorizonKind`] child's
9334 /// own `#[default]` variant) and `false` on every other variant.
9335 /// Pins the fresh (Option-parent × NESTED-STRUCT-scalar-child ×
9336 /// operator-resolvable-baseline) corner's default-arm short-
9337 /// circuit on the FIFTH classification-axis peer. Two-defaults
9338 /// composition property through a NESTED-STRUCT hop: both the
9339 /// parent Option's fill-through baseline
9340 /// (`default_ephemeral_class` fills `horizon: Horizon::default()`)
9341 /// AND the child's own `#[default]` (`HorizonKind::Bounded` via
9342 /// `#[default]` on the closed set) land on the SAME variant, so
9343 /// the ephemeral sugar surface's `horizon-Bounded` require-tag
9344 /// reads `true` on every operator-authored spec that omits both
9345 /// the `:classification` slot AND the `:horizon` sub-slot,
9346 /// pinning the workspace's bounded-by-default lifetime posture.
9347 #[test]
9348 fn has_horizon_kind_probes_bounded_only_on_absent_classification() {
9349 let spec = empty_ephemeral();
9350 assert!(spec.classification.is_none());
9351 for kind in HorizonKind::ALL {
9352 let expected = kind == HorizonKind::Bounded;
9353 assert_eq!(
9354 spec.has_horizon_kind(kind),
9355 expected,
9356 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9357 );
9358 }
9359 }
9360
9361 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9362 /// identically through [`Self::has_horizon_kind`] AND through
9363 /// `<eph.clone().into::<ProcessSpec>>()`
9364 /// `.classification.has_horizon_kind(kind)` on the mechanically-
9365 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
9366 /// classification on every [`HorizonKind::ALL`] variant) × ALL
9367 /// queries so a future regression on either side of the resolver
9368 /// (a shift in the ephemeral resolver's default, a shift in the
9369 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
9370 /// the parity boundary. Byte-for-byte peer of the sibling
9371 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
9372 /// [`Self::has_calm`] + [`Self::has_data_classification`] two-
9373 /// surface parity pins on the SAME `Cow`-resolver carrier — the
9374 /// FIFTH classification-axis two-surface parity contract on the
9375 /// ephemeral surface, and the FIRST on the (Option-parent ×
9376 /// NESTED-STRUCT-scalar-child) corner.
9377 #[test]
9378 fn has_horizon_kind_matches_point_peer_through_lowered_classification() {
9379 // Absent classification: both surfaces resolve through the SAME
9380 // default and agree on every variant.
9381 let eph = empty_ephemeral();
9382 let lowered: ProcessSpec = eph.clone().into();
9383 for query in HorizonKind::ALL {
9384 assert_eq!(
9385 eph.has_horizon_kind(query),
9386 lowered.classification.has_horizon_kind(query),
9387 "None-classification parity drift on query {query:?}",
9388 );
9389 }
9390 // Authored classification: both surfaces read the same authored
9391 // value verbatim.
9392 for populated in HorizonKind::ALL {
9393 let classification = Classification::gate_compute_with_axis(populated);
9394 let mut eph = empty_ephemeral();
9395 eph.classification = Some(classification);
9396 let lowered: ProcessSpec = eph.clone().into();
9397 for query in HorizonKind::ALL {
9398 assert_eq!(
9399 eph.has_horizon_kind(query),
9400 lowered.classification.has_horizon_kind(query),
9401 "authored classification.horizon.kind={populated:?}: parity drift on query {query:?}",
9402 );
9403 }
9404 }
9405 }
9406
9407 // ── EphemeralSpec::has_optimization_direction pins ───────────────
9408 //
9409 // Fail-before-pass-after granularity:
9410 // [`Self::has_optimization_direction`] did not exist pre-lift on
9411 // `impl EphemeralSpec` — every callsite went through
9412 // `.resolved_classification().horizon.direction.unwrap_or_default() == kind`
9413 // or through the lowered `ProcessSpec`'s
9414 // `spec.classification.has_optimization_direction`. Post-lift the
9415 // SIXTH classification-axis peer on the ephemeral sugar surface
9416 // routes through the SAME [`Self::resolved_classification`]
9417 // resolver + the sibling closed-set primitive
9418 // [`crate::classification::Classification::has_optimization_direction`],
9419 // so a regression that dropped the resolver hop, inverted the
9420 // `Some`/`None` fill-through, wired the closure to a fixed
9421 // unrelated slot, or flipped [`OptimizationDirection`]'s
9422 // `#[default]` off `Minimize` fails HERE. SECOND occupant on the
9423 // (Option-parent × NESTED-STRUCT-scalar-child × operator-
9424 // resolvable-baseline) corner alongside
9425 // [`Self::has_horizon_kind`] — pinning the corner as a proven-
9426 // repeatable primitive shape on the ephemeral surface with a
9427 // second nested-struct-child probe, and DEMONSTRATING that the
9428 // corner admits both direct-scalar and Option-scalar traversals
9429 // through the SAME nested [`Horizon`] intermediary via the closed
9430 // set's `Default` on the inner `Option<OptimizationDirection>`
9431 // slot.
9432
9433 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
9434 /// [`EphemeralSpec::classification`] slot names a concrete
9435 /// [`Classification`] whose [`crate::classification::Horizon::direction`]
9436 /// slot carries `Some(<direction>)` returns `true` from
9437 /// [`Self::has_optimization_direction`] on the authored
9438 /// [`OptimizationDirection`] variant and `false` for every other
9439 /// variant. Sweep the [`OptimizationDirection::ALL`] × ALL cross
9440 /// so a regression that hard-coded the arm to a single kind, or
9441 /// dropped the `Option::unwrap_or_default` collapse, or wired the
9442 /// closure to a fixed unrelated slot (e.g. reading `self.horizon.kind`)
9443 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9444 /// point-surface
9445 /// [`Classification::has_optimization_direction`] populated-slot
9446 /// sweep on the SAME closed-set primitive.
9447 #[test]
9448 fn has_optimization_direction_returns_true_iff_authored_direction_matches_per_kind() {
9449 for populated in OptimizationDirection::ALL {
9450 let classification = Classification::gate_compute_with_axis(populated);
9451 let mut spec = empty_ephemeral();
9452 spec.classification = Some(classification);
9453 for query in OptimizationDirection::ALL {
9454 let expected = query == populated;
9455 assert_eq!(
9456 spec.has_optimization_direction(query),
9457 expected,
9458 "ephemeral classification.horizon.direction=Some({populated:?}): query {query:?} drifted",
9459 );
9460 }
9461 }
9462 }
9463
9464 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9465 /// [`EphemeralSpec::classification`] slot is `None` returns
9466 /// `true` from [`Self::has_optimization_direction`] on
9467 /// [`OptimizationDirection::Minimize`] (the `default_ephemeral_class`
9468 /// baseline fills `horizon: Horizon::default()`, which in turn
9469 /// leaves `direction: None`, and the substrate's
9470 /// `Option::unwrap_or_default` collapse then reads
9471 /// [`OptimizationDirection::Minimize`] via the closed set's
9472 /// `#[default]`) and `false` on every other variant. Pins the
9473 /// (Option-parent × NESTED-STRUCT-scalar-child × operator-
9474 /// resolvable-baseline) corner's default-arm short-circuit on the
9475 /// SIXTH classification-axis peer through TWO Option-hops: parent
9476 /// `EphemeralSpec::classification` and inner `Horizon::direction`
9477 /// both `None`, both collapsing to the closed set's `#[default]`
9478 /// [`OptimizationDirection::Minimize`]. A regression that promoted
9479 /// [`OptimizationDirection::Maximize`] to `#[default]` (silently
9480 /// inverting every unadorned Process's rate-window evaluator
9481 /// polarity), dropped `Option::unwrap_or_default`, or wired the arm
9482 /// to a fixed variant answer fails HERE.
9483 #[test]
9484 fn has_optimization_direction_probes_minimize_only_on_absent_classification() {
9485 let spec = empty_ephemeral();
9486 assert!(spec.classification.is_none());
9487 for kind in OptimizationDirection::ALL {
9488 let expected = kind == OptimizationDirection::Minimize;
9489 assert_eq!(
9490 spec.has_optimization_direction(kind),
9491 expected,
9492 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9493 );
9494 }
9495 }
9496
9497 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9498 /// identically through [`Self::has_optimization_direction`] AND
9499 /// through
9500 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
9501 /// on the mechanically-lowered `ProcessSpec`. Sweeps three arms —
9502 /// (`None` classification), (`Some(_)` classification with
9503 /// `direction: None`), and (`Some(_)` classification on every
9504 /// [`OptimizationDirection::ALL`] variant) — × ALL queries so a
9505 /// future regression on either side of the resolver (an ephemeral-
9506 /// side fill-through drift, a lowering-side `From<EphemeralSpec>`
9507 /// `unwrap_or_else(default_ephemeral_class)` drift, an inner
9508 /// `Option::unwrap_or_default` collapse drift on either side)
9509 /// fails HERE at the parity boundary. Byte-for-byte peer of the
9510 /// sibling [`Self::has_point_type`] + [`Self::has_substrate`] +
9511 /// [`Self::has_calm`] + [`Self::has_data_classification`] +
9512 /// [`Self::has_horizon_kind`] two-surface parity pins on the SAME
9513 /// `Cow`-resolver carrier — the SIXTH classification-axis two-
9514 /// surface parity contract on the ephemeral surface, and the
9515 /// SECOND on the (Option-parent × NESTED-STRUCT-scalar-child)
9516 /// corner.
9517 #[test]
9518 fn has_optimization_direction_matches_point_peer_through_lowered_classification() {
9519 // Absent classification: both surfaces resolve through the SAME
9520 // default and agree on every variant.
9521 let eph = empty_ephemeral();
9522 let lowered: ProcessSpec = eph.clone().into();
9523 for query in OptimizationDirection::ALL {
9524 assert_eq!(
9525 eph.has_optimization_direction(query),
9526 lowered.classification.has_optimization_direction(query),
9527 "None-classification parity drift on query {query:?}",
9528 );
9529 }
9530 // Authored classification with `direction: None` — the inner
9531 // Option collapses through `unwrap_or_default` on both sides,
9532 // reading `Minimize`.
9533 let mut classification = Classification::gate_compute();
9534 classification.horizon = Horizon::default();
9535 let mut eph = empty_ephemeral();
9536 eph.classification = Some(classification);
9537 let lowered: ProcessSpec = eph.clone().into();
9538 for query in OptimizationDirection::ALL {
9539 assert_eq!(
9540 eph.has_optimization_direction(query),
9541 lowered.classification.has_optimization_direction(query),
9542 "authored classification with horizon.direction=None: parity drift on query {query:?}",
9543 );
9544 }
9545 // Authored classification with `direction: Some(_)` — both
9546 // surfaces read the same authored value verbatim.
9547 for populated in OptimizationDirection::ALL {
9548 let classification = Classification::gate_compute_with_axis(populated);
9549 let mut eph = empty_ephemeral();
9550 eph.classification = Some(classification);
9551 let lowered: ProcessSpec = eph.clone().into();
9552 for query in OptimizationDirection::ALL {
9553 assert_eq!(
9554 eph.has_optimization_direction(query),
9555 lowered.classification.has_optimization_direction(query),
9556 "authored classification.horizon.direction=Some({populated:?}): parity drift on query {query:?}",
9557 );
9558 }
9559 }
9560 }
9561
9562 // ── EphemeralSpec::has_input_arity pins ──────────────────────────
9563 //
9564 // Fail-before-pass-after granularity: [`Self::has_input_arity`] did
9565 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
9566 // through `.resolved_classification().point_type.input_arity() ==
9567 // kind` or through the lowered `ProcessSpec`'s
9568 // `spec.classification.has_input_arity`. Post-lift the SEVENTH
9569 // classification-axis peer on the ephemeral sugar surface routes
9570 // through the SAME [`Self::resolved_classification`] resolver + the
9571 // sibling closed-set primitive
9572 // [`crate::classification::Classification::has_input_arity`], so a
9573 // regression that dropped the resolver hop, dropped the
9574 // `.input_arity()` projection call, inverted the projection (`One
9575 // ↔ Many`), or crossed the wires with the sibling
9576 // [`ConvergencePointType::output_arity`] projection fails HERE.
9577 // OPENS the (Option-parent × NESTED-STRUCT-scalar-child ×
9578 // derived-typed-projection) corner on the ephemeral surface —
9579 // distinct from the two prior nested-scalar peers on the corner
9580 // (`has_horizon_kind` reads `horizon.kind` directly;
9581 // `has_optimization_direction` reads `horizon.direction` through an
9582 // Option collapse), both of which reach a discriminator DIRECTLY off
9583 // a scalar. This peer instead threads through a many-to-one closed-
9584 // set typed projection so the child's closed set is REACHED THROUGH
9585 // a projection layer, pinning the corner as admitting three
9586 // ephemeral-surface traversal shapes (direct-scalar, Option-scalar-
9587 // with-default, derived-typed-projection) through the SAME resolver
9588 // walk.
9589
9590 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
9591 /// [`EphemeralSpec::classification`] slot names a concrete
9592 /// [`Classification`] with an authored [`ConvergencePointType`]
9593 /// returns `true` from [`Self::has_input_arity`] on the [`Arity`]
9594 /// value the projection [`ConvergencePointType::input_arity`] maps
9595 /// the authored point-type to and `false` for every other variant.
9596 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
9597 /// a regression that (a) dropped the projection call, (b) inverted
9598 /// the projection, (c) probed [`ConvergencePointType`] directly, or
9599 /// (d) crossed wires with [`ConvergencePointType::output_arity`]
9600 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9601 /// point-surface [`Classification::has_input_arity`] populated-slot
9602 /// sweep on the SAME closed-set primitive routed through the SAME
9603 /// projection.
9604 #[test]
9605 fn has_input_arity_returns_true_iff_authored_point_type_projects_per_kind() {
9606 for populated in ConvergencePointType::ALL {
9607 let mut classification = Classification::gate_compute();
9608 classification.point_type = populated;
9609 let mut spec = empty_ephemeral();
9610 spec.classification = Some(classification);
9611 let projected = populated.input_arity();
9612 for query in Arity::ALL {
9613 let expected = query == projected;
9614 assert_eq!(
9615 spec.has_input_arity(query),
9616 expected,
9617 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
9618 );
9619 }
9620 }
9621 }
9622
9623 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
9624 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
9625 /// from [`Self::has_input_arity`] on [`Arity::Many`] (the
9626 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
9627 /// and [`ConvergencePointType::input_arity`] projects
9628 /// `Gate → Arity::Many`) and `false` on [`Arity::One`]. Pins the
9629 /// (Option-parent × NESTED-STRUCT-scalar-child × derived-typed-
9630 /// projection) corner's baseline projection on the SEVENTH
9631 /// classification-axis peer through a chain of TWO fill-throughs
9632 /// composed with ONE projection: the parent Option's
9633 /// `unwrap_or_else(default_ephemeral_class)` picks the substrate
9634 /// baseline, and the projection then collapses the baseline's
9635 /// point-type through the closed-set-driven many-to-one bucket
9636 /// walk. [`Arity`] carries no `#[default]`, so there is NO default-
9637 /// arm short-circuit shortcut here — the answer flows entirely
9638 /// through the projection's bucket-membership decision. A
9639 /// regression that promoted the baseline's `point_type` off `Gate`
9640 /// (silently flipping every unadorned Process's convergent-by-
9641 /// default input-side posture to endomorphic or diffusive), dropped
9642 /// the projection call, inverted the projection, or crossed wires
9643 /// with [`ConvergencePointType::output_arity`] (which would flip
9644 /// the baseline answer from `Many` to `One` for `Gate`) fails HERE.
9645 #[test]
9646 fn has_input_arity_probes_many_only_on_absent_classification() {
9647 let spec = empty_ephemeral();
9648 assert!(spec.classification.is_none());
9649 for kind in Arity::ALL {
9650 let expected = kind == Arity::Many;
9651 assert_eq!(
9652 spec.has_input_arity(kind),
9653 expected,
9654 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many): query {kind:?} must be {expected}",
9655 );
9656 }
9657 }
9658
9659 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9660 /// identically through [`Self::has_input_arity`] AND through
9661 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
9662 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9663 /// classification, `Some(_)` classification on every
9664 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
9665 /// so a future regression on either side of the resolver (a shift
9666 /// in the ephemeral resolver's default, a shift in the
9667 /// `From<EphemeralSpec>` lowering's fill-through, a projection
9668 /// drift on either side) fails HERE at the parity boundary. Byte-
9669 /// for-byte peer of the sibling [`Self::has_point_type`] +
9670 /// [`Self::has_substrate`] + [`Self::has_calm`] +
9671 /// [`Self::has_data_classification`] + [`Self::has_horizon_kind`] +
9672 /// [`Self::has_optimization_direction`] two-surface parity pins on
9673 /// the SAME `Cow`-resolver carrier — the SEVENTH classification-
9674 /// axis two-surface parity contract on the ephemeral surface, and
9675 /// the FIRST on the (Option-parent × NESTED-STRUCT-scalar-child ×
9676 /// derived-typed-projection) corner.
9677 #[test]
9678 fn has_input_arity_matches_point_peer_through_lowered_classification() {
9679 // Absent classification: both surfaces resolve through the SAME
9680 // default and agree on every variant.
9681 let eph = empty_ephemeral();
9682 let lowered: ProcessSpec = eph.clone().into();
9683 for query in Arity::ALL {
9684 assert_eq!(
9685 eph.has_input_arity(query),
9686 lowered.classification.has_input_arity(query),
9687 "None-classification parity drift on query {query:?}",
9688 );
9689 }
9690 // Authored classification: both surfaces read the same authored
9691 // point_type and route through the same projection.
9692 for populated in ConvergencePointType::ALL {
9693 let mut classification = Classification::gate_compute();
9694 classification.point_type = populated;
9695 let mut eph = empty_ephemeral();
9696 eph.classification = Some(classification);
9697 let lowered: ProcessSpec = eph.clone().into();
9698 for query in Arity::ALL {
9699 assert_eq!(
9700 eph.has_input_arity(query),
9701 lowered.classification.has_input_arity(query),
9702 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
9703 );
9704 }
9705 }
9706 }
9707
9708 // ── EphemeralSpec::has_output_arity pins ─────────────────────────
9709 //
9710 // Fail-before-pass-after granularity: [`Self::has_output_arity`] did
9711 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
9712 // through `.resolved_classification().point_type.output_arity() ==
9713 // kind` or through the lowered `ProcessSpec`'s
9714 // `spec.classification.has_output_arity`. Post-lift the EIGHTH
9715 // classification-axis peer on the ephemeral sugar surface routes
9716 // through the SAME [`Self::resolved_classification`] resolver + the
9717 // sibling closed-set primitive
9718 // [`crate::classification::Classification::has_output_arity`], so a
9719 // regression that dropped the resolver hop, dropped the
9720 // `.output_arity()` projection call, inverted the projection (`One
9721 // ↔ Many`), or crossed the wires with the sibling
9722 // [`ConvergencePointType::input_arity`] projection fails HERE.
9723 // CLOSES the (Option-parent × NESTED-STRUCT-scalar-child ×
9724 // derived-typed-projection) corner on the ephemeral surface as the
9725 // SECOND occupant — co-tenant with [`Self::has_input_arity`] on the
9726 // SAME `point_type` scalar carrier through the SAME [`Arity`] closed
9727 // set but through the sibling many-to-one projection, closing the
9728 // DAG-composition arity pair on the ephemeral side.
9729
9730 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
9731 /// [`EphemeralSpec::classification`] slot names a concrete
9732 /// [`Classification`] with an authored [`ConvergencePointType`]
9733 /// returns `true` from [`Self::has_output_arity`] on the [`Arity`]
9734 /// value the projection [`ConvergencePointType::output_arity`] maps
9735 /// the authored point-type to and `false` for every other variant.
9736 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
9737 /// a regression that (a) dropped the projection call, (b) inverted
9738 /// the projection, (c) probed [`ConvergencePointType`] directly, or
9739 /// (d) crossed wires with [`ConvergencePointType::input_arity`]
9740 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9741 /// point-surface [`Classification::has_output_arity`] populated-slot
9742 /// sweep on the SAME closed-set primitive routed through the SAME
9743 /// projection.
9744 #[test]
9745 fn has_output_arity_returns_true_iff_authored_point_type_projects_per_kind() {
9746 for populated in ConvergencePointType::ALL {
9747 let mut classification = Classification::gate_compute();
9748 classification.point_type = populated;
9749 let mut spec = empty_ephemeral();
9750 spec.classification = Some(classification);
9751 let projected = populated.output_arity();
9752 for query in Arity::ALL {
9753 let expected = query == projected;
9754 assert_eq!(
9755 spec.has_output_arity(query),
9756 expected,
9757 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
9758 );
9759 }
9760 }
9761 }
9762
9763 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
9764 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
9765 /// from [`Self::has_output_arity`] on [`Arity::One`] (the
9766 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
9767 /// and [`ConvergencePointType::output_arity`] projects
9768 /// `Gate → Arity::One`) and `false` on [`Arity::Many`]. MIRROR of
9769 /// the [`Self::has_input_arity`] baseline (`Gate → input_arity =
9770 /// Many`) — the DAG-composition arity pair projects the same `Gate`
9771 /// baseline through the two projections to opposite [`Arity`] arms,
9772 /// so this pin locks the output-side half of that pair against a
9773 /// regression that (a) promoted the baseline's `point_type` off
9774 /// `Gate` (silently flipping every unadorned Process's convergent-
9775 /// by-default output-side posture to diffusive), (b) dropped the
9776 /// projection call, (c) inverted the projection, or (d) crossed
9777 /// wires with [`ConvergencePointType::input_arity`] (which would
9778 /// flip the baseline answer from `One` to `Many` for `Gate`).
9779 #[test]
9780 fn has_output_arity_probes_one_only_on_absent_classification() {
9781 let spec = empty_ephemeral();
9782 assert!(spec.classification.is_none());
9783 for kind in Arity::ALL {
9784 let expected = kind == Arity::One;
9785 assert_eq!(
9786 spec.has_output_arity(kind),
9787 expected,
9788 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One): query {kind:?} must be {expected}",
9789 );
9790 }
9791 }
9792
9793 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9794 /// identically through [`Self::has_output_arity`] AND through
9795 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
9796 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9797 /// classification, `Some(_)` classification on every
9798 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
9799 /// so a future regression on either side of the resolver fails HERE
9800 /// at the parity boundary. Byte-for-byte peer of the seven sibling
9801 /// two-surface parity pins on the SAME `Cow`-resolver carrier — the
9802 /// EIGHTH classification-axis two-surface parity contract on the
9803 /// ephemeral surface, closing the SECOND occupant of the (Option-
9804 /// parent × NESTED-STRUCT-scalar-child × derived-typed-projection)
9805 /// corner.
9806 #[test]
9807 fn has_output_arity_matches_point_peer_through_lowered_classification() {
9808 // Absent classification: both surfaces resolve through the SAME
9809 // default and agree on every variant.
9810 let eph = empty_ephemeral();
9811 let lowered: ProcessSpec = eph.clone().into();
9812 for query in Arity::ALL {
9813 assert_eq!(
9814 eph.has_output_arity(query),
9815 lowered.classification.has_output_arity(query),
9816 "None-classification parity drift on query {query:?}",
9817 );
9818 }
9819 // Authored classification: both surfaces read the same authored
9820 // point_type and route through the same projection.
9821 for populated in ConvergencePointType::ALL {
9822 let mut classification = Classification::gate_compute();
9823 classification.point_type = populated;
9824 let mut eph = empty_ephemeral();
9825 eph.classification = Some(classification);
9826 let lowered: ProcessSpec = eph.clone().into();
9827 for query in Arity::ALL {
9828 assert_eq!(
9829 eph.has_output_arity(query),
9830 lowered.classification.has_output_arity(query),
9831 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
9832 );
9833 }
9834 }
9835 }
9836
9837 /// DAG-COMPOSITION ARITY-PAIR pin — the SEVENTH
9838 /// ([`Self::has_input_arity`]) and EIGHTH
9839 /// ([`Self::has_output_arity`]) classification-axis peers on the
9840 /// ephemeral surface walk the SAME `point_type` scalar carrier
9841 /// (routed through the SAME [`Self::resolved_classification`]
9842 /// resolver) through the SAME [`Arity`] closed set but through
9843 /// DIFFERENT typed projections
9844 /// ([`ConvergencePointType::input_arity`] vs.
9845 /// [`ConvergencePointType::output_arity`]). An [`EphemeralSpec`]
9846 /// with `classification.point_type = Fork` (the diffusive `(One,
9847 /// Many)` cell) MUST simultaneously answer `has_input_arity(One)`
9848 /// true AND `has_output_arity(Many)` true AND
9849 /// `has_input_arity(Many)` false AND `has_output_arity(One)` false.
9850 /// An [`EphemeralSpec`] with `point_type = Transform` (endomorphic
9851 /// `(One, One)`) MUST answer BOTH `has_input_arity(One)` and
9852 /// `has_output_arity(One)` true — the two projections AGREE in the
9853 /// endomorphic bucket. The absent-classification baseline (Gate,
9854 /// convergent `(Many, One)`) MUST answer
9855 /// `has_input_arity(Many)` true AND `has_output_arity(One)` true —
9856 /// the mirror of the Fork case. A regression that (a) collapsed
9857 /// `has_output_arity` onto `has_input_arity`, (b) swapped the
9858 /// projection direction, or (c) drifted the topology-bucket
9859 /// contract fails HERE at ONE narrow ephemeral-surface site,
9860 /// symmetric with the point-surface DAG-composition arity-pair pin.
9861 #[test]
9862 fn has_input_arity_and_has_output_arity_pin_dag_composition_pair() {
9863 // Diffusive cell: Fork carries (input, output) = (One, Many)
9864 let mut classification = Classification::gate_compute();
9865 classification.point_type = ConvergencePointType::Fork;
9866 let mut fork = empty_ephemeral();
9867 fork.classification = Some(classification);
9868 assert!(fork.has_input_arity(Arity::One));
9869 assert!(fork.has_output_arity(Arity::Many));
9870 assert!(!fork.has_input_arity(Arity::Many));
9871 assert!(!fork.has_output_arity(Arity::One));
9872
9873 // Endomorphic cell: Transform carries (input, output) = (One, One)
9874 let mut classification = Classification::gate_compute();
9875 classification.point_type = ConvergencePointType::Transform;
9876 let mut transform = empty_ephemeral();
9877 transform.classification = Some(classification);
9878 assert!(transform.has_input_arity(Arity::One));
9879 assert!(transform.has_output_arity(Arity::One));
9880 assert!(!transform.has_input_arity(Arity::Many));
9881 assert!(!transform.has_output_arity(Arity::Many));
9882
9883 // Convergent cell: absent classification defaults to Gate,
9884 // which carries (input, output) = (Many, One).
9885 let gate = empty_ephemeral();
9886 assert!(gate.classification.is_none());
9887 assert!(gate.has_input_arity(Arity::Many));
9888 assert!(gate.has_output_arity(Arity::One));
9889 assert!(!gate.has_input_arity(Arity::One));
9890 assert!(!gate.has_output_arity(Arity::Many));
9891 }
9892
9893 // ── EphemeralSpec::horizon_terminates pins ───────────────────────
9894 //
9895 // Fail-before-pass-after granularity: `horizon_terminates` did not
9896 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9897 // the "does this ephemeral spec's horizon terminate?" question
9898 // went through `.resolved_classification().horizon.kind.terminates()`
9899 // or through the lowered `ProcessSpec`'s
9900 // `spec.classification.horizon.kind.terminates()`. Post-lift the
9901 // NINTH classification-axis peer on the ephemeral surface routes
9902 // through the SAME [`Self::resolved_classification`] resolver +
9903 // the sibling substrate primitive
9904 // [`crate::classification::Classification::horizon_terminates`],
9905 // so the two-surface parity contract holds by construction — a
9906 // regression on either side of the resolver fails at these pins
9907 // before landing at the operator-facing `terminating-horizon`
9908 // fixed tag in `tatara-check`.
9909
9910 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9911 /// [`Classification`] carries a specific [`HorizonKind`] variant
9912 /// answers [`Self::horizon_terminates`] matching the closed
9913 /// set's own [`HorizonKind::terminates`] truth table. Sweep
9914 /// [`HorizonKind::ALL`] so a regression that (a) hard-coded the
9915 /// body to a fixed answer, (b) inverted the projection, or (c)
9916 /// crossed the wires with the antisymmetric partner
9917 /// [`HorizonKind::requires_metric_axes`] fails HERE at the
9918 /// substrate primitive before drifting through the
9919 /// `terminating-horizon` fixed tag or the peer point surface.
9920 #[test]
9921 fn horizon_terminates_returns_horizon_kind_projection_per_kind() {
9922 for populated in HorizonKind::ALL {
9923 let classification = Classification::gate_compute_with_axis(populated);
9924 let mut spec = empty_ephemeral();
9925 spec.classification = Some(classification);
9926 assert_eq!(
9927 spec.horizon_terminates(),
9928 populated.terminates(),
9929 "authored horizon.kind={populated:?}: horizon_terminates() drift",
9930 );
9931 }
9932 }
9933
9934 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9935 /// with `classification: None` routes through the
9936 /// [`Self::resolved_classification`] resolver's substrate default
9937 /// [`Classification::gate_compute`], which uses
9938 /// [`crate::classification::Horizon::default`] whose `kind`
9939 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
9940 /// [`HorizonKind::Bounded::terminates`] projects `true`, so
9941 /// [`Self::horizon_terminates`] returns `true`. Pins the default-
9942 /// arm short-circuit through THREE layers of `Default`
9943 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
9944 /// [`HorizonKind::default`]) reaching this derived-nullary
9945 /// predicate — a regression that dropped the resolver hop
9946 /// (silently answering `false` on an absent classification, as
9947 /// if the operator's absence meant "no horizon at all") fails
9948 /// HERE at ONE narrow ephemeral-surface site.
9949 #[test]
9950 fn horizon_terminates_probes_true_on_absent_classification() {
9951 let spec = empty_ephemeral();
9952 assert!(spec.classification.is_none());
9953 assert!(
9954 spec.horizon_terminates(),
9955 "absent classification (defaults to gate_compute, horizon.kind=Bounded → terminates=true)",
9956 );
9957 }
9958
9959 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9960 /// identically through [`Self::horizon_terminates`] AND through
9961 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_terminates()`
9962 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9963 /// classification, `Some(_)` classification on every
9964 /// [`HorizonKind::ALL`] variant) so a future regression on
9965 /// either side of the resolver fails HERE at the parity
9966 /// boundary. Byte-for-byte peer of the eight sibling two-surface
9967 /// parity pins on the SAME `Cow`-resolver carrier — the NINTH
9968 /// classification-axis two-surface parity contract on the
9969 /// ephemeral surface, and the FIRST via a derived-nullary-
9970 /// boolean predicate rather than a variant-equality probe.
9971 #[test]
9972 fn horizon_terminates_matches_point_peer_through_lowered_classification() {
9973 // Absent classification: both surfaces resolve through the SAME
9974 // default and agree.
9975 let eph = empty_ephemeral();
9976 let lowered: ProcessSpec = eph.clone().into();
9977 assert_eq!(
9978 eph.horizon_terminates(),
9979 lowered.classification.horizon_terminates(),
9980 "None-classification parity drift",
9981 );
9982 // Authored classification: both surfaces read the same authored
9983 // horizon.kind and route through the same projection.
9984 for populated in HorizonKind::ALL {
9985 let classification = Classification::gate_compute_with_axis(populated);
9986 let mut eph = empty_ephemeral();
9987 eph.classification = Some(classification);
9988 let lowered: ProcessSpec = eph.clone().into();
9989 assert_eq!(
9990 eph.horizon_terminates(),
9991 lowered.classification.horizon_terminates(),
9992 "authored horizon.kind={populated:?}: parity drift",
9993 );
9994 }
9995 }
9996
9997 // ── EphemeralSpec::horizon_requires_metric_axes pins ─────────────
9998 //
9999 // Fail-before-pass-after granularity: `horizon_requires_metric_axes`
10000 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10001 // walking the "does this ephemeral spec's horizon require metric
10002 // axes?" question went through
10003 // `.resolved_classification().horizon.kind.requires_metric_axes()`
10004 // or through the lowered `ProcessSpec`'s
10005 // `spec.classification.horizon.kind.requires_metric_axes()`. Post-
10006 // lift the antisymmetric peer of `horizon_terminates` routes
10007 // through the SAME [`Self::resolved_classification`] resolver +
10008 // the sibling substrate primitive
10009 // [`crate::classification::Classification::horizon_requires_metric_axes`],
10010 // so the two-surface parity contract holds by construction — a
10011 // regression on either side of the resolver fails at these pins
10012 // before landing at the operator-facing `metric-axes-required`
10013 // fixed tag in `tatara-check`.
10014
10015 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10016 /// [`Classification`] carries a specific [`HorizonKind`] variant
10017 /// answers [`Self::horizon_requires_metric_axes`] matching the
10018 /// closed set's own [`HorizonKind::requires_metric_axes`] truth
10019 /// table. Sweep [`HorizonKind::ALL`] so a regression that (a)
10020 /// hard-coded the body to a fixed answer, (b) inverted the
10021 /// projection, or (c) crossed the wires with the antisymmetric
10022 /// partner [`HorizonKind::terminates`] fails HERE at the
10023 /// substrate primitive before drifting through the
10024 /// `metric-axes-required` fixed tag or the peer point surface.
10025 #[test]
10026 fn horizon_requires_metric_axes_returns_horizon_kind_projection_per_kind() {
10027 for populated in HorizonKind::ALL {
10028 let classification = Classification::gate_compute_with_axis(populated);
10029 let mut spec = empty_ephemeral();
10030 spec.classification = Some(classification);
10031 assert_eq!(
10032 spec.horizon_requires_metric_axes(),
10033 populated.requires_metric_axes(),
10034 "authored horizon.kind={populated:?}: horizon_requires_metric_axes() drift",
10035 );
10036 }
10037 }
10038
10039 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10040 /// with `classification: None` routes through the
10041 /// [`Self::resolved_classification`] resolver's substrate default
10042 /// [`Classification::gate_compute`], which uses
10043 /// [`crate::classification::Horizon::default`] whose `kind`
10044 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
10045 /// [`HorizonKind::Bounded::requires_metric_axes`] projects
10046 /// `false`, so [`Self::horizon_requires_metric_axes`] returns
10047 /// `false`. Pins the default-arm short-circuit through THREE
10048 /// layers of `Default` ([`Classification::gate_compute`] →
10049 /// [`Horizon::default`] → [`HorizonKind::default`]) reaching this
10050 /// derived-nullary predicate — mirror image of
10051 /// `horizon_terminates_probes_true_on_absent_classification`.
10052 #[test]
10053 fn horizon_requires_metric_axes_probes_false_on_absent_classification() {
10054 let spec = empty_ephemeral();
10055 assert!(spec.classification.is_none());
10056 assert!(
10057 !spec.horizon_requires_metric_axes(),
10058 "absent classification (defaults to gate_compute, horizon.kind=Bounded → requires_metric_axes=false)",
10059 );
10060 }
10061
10062 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10063 /// identically through [`Self::horizon_requires_metric_axes`]
10064 /// AND through
10065 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_requires_metric_axes()`
10066 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10067 /// classification, `Some(_)` classification on every
10068 /// [`HorizonKind::ALL`] variant) so a future regression on
10069 /// either side of the resolver fails HERE at the parity
10070 /// boundary. Byte-for-byte peer of the sibling
10071 /// `horizon_terminates_matches_point_peer_through_lowered_classification`.
10072 #[test]
10073 fn horizon_requires_metric_axes_matches_point_peer_through_lowered_classification() {
10074 // Absent classification.
10075 let eph = empty_ephemeral();
10076 let lowered: ProcessSpec = eph.clone().into();
10077 assert_eq!(
10078 eph.horizon_requires_metric_axes(),
10079 lowered.classification.horizon_requires_metric_axes(),
10080 "None-classification parity drift",
10081 );
10082 // Authored classification.
10083 for populated in HorizonKind::ALL {
10084 let classification = Classification::gate_compute_with_axis(populated);
10085 let mut eph = empty_ephemeral();
10086 eph.classification = Some(classification);
10087 let lowered: ProcessSpec = eph.clone().into();
10088 assert_eq!(
10089 eph.horizon_requires_metric_axes(),
10090 lowered.classification.horizon_requires_metric_axes(),
10091 "authored horizon.kind={populated:?}: parity drift",
10092 );
10093 }
10094 }
10095
10096 // ── EphemeralSpec::calm_requires_coordination pins ───────────────
10097 //
10098 // Fail-before-pass-after granularity: `calm_requires_coordination`
10099 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10100 // walking the "does this ephemeral spec require coordination?"
10101 // question went through
10102 // `.resolved_classification().calm.requires_coordination()` or
10103 // through the lowered `ProcessSpec`'s
10104 // `spec.classification.calm.requires_coordination()`. Post-lift the
10105 // THIRD derived-nullary-boolean peer on the ephemeral surface
10106 // (first on the calm axis, after the two horizon-axis peers)
10107 // routes through the SAME [`Self::resolved_classification`]
10108 // resolver + the sibling substrate primitive
10109 // [`crate::classification::Classification::calm_requires_coordination`],
10110 // so the two-surface parity contract holds by construction — a
10111 // regression on either side of the resolver fails at these pins
10112 // before landing at the operator-facing `coordination-required`
10113 // fixed tag in `tatara-check`.
10114
10115 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10116 /// [`Classification`] carries a specific [`CalmClassification`]
10117 /// variant answers [`Self::calm_requires_coordination`] matching
10118 /// the closed set's own
10119 /// [`CalmClassification::requires_coordination`] truth table.
10120 /// Sweep [`CalmClassification::ALL`] so a regression that (a)
10121 /// hard-coded the body to a fixed answer, (b) inverted the
10122 /// projection, or (c) crossed the wires with a sibling
10123 /// classification-axis probe fails HERE at the substrate primitive
10124 /// before drifting through the `coordination-required` fixed tag
10125 /// or the peer point surface.
10126 #[test]
10127 fn calm_requires_coordination_returns_calm_projection_per_kind() {
10128 for populated in CalmClassification::ALL {
10129 let mut classification = Classification::gate_compute();
10130 classification.calm = populated;
10131 let mut spec = empty_ephemeral();
10132 spec.classification = Some(classification);
10133 assert_eq!(
10134 spec.calm_requires_coordination(),
10135 populated.requires_coordination(),
10136 "authored calm={populated:?}: calm_requires_coordination() drift",
10137 );
10138 }
10139 }
10140
10141 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10142 /// with `classification: None` routes through the
10143 /// [`Self::resolved_classification`] resolver's substrate default
10144 /// [`Classification::gate_compute`], which carries
10145 /// [`CalmClassification::default = Monotone`], and
10146 /// [`CalmClassification::Monotone::requires_coordination`] projects
10147 /// `false`, so [`Self::calm_requires_coordination`] returns
10148 /// `false`. Pins the default-arm short-circuit through TWO layers
10149 /// of `Default` ([`Classification::gate_compute`] →
10150 /// [`CalmClassification::default`]) reaching this derived-nullary
10151 /// predicate — distinct from the sibling `horizon_*` absent-
10152 /// classification pins by ONE structural degree (those walk THREE
10153 /// layers of `Default` because horizon has a nested-struct wrapper;
10154 /// this walks TWO because `calm` is a direct scalar). A regression
10155 /// that dropped the resolver hop (silently answering `true` on an
10156 /// absent classification, as if the operator's absence meant
10157 /// "requires coordination") fails HERE at ONE narrow ephemeral-
10158 /// surface site.
10159 #[test]
10160 fn calm_requires_coordination_probes_false_on_absent_classification() {
10161 let spec = empty_ephemeral();
10162 assert!(spec.classification.is_none());
10163 assert!(
10164 !spec.calm_requires_coordination(),
10165 "absent classification (defaults to gate_compute, calm=Monotone → requires_coordination=false)",
10166 );
10167 }
10168
10169 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10170 /// identically through [`Self::calm_requires_coordination`] AND
10171 /// through
10172 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_requires_coordination()`
10173 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10174 /// classification, `Some(_)` classification on every
10175 /// [`CalmClassification::ALL`] variant) so a future regression on
10176 /// either side of the resolver fails HERE at the parity boundary.
10177 /// Byte-for-byte peer of the sibling
10178 /// `horizon_terminates_matches_point_peer_through_lowered_classification`
10179 /// on the calm axis.
10180 #[test]
10181 fn calm_requires_coordination_matches_point_peer_through_lowered_classification() {
10182 // Absent classification.
10183 let eph = empty_ephemeral();
10184 let lowered: ProcessSpec = eph.clone().into();
10185 assert_eq!(
10186 eph.calm_requires_coordination(),
10187 lowered.classification.calm_requires_coordination(),
10188 "None-classification parity drift",
10189 );
10190 // Authored classification.
10191 for populated in CalmClassification::ALL {
10192 let mut classification = Classification::gate_compute();
10193 classification.calm = populated;
10194 let mut eph = empty_ephemeral();
10195 eph.classification = Some(classification);
10196 let lowered: ProcessSpec = eph.clone().into();
10197 assert_eq!(
10198 eph.calm_requires_coordination(),
10199 lowered.classification.calm_requires_coordination(),
10200 "authored calm={populated:?}: parity drift",
10201 );
10202 }
10203 }
10204
10205 // ── EphemeralSpec::data_is_regulated pins ────────────────────────
10206 //
10207 // Fail-before-pass-after granularity: `data_is_regulated` did not
10208 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10209 // the "does this ephemeral spec carry regulated data?" question
10210 // went through
10211 // `.resolved_classification().data_classification.is_regulated()`
10212 // or through the lowered `ProcessSpec`'s
10213 // `spec.classification.data_classification.is_regulated()`. Post-
10214 // lift the FOURTH derived-nullary-boolean peer on the ephemeral
10215 // surface (first on the data axis, after two horizon-axis peers
10216 // and one calm-axis peer) routes through the SAME
10217 // [`Self::resolved_classification`] resolver + the sibling
10218 // substrate primitive
10219 // [`crate::classification::Classification::data_is_regulated`],
10220 // so the two-surface parity contract holds by construction — a
10221 // regression on either side of the resolver fails at these pins
10222 // before landing at the operator-facing `data-regulated` fixed
10223 // tag in `tatara-check`.
10224
10225 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10226 /// [`Classification`] carries a specific [`DataClassification`]
10227 /// variant answers [`Self::data_is_regulated`] matching the
10228 /// closed set's own [`DataClassification::is_regulated`] truth
10229 /// table. Sweep [`DataClassification::ALL`] so a regression that
10230 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10231 /// projection, or (c) crossed the wires with a sibling
10232 /// classification-axis probe fails HERE at the substrate
10233 /// primitive before drifting through the `data-regulated` fixed
10234 /// tag or the peer point surface.
10235 #[test]
10236 fn data_is_regulated_returns_data_classification_projection_per_kind() {
10237 for populated in DataClassification::ALL {
10238 let mut classification = Classification::gate_compute();
10239 classification.data_classification = populated;
10240 let mut spec = empty_ephemeral();
10241 spec.classification = Some(classification);
10242 assert_eq!(
10243 spec.data_is_regulated(),
10244 populated.is_regulated(),
10245 "authored data_classification={populated:?}: data_is_regulated() drift",
10246 );
10247 }
10248 }
10249
10250 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10251 /// with `classification: None` routes through the
10252 /// [`Self::resolved_classification`] resolver's substrate default
10253 /// [`Classification::gate_compute`], which carries
10254 /// [`DataClassification::default = Internal`], and
10255 /// [`DataClassification::Internal::is_regulated`] projects
10256 /// `false`, so [`Self::data_is_regulated`] returns `false`. Pins
10257 /// the default-arm short-circuit through TWO layers of `Default`
10258 /// ([`Classification::gate_compute`] →
10259 /// [`DataClassification::default`]) reaching this derived-nullary
10260 /// predicate — byte-for-byte structural peer of the sibling
10261 /// `calm_requires_coordination_probes_false_on_absent_classification`
10262 /// on the classification-data axis, distinct from the two
10263 /// `horizon_*` absent-classification pins by ONE structural
10264 /// degree (those walk THREE layers because horizon has a nested-
10265 /// struct wrapper; this walks TWO because `data_classification`
10266 /// is a direct scalar). A regression that dropped the resolver
10267 /// hop (silently answering `true` on an absent classification,
10268 /// as if the operator's absence meant "regulated data") fails
10269 /// HERE at ONE narrow ephemeral-surface site.
10270 #[test]
10271 fn data_is_regulated_probes_false_on_absent_classification() {
10272 let spec = empty_ephemeral();
10273 assert!(spec.classification.is_none());
10274 assert!(
10275 !spec.data_is_regulated(),
10276 "absent classification (defaults to gate_compute, data_classification=Internal → is_regulated=false)",
10277 );
10278 }
10279
10280 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10281 /// identically through [`Self::data_is_regulated`] AND through
10282 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_regulated()`
10283 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10284 /// classification, `Some(_)` classification on every
10285 /// [`DataClassification::ALL`] variant) so a future regression on
10286 /// either side of the resolver fails HERE at the parity boundary.
10287 /// Byte-for-byte peer of the sibling
10288 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
10289 /// on the data axis.
10290 #[test]
10291 fn data_is_regulated_matches_point_peer_through_lowered_classification() {
10292 // Absent classification.
10293 let eph = empty_ephemeral();
10294 let lowered: ProcessSpec = eph.clone().into();
10295 assert_eq!(
10296 eph.data_is_regulated(),
10297 lowered.classification.data_is_regulated(),
10298 "None-classification parity drift",
10299 );
10300 // Authored classification.
10301 for populated in DataClassification::ALL {
10302 let mut classification = Classification::gate_compute();
10303 classification.data_classification = populated;
10304 let mut eph = empty_ephemeral();
10305 eph.classification = Some(classification);
10306 let lowered: ProcessSpec = eph.clone().into();
10307 assert_eq!(
10308 eph.data_is_regulated(),
10309 lowered.classification.data_is_regulated(),
10310 "authored data_classification={populated:?}: parity drift",
10311 );
10312 }
10313 }
10314
10315 // ── EphemeralSpec::data_is_restricted pins ───────────────────────
10316 //
10317 // Fail-before-pass-after granularity: `data_is_restricted` did not
10318 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10319 // the "does this ephemeral spec require access controls?" question
10320 // went through
10321 // `.resolved_classification().data_classification.is_restricted()`
10322 // or through the lowered `ProcessSpec`'s
10323 // `spec.classification.data_classification.is_restricted()`. Post-
10324 // lift the FIFTH derived-nullary-boolean peer on the ephemeral
10325 // surface (second on the data axis, after
10326 // [`Self::data_is_regulated`] opened the axis) routes through the
10327 // SAME [`Self::resolved_classification`] resolver + the sibling
10328 // substrate primitive
10329 // [`crate::classification::Classification::data_is_restricted`],
10330 // so the two-surface parity contract holds by construction — a
10331 // regression on either side of the resolver fails at these pins
10332 // before landing at the operator-facing `data-restricted` fixed
10333 // tag in `tatara-check`. FIRST direct-scalar ephemeral-surface
10334 // peer whose absent-classification baseline projects to `true`
10335 // rather than `false`.
10336
10337 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10338 /// [`Classification`] carries a specific [`DataClassification`]
10339 /// variant answers [`Self::data_is_restricted`] matching the
10340 /// closed set's own [`DataClassification::is_restricted`] truth
10341 /// table. Sweep [`DataClassification::ALL`] so a regression that
10342 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10343 /// projection, or (c) crossed the wires with the sibling
10344 /// [`DataClassification::is_regulated`] projection fails HERE at
10345 /// the substrate primitive before drifting through the
10346 /// `data-restricted` fixed tag or the peer point surface.
10347 #[test]
10348 fn data_is_restricted_returns_data_classification_projection_per_kind() {
10349 for populated in DataClassification::ALL {
10350 let mut classification = Classification::gate_compute();
10351 classification.data_classification = populated;
10352 let mut spec = empty_ephemeral();
10353 spec.classification = Some(classification);
10354 assert_eq!(
10355 spec.data_is_restricted(),
10356 populated.is_restricted(),
10357 "authored data_classification={populated:?}: data_is_restricted() drift",
10358 );
10359 }
10360 }
10361
10362 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10363 /// with `classification: None` routes through the
10364 /// [`Self::resolved_classification`] resolver's substrate default
10365 /// [`Classification::gate_compute`], which carries
10366 /// [`DataClassification::default = Internal`], and
10367 /// [`DataClassification::Internal::is_restricted`] projects
10368 /// `true`, so [`Self::data_is_restricted`] returns `true`. Pins
10369 /// the default-arm short-circuit through TWO layers of `Default`
10370 /// ([`Classification::gate_compute`] →
10371 /// [`DataClassification::default`]) reaching this derived-nullary
10372 /// predicate. FIRST direct-scalar ephemeral-surface peer whose
10373 /// absent-classification baseline answers `true`, not `false`
10374 /// (the four earlier direct-scalar peers on this surface —
10375 /// `data_is_regulated`, `calm_requires_coordination`, plus the
10376 /// nested-struct `horizon_requires_metric_axes` — all project
10377 /// `false` on the same absent classification, and only the
10378 /// sibling nested-struct `horizon_terminates` projects `true`).
10379 /// A regression that dropped the resolver hop (silently answering
10380 /// `false` on an absent classification, as if the operator's
10381 /// absence meant "freely distributable"), or that inverted the
10382 /// projection while the closed-set primitive stayed intact,
10383 /// fails HERE at ONE narrow ephemeral-surface site.
10384 #[test]
10385 fn data_is_restricted_probes_true_on_absent_classification() {
10386 let spec = empty_ephemeral();
10387 assert!(spec.classification.is_none());
10388 assert!(
10389 spec.data_is_restricted(),
10390 "absent classification (defaults to gate_compute, data_classification=Internal → is_restricted=true)",
10391 );
10392 }
10393
10394 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10395 /// identically through [`Self::data_is_restricted`] AND through
10396 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_restricted()`
10397 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10398 /// classification, `Some(_)` classification on every
10399 /// [`DataClassification::ALL`] variant) so a future regression on
10400 /// either side of the resolver fails HERE at the parity boundary.
10401 /// Byte-for-byte peer of the sibling
10402 /// `data_is_regulated_matches_point_peer_through_lowered_classification`
10403 /// on the same classification-data axis, published a second time
10404 /// through the antisymmetric closed-set projection.
10405 #[test]
10406 fn data_is_restricted_matches_point_peer_through_lowered_classification() {
10407 // Absent classification.
10408 let eph = empty_ephemeral();
10409 let lowered: ProcessSpec = eph.clone().into();
10410 assert_eq!(
10411 eph.data_is_restricted(),
10412 lowered.classification.data_is_restricted(),
10413 "None-classification parity drift",
10414 );
10415 // Authored classification.
10416 for populated in DataClassification::ALL {
10417 let mut classification = Classification::gate_compute();
10418 classification.data_classification = populated;
10419 let mut eph = empty_ephemeral();
10420 eph.classification = Some(classification);
10421 let lowered: ProcessSpec = eph.clone().into();
10422 assert_eq!(
10423 eph.data_is_restricted(),
10424 lowered.classification.data_is_restricted(),
10425 "authored data_classification={populated:?}: parity drift",
10426 );
10427 }
10428 }
10429
10430 /// COMPOSED IMPLICATION pin — the ephemeral-surface counterpart of
10431 /// the closed-set-internal
10432 /// `data_classification_regulated_implies_restricted` and its
10433 /// parent-composed peer
10434 /// `classification_data_is_regulated_implies_data_is_restricted_over_all`:
10435 /// for every ([`EphemeralSpec`] with authored classification
10436 /// carrying every [`DataClassification`] variant, plus the
10437 /// absent-classification case), the resolver-hop probe pair
10438 /// satisfies `data_is_regulated() ⇒ data_is_restricted()`. Pins
10439 /// the implication contract at the ephemeral-surface site so a
10440 /// regression that (a) inverted the ephemeral
10441 /// [`Self::data_is_regulated`] resolver hop, (b) inverted the
10442 /// ephemeral [`Self::data_is_restricted`] resolver hop, or (c)
10443 /// crossed their wires while the underlying substrate primitives
10444 /// stayed intact fails HERE. FIRST ephemeral-surface corner-peer
10445 /// pair whose two projections carry a non-trivial closed-set-
10446 /// internal implication relationship.
10447 #[test]
10448 fn ephemeral_data_is_regulated_implies_data_is_restricted_over_all() {
10449 // Absent classification.
10450 let eph = empty_ephemeral();
10451 assert!(
10452 !eph.data_is_regulated() || eph.data_is_restricted(),
10453 "None-classification: data_is_regulated ⇒ data_is_restricted violated",
10454 );
10455 // Authored classification.
10456 for populated in DataClassification::ALL {
10457 let mut classification = Classification::gate_compute();
10458 classification.data_classification = populated;
10459 let mut eph = empty_ephemeral();
10460 eph.classification = Some(classification);
10461 assert!(
10462 !eph.data_is_regulated() || eph.data_is_restricted(),
10463 "authored data_classification={populated:?}: data_is_regulated ⇒ data_is_restricted violated",
10464 );
10465 }
10466 }
10467
10468 // ── EphemeralSpec::point_is_endomorphic pins ─────────────────────
10469 //
10470 // Fail-before-pass-after granularity: `point_is_endomorphic` did
10471 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10472 // walking the "does this ephemeral spec's point-type project to
10473 // the 1→1 endomorphic bucket?" question went through
10474 // `.resolved_classification().point_type.is_endomorphic()` or the
10475 // lowered `ProcessSpec`'s
10476 // `spec.classification.point_type.is_endomorphic()`. Post-lift the
10477 // SIXTH derived-nullary-boolean peer on the ephemeral surface
10478 // (first on the `point_type` axis) routes through the SAME
10479 // [`Self::resolved_classification`] resolver + the sibling
10480 // substrate primitive
10481 // [`crate::classification::Classification::point_is_endomorphic`],
10482 // so the two-surface parity contract holds by construction — a
10483 // regression on either side of the resolver fails at these pins
10484 // before landing at the operator-facing `endomorphic-point` fixed
10485 // tag in `tatara-check`.
10486
10487 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10488 /// [`Classification`] carries a specific [`ConvergencePointType`]
10489 /// variant answers [`Self::point_is_endomorphic`] matching the
10490 /// closed set's own [`ConvergencePointType::is_endomorphic`] truth
10491 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10492 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10493 /// projection, or (c) crossed the wires with the sibling
10494 /// [`ConvergencePointType::is_diffusive`] /
10495 /// [`ConvergencePointType::is_convergent`] projections fails
10496 /// HERE at the substrate primitive before drifting through the
10497 /// `endomorphic-point` fixed tag or the peer point surface.
10498 #[test]
10499 fn point_is_endomorphic_returns_point_type_projection_per_kind() {
10500 for populated in ConvergencePointType::ALL {
10501 let mut classification = Classification::gate_compute();
10502 classification.point_type = populated;
10503 let mut spec = empty_ephemeral();
10504 spec.classification = Some(classification);
10505 assert_eq!(
10506 spec.point_is_endomorphic(),
10507 populated.is_endomorphic(),
10508 "authored point_type={populated:?}: point_is_endomorphic() drift",
10509 );
10510 }
10511 }
10512
10513 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10514 /// with `classification: None` routes through the
10515 /// [`Self::resolved_classification`] resolver's substrate default
10516 /// [`Classification::gate_compute`], which carries
10517 /// [`ConvergencePointType::Gate`] (a convergent barrier, not an
10518 /// endomorphism), and
10519 /// [`ConvergencePointType::Gate::is_endomorphic`] projects `false`,
10520 /// so [`Self::point_is_endomorphic`] returns `false`. Pins the
10521 /// resolver's chosen-field baseline at ONE narrow site — a
10522 /// regression that dropped the resolver hop, or that promoted
10523 /// [`ConvergencePointType::Transform`] to the gate-compute
10524 /// baseline (silently retargeting every unadorned ephemeral
10525 /// spec's topology bucket), fails HERE at ONE narrow ephemeral-
10526 /// surface site. FIRST direct-scalar ephemeral-surface peer whose
10527 /// absent-classification baseline is a chosen-field answer on the
10528 /// resolver's [`Classification::gate_compute`] default rather
10529 /// than a substrate-`#[default]` short-circuit on the closed-set
10530 /// side ([`ConvergencePointType`] has no `impl Default`).
10531 #[test]
10532 fn point_is_endomorphic_probes_false_on_absent_classification() {
10533 let spec = empty_ephemeral();
10534 assert!(spec.classification.is_none());
10535 assert!(
10536 !spec.point_is_endomorphic(),
10537 "absent classification (defaults to gate_compute, point_type=Gate → is_endomorphic=false)",
10538 );
10539 }
10540
10541 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10542 /// identically through [`Self::point_is_endomorphic`] AND through
10543 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_endomorphic()`
10544 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10545 /// classification, `Some(_)` classification on every
10546 /// [`ConvergencePointType::ALL`] variant) so a future regression
10547 /// on either side of the resolver fails HERE at the parity
10548 /// boundary. Byte-for-byte peer of the sibling
10549 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
10550 /// on a DIFFERENT closed-set axis, published a first time through
10551 /// the `point_type` closed-set projection.
10552 #[test]
10553 fn point_is_endomorphic_matches_point_peer_through_lowered_classification() {
10554 // Absent classification.
10555 let eph = empty_ephemeral();
10556 let lowered: ProcessSpec = eph.clone().into();
10557 assert_eq!(
10558 eph.point_is_endomorphic(),
10559 lowered.classification.point_is_endomorphic(),
10560 "None-classification parity drift",
10561 );
10562 // Authored classification.
10563 for populated in ConvergencePointType::ALL {
10564 let mut classification = Classification::gate_compute();
10565 classification.point_type = populated;
10566 let mut eph = empty_ephemeral();
10567 eph.classification = Some(classification);
10568 let lowered: ProcessSpec = eph.clone().into();
10569 assert_eq!(
10570 eph.point_is_endomorphic(),
10571 lowered.classification.point_is_endomorphic(),
10572 "authored point_type={populated:?}: parity drift",
10573 );
10574 }
10575 }
10576
10577 // ── EphemeralSpec::point_is_diffusive pins ───────────────────────
10578 //
10579 // Fail-before-pass-after granularity: `point_is_diffusive` did not
10580 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10581 // the "does this ephemeral spec's point-type project to the 1→N
10582 // diffusive fan-out bucket?" question went through
10583 // `.resolved_classification().point_type.is_diffusive()` or the
10584 // lowered `ProcessSpec`'s
10585 // `spec.classification.point_type.is_diffusive()`. Post-lift the
10586 // SEVENTH derived-nullary-boolean peer on the ephemeral surface
10587 // (SECOND on the `point_type` axis) routes through the SAME
10588 // [`Self::resolved_classification`] resolver + the sibling
10589 // substrate primitive
10590 // [`crate::classification::Classification::point_is_diffusive`],
10591 // so the two-surface parity contract holds by construction.
10592
10593 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10594 /// [`Classification`] carries a specific [`ConvergencePointType`]
10595 /// variant answers [`Self::point_is_diffusive`] matching the
10596 /// closed set's own [`ConvergencePointType::is_diffusive`] truth
10597 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10598 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10599 /// projection, or (c) crossed the wires with the sibling
10600 /// [`ConvergencePointType::is_endomorphic`] /
10601 /// [`ConvergencePointType::is_convergent`] projections fails HERE
10602 /// at the substrate primitive before drifting through the
10603 /// `diffusive-point` fixed tag or the peer point surface.
10604 #[test]
10605 fn point_is_diffusive_returns_point_type_projection_per_kind() {
10606 for populated in ConvergencePointType::ALL {
10607 let mut classification = Classification::gate_compute();
10608 classification.point_type = populated;
10609 let mut spec = empty_ephemeral();
10610 spec.classification = Some(classification);
10611 assert_eq!(
10612 spec.point_is_diffusive(),
10613 populated.is_diffusive(),
10614 "authored point_type={populated:?}: point_is_diffusive() drift",
10615 );
10616 }
10617 }
10618
10619 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10620 /// with `classification: None` routes through the
10621 /// [`Self::resolved_classification`] resolver's substrate default
10622 /// [`Classification::gate_compute`], which carries
10623 /// [`ConvergencePointType::Gate`] (a convergent barrier, not a
10624 /// diffusive fan-out), and
10625 /// [`ConvergencePointType::Gate::is_diffusive`] projects `false`,
10626 /// so [`Self::point_is_diffusive`] returns `false`. Pins the
10627 /// resolver's chosen-field baseline at ONE narrow site.
10628 #[test]
10629 fn point_is_diffusive_probes_false_on_absent_classification() {
10630 let spec = empty_ephemeral();
10631 assert!(spec.classification.is_none());
10632 assert!(
10633 !spec.point_is_diffusive(),
10634 "absent classification (defaults to gate_compute, point_type=Gate → is_diffusive=false)",
10635 );
10636 }
10637
10638 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10639 /// identically through [`Self::point_is_diffusive`] AND through
10640 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_diffusive()`
10641 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10642 /// classification, `Some(_)` classification on every
10643 /// [`ConvergencePointType::ALL`] variant) so a future regression
10644 /// on either side of the resolver fails HERE at the parity
10645 /// boundary. Byte-for-byte peer of
10646 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
10647 /// on the SAME closed-set axis via a sibling projection.
10648 #[test]
10649 fn point_is_diffusive_matches_point_peer_through_lowered_classification() {
10650 // Absent classification.
10651 let eph = empty_ephemeral();
10652 let lowered: ProcessSpec = eph.clone().into();
10653 assert_eq!(
10654 eph.point_is_diffusive(),
10655 lowered.classification.point_is_diffusive(),
10656 "None-classification parity drift",
10657 );
10658 // Authored classification.
10659 for populated in ConvergencePointType::ALL {
10660 let mut classification = Classification::gate_compute();
10661 classification.point_type = populated;
10662 let mut eph = empty_ephemeral();
10663 eph.classification = Some(classification);
10664 let lowered: ProcessSpec = eph.clone().into();
10665 assert_eq!(
10666 eph.point_is_diffusive(),
10667 lowered.classification.point_is_diffusive(),
10668 "authored point_type={populated:?}: parity drift",
10669 );
10670 }
10671 }
10672
10673 /// MUTEX pin — [`Self::point_is_endomorphic`] AND
10674 /// [`Self::point_is_diffusive`] are NEVER simultaneously true for
10675 /// ANY [`EphemeralSpec`] (authored or defaulted), since the
10676 /// underlying [`ConvergencePointType`] closed set carves its
10677 /// eight variants into THREE disjoint buckets. Sweep the absent-
10678 /// classification case + every [`ConvergencePointType::ALL`]
10679 /// variant so a regression that crossed the wires between the
10680 /// two ephemeral-surface corner peers (one probe silently
10681 /// composing the wrong closed-set arm at the resolver-hop layer)
10682 /// fails HERE rather than at every downstream consumer that
10683 /// trusts the two probes partition the resolver's output into
10684 /// disjoint buckets. FIRST ephemeral-surface corner-peer pair on
10685 /// the `point_type` axis whose two projections carry a non-
10686 /// trivial closed-set-internal MUTEX relationship (distinct from
10687 /// the sibling `data`-axis pair whose two projections carry a
10688 /// non-trivial IMPLICATION relationship, sealed by
10689 /// `ephemeral_data_is_regulated_implies_data_is_restricted_over_all`).
10690 #[test]
10691 fn ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all() {
10692 // Absent classification.
10693 let eph = empty_ephemeral();
10694 assert!(
10695 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
10696 "None-classification: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
10697 );
10698 // Authored classification.
10699 for populated in ConvergencePointType::ALL {
10700 let mut classification = Classification::gate_compute();
10701 classification.point_type = populated;
10702 let mut eph = empty_ephemeral();
10703 eph.classification = Some(classification);
10704 assert!(
10705 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
10706 "authored point_type={populated:?}: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
10707 );
10708 }
10709 }
10710
10711 // ── EphemeralSpec::point_is_convergent pins ──────────────────────
10712 //
10713 // Fail-before-pass-after granularity: `point_is_convergent` did
10714 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10715 // walking the "does this ephemeral spec's point-type project to
10716 // the N→1 convergent fan-in bucket?" question went through
10717 // `.resolved_classification().point_type.is_convergent()` or the
10718 // lowered `ProcessSpec`'s
10719 // `spec.classification.point_type.is_convergent()`. Post-lift the
10720 // EIGHTH derived-nullary-boolean peer on the ephemeral surface
10721 // (THIRD on the `point_type` axis) routes through the SAME
10722 // [`Self::resolved_classification`] resolver + the sibling
10723 // substrate primitive
10724 // [`crate::classification::Classification::point_is_convergent`],
10725 // so the two-surface parity contract holds by construction, AND
10726 // the THREE `point_type`-axis peers on this surface close into
10727 // the FULL three-way XOR partition contract.
10728
10729 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10730 /// [`Classification`] carries a specific [`ConvergencePointType`]
10731 /// variant answers [`Self::point_is_convergent`] matching the
10732 /// closed set's own [`ConvergencePointType::is_convergent`] truth
10733 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10734 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10735 /// projection, or (c) crossed the wires with the sibling
10736 /// [`ConvergencePointType::is_endomorphic`] /
10737 /// [`ConvergencePointType::is_diffusive`] projections fails HERE
10738 /// at the substrate primitive before drifting through the
10739 /// `convergent-point` fixed tag or the peer point surface.
10740 #[test]
10741 fn point_is_convergent_returns_point_type_projection_per_kind() {
10742 for populated in ConvergencePointType::ALL {
10743 let mut classification = Classification::gate_compute();
10744 classification.point_type = populated;
10745 let mut spec = empty_ephemeral();
10746 spec.classification = Some(classification);
10747 assert_eq!(
10748 spec.point_is_convergent(),
10749 populated.is_convergent(),
10750 "authored point_type={populated:?}: point_is_convergent() drift",
10751 );
10752 }
10753 }
10754
10755 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10756 /// with `classification: None` routes through the
10757 /// [`Self::resolved_classification`] resolver's substrate default
10758 /// [`Classification::gate_compute`], which carries
10759 /// [`ConvergencePointType::Gate`] (the canonical convergent
10760 /// barrier), and [`ConvergencePointType::Gate::is_convergent`]
10761 /// projects `true`, so [`Self::point_is_convergent`] returns
10762 /// `true`. Pins the resolver's chosen-field baseline at ONE
10763 /// narrow site — FIRST direct-scalar ephemeral-surface peer whose
10764 /// absent-classification baseline projects `true` through the
10765 /// resolver's chosen-field answer, mirror-inverted from the two
10766 /// sibling `point_is_endomorphic` / `point_is_diffusive`
10767 /// ephemeral-surface baselines which both project `false`.
10768 #[test]
10769 fn point_is_convergent_probes_true_on_absent_classification() {
10770 let spec = empty_ephemeral();
10771 assert!(spec.classification.is_none());
10772 assert!(
10773 spec.point_is_convergent(),
10774 "absent classification (defaults to gate_compute, point_type=Gate → is_convergent=true)",
10775 );
10776 }
10777
10778 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10779 /// identically through [`Self::point_is_convergent`] AND through
10780 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_convergent()`
10781 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10782 /// classification, `Some(_)` classification on every
10783 /// [`ConvergencePointType::ALL`] variant) so a future regression
10784 /// on either side of the resolver fails HERE at the parity
10785 /// boundary. Byte-for-byte peer of
10786 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
10787 /// and
10788 /// `point_is_diffusive_matches_point_peer_through_lowered_classification`
10789 /// on the SAME closed-set axis via a sibling projection.
10790 #[test]
10791 fn point_is_convergent_matches_point_peer_through_lowered_classification() {
10792 // Absent classification.
10793 let eph = empty_ephemeral();
10794 let lowered: ProcessSpec = eph.clone().into();
10795 assert_eq!(
10796 eph.point_is_convergent(),
10797 lowered.classification.point_is_convergent(),
10798 "None-classification parity drift",
10799 );
10800 // Authored classification.
10801 for populated in ConvergencePointType::ALL {
10802 let mut classification = Classification::gate_compute();
10803 classification.point_type = populated;
10804 let mut eph = empty_ephemeral();
10805 eph.classification = Some(classification);
10806 let lowered: ProcessSpec = eph.clone().into();
10807 assert_eq!(
10808 eph.point_is_convergent(),
10809 lowered.classification.point_is_convergent(),
10810 "authored point_type={populated:?}: parity drift",
10811 );
10812 }
10813 }
10814
10815 /// THREE-WAY XOR PARTITION pin — for the absent-classification
10816 /// baseline AND every [`ConvergencePointType::ALL`] variant,
10817 /// EXACTLY ONE of [`Self::point_is_endomorphic`],
10818 /// [`Self::point_is_diffusive`], and [`Self::point_is_convergent`]
10819 /// returns `true`. Closes the mutex pair
10820 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`
10821 /// into the FULL ternary XOR partition contract on the ephemeral
10822 /// surface — the resolver-hop peer of the parent-composed
10823 /// `classification_point_type_probes_form_three_way_xor_partition_over_all`
10824 /// test. Guarantees the absent-classification case lands in the
10825 /// convergent bucket (`gate_compute` → Gate → is_convergent =
10826 /// true), so every unadorned `(defephemeral …)` audits under a
10827 /// definite non-empty topology bucket.
10828 #[test]
10829 fn ephemeral_point_type_probes_form_three_way_xor_partition_over_all() {
10830 // Absent classification.
10831 let eph = empty_ephemeral();
10832 let buckets = [
10833 eph.point_is_endomorphic(),
10834 eph.point_is_diffusive(),
10835 eph.point_is_convergent(),
10836 ];
10837 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10838 assert_eq!(
10839 hits, 1,
10840 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10841 );
10842 // Authored classification.
10843 for populated in ConvergencePointType::ALL {
10844 let mut classification = Classification::gate_compute();
10845 classification.point_type = populated;
10846 let mut eph = empty_ephemeral();
10847 eph.classification = Some(classification);
10848 let buckets = [
10849 eph.point_is_endomorphic(),
10850 eph.point_is_diffusive(),
10851 eph.point_is_convergent(),
10852 ];
10853 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10854 assert_eq!(
10855 hits, 1,
10856 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10857 );
10858 }
10859 }
10860
10861 // ── EphemeralSpec::substrate_is_resource pins ────────────────────
10862 //
10863 // Fail-before-pass-after granularity: `substrate_is_resource` did
10864 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10865 // walking the "does this ephemeral spec's substrate project to
10866 // the resource plane?" question went through
10867 // `.resolved_classification().substrate.is_resource()` or the
10868 // lowered `ProcessSpec`'s
10869 // `spec.classification.substrate.is_resource()`. Post-lift the
10870 // NINTH derived-nullary-boolean peer on the ephemeral surface
10871 // (FIRST on the `substrate` axis) routes through the SAME
10872 // [`Self::resolved_classification`] resolver + the sibling
10873 // substrate primitive
10874 // [`crate::classification::Classification::substrate_is_resource`],
10875 // so the two-surface parity contract holds by construction.
10876
10877 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10878 /// [`Classification`] carries a specific
10879 /// [`crate::classification::SubstrateType`] variant answers
10880 /// [`Self::substrate_is_resource`] matching the closed set's own
10881 /// [`crate::classification::SubstrateType::is_resource`] truth
10882 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10883 /// so a regression that (a) hard-coded the body to a fixed
10884 /// answer, (b) inverted the projection, or (c) crossed the wires
10885 /// with the sibling
10886 /// [`crate::classification::SubstrateType::is_policy`] /
10887 /// [`crate::classification::SubstrateType::is_telemetry`]
10888 /// projections fails HERE at the substrate primitive before
10889 /// drifting through the `resource-substrate` fixed tag or the
10890 /// peer point surface.
10891 #[test]
10892 fn substrate_is_resource_returns_substrate_projection_per_kind() {
10893 for populated in SubstrateType::ALL {
10894 let mut classification = Classification::gate_compute();
10895 classification.substrate = populated;
10896 let mut spec = empty_ephemeral();
10897 spec.classification = Some(classification);
10898 assert_eq!(
10899 spec.substrate_is_resource(),
10900 populated.is_resource(),
10901 "authored substrate={populated:?}: substrate_is_resource() drift",
10902 );
10903 }
10904 }
10905
10906 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10907 /// with `classification: None` routes through the
10908 /// [`Self::resolved_classification`] resolver's substrate default
10909 /// [`Classification::gate_compute`], which carries
10910 /// [`crate::classification::SubstrateType::Compute`] (the
10911 /// canonical resource-plane substrate), and
10912 /// [`crate::classification::SubstrateType::Compute::is_resource`]
10913 /// projects `true`, so [`Self::substrate_is_resource`] returns
10914 /// `true`. Pins the resolver's chosen-field baseline at ONE
10915 /// narrow site — mirror-aligned with the sibling
10916 /// `point_is_convergent_probes_true_on_absent_classification`
10917 /// baseline (both projections on `gate_compute` chosen fields
10918 /// answer `true`).
10919 #[test]
10920 fn substrate_is_resource_probes_true_on_absent_classification() {
10921 let spec = empty_ephemeral();
10922 assert!(spec.classification.is_none());
10923 assert!(
10924 spec.substrate_is_resource(),
10925 "absent classification (defaults to gate_compute, substrate=Compute → is_resource=true)",
10926 );
10927 }
10928
10929 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10930 /// identically through [`Self::substrate_is_resource`] AND through
10931 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_resource()`
10932 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10933 /// classification, `Some(_)` classification on every
10934 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10935 /// future regression on either side of the resolver fails HERE
10936 /// at the parity boundary. Byte-for-byte peer of
10937 /// `point_is_convergent_matches_point_peer_through_lowered_classification`
10938 /// on a sibling classification axis.
10939 #[test]
10940 fn substrate_is_resource_matches_point_peer_through_lowered_classification() {
10941 // Absent classification.
10942 let eph = empty_ephemeral();
10943 let lowered: ProcessSpec = eph.clone().into();
10944 assert_eq!(
10945 eph.substrate_is_resource(),
10946 lowered.classification.substrate_is_resource(),
10947 "None-classification parity drift",
10948 );
10949 // Authored classification.
10950 for populated in SubstrateType::ALL {
10951 let mut classification = Classification::gate_compute();
10952 classification.substrate = populated;
10953 let mut eph = empty_ephemeral();
10954 eph.classification = Some(classification);
10955 let lowered: ProcessSpec = eph.clone().into();
10956 assert_eq!(
10957 eph.substrate_is_resource(),
10958 lowered.classification.substrate_is_resource(),
10959 "authored substrate={populated:?}: parity drift",
10960 );
10961 }
10962 }
10963
10964 // ── EphemeralSpec::substrate_is_policy pins ──────────────────────
10965 //
10966 // Fail-before-pass-after granularity: `substrate_is_policy` did
10967 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10968 // walking the "does this ephemeral spec's substrate project to
10969 // the policy plane?" question went through
10970 // `.resolved_classification().substrate.is_policy()` or the
10971 // lowered `ProcessSpec`'s
10972 // `spec.classification.substrate.is_policy()`. Post-lift the
10973 // TENTH derived-nullary-boolean peer on the ephemeral surface
10974 // (SECOND on the `substrate` axis) routes through the SAME
10975 // [`Self::resolved_classification`] resolver + the sibling
10976 // substrate primitive
10977 // [`crate::classification::Classification::substrate_is_policy`],
10978 // so the two-surface parity contract holds by construction, AND
10979 // the two `substrate`-axis peers on this surface open the
10980 // MUTEX pair on the axis via
10981 // `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`.
10982
10983 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10984 /// [`Classification`] carries a specific
10985 /// [`crate::classification::SubstrateType`] variant answers
10986 /// [`Self::substrate_is_policy`] matching the closed set's own
10987 /// [`crate::classification::SubstrateType::is_policy`] truth
10988 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10989 /// so a regression that (a) hard-coded the body to a fixed
10990 /// answer, (b) inverted the projection, or (c) crossed the wires
10991 /// with the sibling
10992 /// [`crate::classification::SubstrateType::is_resource`] /
10993 /// [`crate::classification::SubstrateType::is_telemetry`]
10994 /// projections fails HERE at the substrate primitive before
10995 /// drifting through the `policy-substrate` fixed tag or the
10996 /// peer point surface.
10997 #[test]
10998 fn substrate_is_policy_returns_substrate_projection_per_kind() {
10999 for populated in SubstrateType::ALL {
11000 let mut classification = Classification::gate_compute();
11001 classification.substrate = populated;
11002 let mut spec = empty_ephemeral();
11003 spec.classification = Some(classification);
11004 assert_eq!(
11005 spec.substrate_is_policy(),
11006 populated.is_policy(),
11007 "authored substrate={populated:?}: substrate_is_policy() drift",
11008 );
11009 }
11010 }
11011
11012 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11013 /// with `classification: None` routes through the
11014 /// [`Self::resolved_classification`] resolver's substrate default
11015 /// [`Classification::gate_compute`], which carries
11016 /// [`crate::classification::SubstrateType::Compute`] (the
11017 /// canonical resource-plane substrate, NOT a policy plane), and
11018 /// [`crate::classification::SubstrateType::Compute::is_policy`]
11019 /// projects `false`, so [`Self::substrate_is_policy`] returns
11020 /// `false`. Pins the resolver's chosen-field baseline at ONE
11021 /// narrow site — mirror-inverted from the sibling
11022 /// `substrate_is_resource_probes_true_on_absent_classification`
11023 /// (both projections on `gate_compute`'s chosen `substrate`
11024 /// field, but the sibling answers `true` where this one
11025 /// answers `false` — the closed set's disjoint plane partition
11026 /// forbids both being true).
11027 #[test]
11028 fn substrate_is_policy_probes_false_on_absent_classification() {
11029 let spec = empty_ephemeral();
11030 assert!(spec.classification.is_none());
11031 assert!(
11032 !spec.substrate_is_policy(),
11033 "absent classification (defaults to gate_compute, substrate=Compute → is_policy=false)",
11034 );
11035 }
11036
11037 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11038 /// identically through [`Self::substrate_is_policy`] AND through
11039 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_policy()`
11040 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11041 /// classification, `Some(_)` classification on every
11042 /// [`crate::classification::SubstrateType::ALL`] variant) so a
11043 /// future regression on either side of the resolver fails HERE
11044 /// at the parity boundary. Byte-for-byte peer of
11045 /// `substrate_is_resource_matches_point_peer_through_lowered_classification`
11046 /// on the SAME closed-set axis via a sibling projection.
11047 #[test]
11048 fn substrate_is_policy_matches_point_peer_through_lowered_classification() {
11049 // Absent classification.
11050 let eph = empty_ephemeral();
11051 let lowered: ProcessSpec = eph.clone().into();
11052 assert_eq!(
11053 eph.substrate_is_policy(),
11054 lowered.classification.substrate_is_policy(),
11055 "None-classification parity drift",
11056 );
11057 // Authored classification.
11058 for populated in SubstrateType::ALL {
11059 let mut classification = Classification::gate_compute();
11060 classification.substrate = populated;
11061 let mut eph = empty_ephemeral();
11062 eph.classification = Some(classification);
11063 let lowered: ProcessSpec = eph.clone().into();
11064 assert_eq!(
11065 eph.substrate_is_policy(),
11066 lowered.classification.substrate_is_policy(),
11067 "authored substrate={populated:?}: parity drift",
11068 );
11069 }
11070 }
11071
11072 /// MUTEX pin — [`Self::substrate_is_resource`] AND
11073 /// [`Self::substrate_is_policy`] are NEVER simultaneously true
11074 /// for ANY [`EphemeralSpec`] (authored or defaulted), since the
11075 /// underlying [`crate::classification::SubstrateType`] closed set
11076 /// carves its eight variants into THREE disjoint buckets. Sweep
11077 /// the absent-classification case + every
11078 /// [`crate::classification::SubstrateType::ALL`] variant so a
11079 /// regression that crossed the wires between the two ephemeral-
11080 /// surface corner peers (one probe silently composing the wrong
11081 /// closed-set arm at the resolver-hop layer) fails HERE rather
11082 /// than at every downstream consumer that trusts the two probes
11083 /// partition the resolver's output into disjoint buckets.
11084 /// FIRST ephemeral-surface `substrate`-axis corner-peer pair
11085 /// carrying a non-trivial MUTEX relationship — structural twin
11086 /// of the sibling `point_type`-axis MUTEX pair sealed on this
11087 /// surface by
11088 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
11089 #[test]
11090 fn ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all() {
11091 // Absent classification.
11092 let eph = empty_ephemeral();
11093 assert!(
11094 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
11095 "None-classification: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
11096 );
11097 // Authored classification.
11098 for populated in SubstrateType::ALL {
11099 let mut classification = Classification::gate_compute();
11100 classification.substrate = populated;
11101 let mut eph = empty_ephemeral();
11102 eph.classification = Some(classification);
11103 assert!(
11104 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
11105 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
11106 );
11107 }
11108 }
11109
11110 // ── EphemeralSpec::substrate_is_telemetry pins ───────────────────
11111 //
11112 // Fail-before-pass-after granularity: `substrate_is_telemetry`
11113 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
11114 // walking the "does this ephemeral spec's substrate project to
11115 // the telemetry plane?" question went through
11116 // `.resolved_classification().substrate.is_telemetry()` or the
11117 // lowered `ProcessSpec`'s
11118 // `spec.classification.substrate.is_telemetry()`. Post-lift the
11119 // ELEVENTH derived-nullary-boolean peer on the ephemeral surface
11120 // (THIRD on the `substrate` axis) routes through the SAME
11121 // [`Self::resolved_classification`] resolver + the sibling
11122 // substrate primitive
11123 // [`crate::classification::Classification::substrate_is_telemetry`],
11124 // so the two-surface parity contract holds by construction, AND
11125 // the three `substrate`-axis peers on this surface CLOSE the
11126 // axis into the FULL three-way XOR partition contract via
11127 // `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
11128
11129 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11130 /// [`Classification`] carries a specific
11131 /// [`crate::classification::SubstrateType`] variant answers
11132 /// [`Self::substrate_is_telemetry`] matching the closed set's own
11133 /// [`crate::classification::SubstrateType::is_telemetry`] truth
11134 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
11135 /// so a regression that (a) hard-coded the body to a fixed
11136 /// answer, (b) inverted the projection, or (c) crossed the wires
11137 /// with the sibling
11138 /// [`crate::classification::SubstrateType::is_resource`] /
11139 /// [`crate::classification::SubstrateType::is_policy`]
11140 /// projections fails HERE at the substrate primitive before
11141 /// drifting through the `telemetry-substrate` fixed tag or the
11142 /// peer point surface.
11143 #[test]
11144 fn substrate_is_telemetry_returns_substrate_projection_per_kind() {
11145 for populated in SubstrateType::ALL {
11146 let mut classification = Classification::gate_compute();
11147 classification.substrate = populated;
11148 let mut spec = empty_ephemeral();
11149 spec.classification = Some(classification);
11150 assert_eq!(
11151 spec.substrate_is_telemetry(),
11152 populated.is_telemetry(),
11153 "authored substrate={populated:?}: substrate_is_telemetry() drift",
11154 );
11155 }
11156 }
11157
11158 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11159 /// with `classification: None` routes through the
11160 /// [`Self::resolved_classification`] resolver's substrate default
11161 /// [`Classification::gate_compute`], which carries
11162 /// [`crate::classification::SubstrateType::Compute`] (the
11163 /// canonical resource-plane substrate, NOT a telemetry plane),
11164 /// and
11165 /// [`crate::classification::SubstrateType::Compute::is_telemetry`]
11166 /// projects `false`, so [`Self::substrate_is_telemetry`] returns
11167 /// `false`. Pins the resolver's chosen-field baseline at ONE
11168 /// narrow site — aligned with the sibling
11169 /// `substrate_is_policy_probes_false_on_absent_classification`
11170 /// (both projections on `gate_compute`'s chosen `substrate`
11171 /// field project `false` since `Compute` lives in the resource
11172 /// plane), mirror-inverted from
11173 /// `substrate_is_resource_probes_true_on_absent_classification`.
11174 #[test]
11175 fn substrate_is_telemetry_probes_false_on_absent_classification() {
11176 let spec = empty_ephemeral();
11177 assert!(spec.classification.is_none());
11178 assert!(
11179 !spec.substrate_is_telemetry(),
11180 "absent classification (defaults to gate_compute, substrate=Compute → is_telemetry=false)",
11181 );
11182 }
11183
11184 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11185 /// identically through [`Self::substrate_is_telemetry`] AND
11186 /// through
11187 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_telemetry()`
11188 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11189 /// classification, `Some(_)` classification on every
11190 /// [`crate::classification::SubstrateType::ALL`] variant) so a
11191 /// future regression on either side of the resolver fails HERE
11192 /// at the parity boundary. Byte-for-byte peer of
11193 /// `substrate_is_policy_matches_point_peer_through_lowered_classification`
11194 /// on the SAME closed-set axis via a sibling projection.
11195 #[test]
11196 fn substrate_is_telemetry_matches_point_peer_through_lowered_classification() {
11197 // Absent classification.
11198 let eph = empty_ephemeral();
11199 let lowered: ProcessSpec = eph.clone().into();
11200 assert_eq!(
11201 eph.substrate_is_telemetry(),
11202 lowered.classification.substrate_is_telemetry(),
11203 "None-classification parity drift",
11204 );
11205 // Authored classification.
11206 for populated in SubstrateType::ALL {
11207 let mut classification = Classification::gate_compute();
11208 classification.substrate = populated;
11209 let mut eph = empty_ephemeral();
11210 eph.classification = Some(classification);
11211 let lowered: ProcessSpec = eph.clone().into();
11212 assert_eq!(
11213 eph.substrate_is_telemetry(),
11214 lowered.classification.substrate_is_telemetry(),
11215 "authored substrate={populated:?}: parity drift",
11216 );
11217 }
11218 }
11219
11220 /// MUTEX pin — [`Self::substrate_is_resource`] AND
11221 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
11222 /// for ANY [`EphemeralSpec`] (authored or defaulted). Second
11223 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
11224 /// peer of
11225 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
11226 /// on a sibling closed-set projection.
11227 #[test]
11228 fn ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all() {
11229 // Absent classification.
11230 let eph = empty_ephemeral();
11231 assert!(
11232 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
11233 "None-classification: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
11234 );
11235 // Authored classification.
11236 for populated in SubstrateType::ALL {
11237 let mut classification = Classification::gate_compute();
11238 classification.substrate = populated;
11239 let mut eph = empty_ephemeral();
11240 eph.classification = Some(classification);
11241 assert!(
11242 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
11243 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
11244 );
11245 }
11246 }
11247
11248 /// MUTEX pin — [`Self::substrate_is_policy`] AND
11249 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
11250 /// for ANY [`EphemeralSpec`] (authored or defaulted). Third
11251 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
11252 /// completes the three pairwise MUTEX relations alongside
11253 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
11254 /// and
11255 /// `ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all`.
11256 #[test]
11257 fn ephemeral_substrate_is_policy_and_substrate_is_telemetry_are_mutex_over_all() {
11258 // Absent classification.
11259 let eph = empty_ephemeral();
11260 assert!(
11261 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
11262 "None-classification: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
11263 );
11264 // Authored classification.
11265 for populated in SubstrateType::ALL {
11266 let mut classification = Classification::gate_compute();
11267 classification.substrate = populated;
11268 let mut eph = empty_ephemeral();
11269 eph.classification = Some(classification);
11270 assert!(
11271 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
11272 "authored substrate={populated:?}: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
11273 );
11274 }
11275 }
11276
11277 /// THREE-WAY XOR PARTITION pin — for the absent-classification
11278 /// baseline AND every [`crate::classification::SubstrateType::ALL`]
11279 /// variant, EXACTLY ONE of [`Self::substrate_is_resource`],
11280 /// [`Self::substrate_is_policy`], and
11281 /// [`Self::substrate_is_telemetry`] returns `true`. CLOSES the
11282 /// three pairwise MUTEX pins on the substrate axis
11283 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`,
11284 /// `substrate_is_resource ⇒ ¬substrate_is_telemetry`,
11285 /// `substrate_is_policy ⇒ ¬substrate_is_telemetry`) into the
11286 /// FULL ternary XOR partition contract on the ephemeral surface
11287 /// — the resolver-hop peer of the parent-composed
11288 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`
11289 /// test. Structural twin of the sibling `point_type`-axis
11290 /// ternary lift sealed on this surface by
11291 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
11292 /// Guarantees the absent-classification case lands in the
11293 /// resource bucket (`gate_compute` → Compute → is_resource =
11294 /// true), so every unadorned `(defephemeral …)` audits under a
11295 /// definite non-empty plane bucket.
11296 #[test]
11297 fn ephemeral_substrate_probes_form_three_way_xor_partition_over_all() {
11298 // Absent classification.
11299 let eph = empty_ephemeral();
11300 let buckets = [
11301 eph.substrate_is_resource(),
11302 eph.substrate_is_policy(),
11303 eph.substrate_is_telemetry(),
11304 ];
11305 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11306 assert_eq!(
11307 hits, 1,
11308 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
11309 );
11310 // Authored classification.
11311 for populated in SubstrateType::ALL {
11312 let mut classification = Classification::gate_compute();
11313 classification.substrate = populated;
11314 let mut eph = empty_ephemeral();
11315 eph.classification = Some(classification);
11316 let buckets = [
11317 eph.substrate_is_resource(),
11318 eph.substrate_is_policy(),
11319 eph.substrate_is_telemetry(),
11320 ];
11321 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11322 assert_eq!(
11323 hits, 1,
11324 "authored substrate={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
11325 );
11326 }
11327 }
11328
11329 // ── EphemeralSpec::calm_is_monotone pins ─────────────────────────
11330 //
11331 // Fail-before-pass-after granularity: `calm_is_monotone` did not
11332 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11333 // the "can this ephemeral spec participate in gossip-only writes?"
11334 // question went through the antisymmetric
11335 // `!self.calm_requires_coordination()` or through
11336 // `.resolved_classification().calm.is_monotone()`. Post-lift the
11337 // TWELFTH derived-nullary-boolean peer on the ephemeral surface
11338 // (SECOND on the calm axis, closing that axis into a binary XOR
11339 // partition on this surface) routes through the SAME
11340 // [`Self::resolved_classification`] resolver + the sibling
11341 // substrate primitive
11342 // [`crate::classification::Classification::calm_is_monotone`], so
11343 // the two-surface parity contract holds by construction, AND the
11344 // two calm-axis peers on this surface CLOSE the axis into the
11345 // FULL binary XOR partition contract via
11346 // `ephemeral_calm_probes_form_binary_xor_partition_over_all`.
11347
11348 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11349 /// [`Classification`] carries a specific
11350 /// [`crate::classification::CalmClassification`] variant answers
11351 /// [`Self::calm_is_monotone`] matching the closed set's own
11352 /// [`crate::classification::CalmClassification::is_monotone`]
11353 /// truth table. Sweep
11354 /// [`crate::classification::CalmClassification::ALL`] so a
11355 /// regression that (a) hard-coded the body to a fixed answer,
11356 /// (b) inverted the projection, or (c) crossed the wires with
11357 /// the sibling
11358 /// [`crate::classification::CalmClassification::requires_coordination`]
11359 /// projection fails HERE at the substrate primitive before
11360 /// drifting through the `monotone-calm` fixed tag or the peer
11361 /// point surface.
11362 #[test]
11363 fn calm_is_monotone_returns_calm_projection_per_kind() {
11364 for populated in CalmClassification::ALL {
11365 let mut classification = Classification::gate_compute();
11366 classification.calm = populated;
11367 let mut spec = empty_ephemeral();
11368 spec.classification = Some(classification);
11369 assert_eq!(
11370 spec.calm_is_monotone(),
11371 populated.is_monotone(),
11372 "authored calm={populated:?}: calm_is_monotone() drift",
11373 );
11374 }
11375 }
11376
11377 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11378 /// with `classification: None` routes through the
11379 /// [`Self::resolved_classification`] resolver's substrate default
11380 /// [`Classification::gate_compute`], which carries
11381 /// [`crate::classification::CalmClassification::default = Monotone`]
11382 /// via `#[default]`, and
11383 /// [`crate::classification::CalmClassification::Monotone::is_monotone`]
11384 /// projects `true`, so [`Self::calm_is_monotone`] returns
11385 /// `true`. Pins the resolver's default-arm short-circuit through
11386 /// TWO layers of `Default` ([`Classification::gate_compute`] →
11387 /// [`crate::classification::CalmClassification::default`])
11388 /// reaching this derived-nullary predicate. Mirror-inverted from
11389 /// the sibling
11390 /// `calm_requires_coordination_probes_false_on_absent_classification`
11391 /// (both walk the SAME defaulted `calm` field, so
11392 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
11393 /// closed set's disjoint XOR partition). Guarantees every
11394 /// unadorned `(defephemeral …)` reads as gossip-eligible under
11395 /// the positive CALM framing.
11396 #[test]
11397 fn calm_is_monotone_probes_true_on_absent_classification() {
11398 let spec = empty_ephemeral();
11399 assert!(spec.classification.is_none());
11400 assert!(
11401 spec.calm_is_monotone(),
11402 "absent classification (defaults to gate_compute, calm=Monotone → is_monotone=true)",
11403 );
11404 }
11405
11406 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11407 /// identically through [`Self::calm_is_monotone`] AND through
11408 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_is_monotone()`
11409 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11410 /// classification, `Some(_)` classification on every
11411 /// [`crate::classification::CalmClassification::ALL`] variant) so
11412 /// a future regression on either side of the resolver fails HERE
11413 /// at the parity boundary. Byte-for-byte peer of
11414 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
11415 /// on the SAME closed-set axis via the antisymmetric projection.
11416 #[test]
11417 fn calm_is_monotone_matches_point_peer_through_lowered_classification() {
11418 // Absent classification.
11419 let eph = empty_ephemeral();
11420 let lowered: ProcessSpec = eph.clone().into();
11421 assert_eq!(
11422 eph.calm_is_monotone(),
11423 lowered.classification.calm_is_monotone(),
11424 "None-classification parity drift",
11425 );
11426 // Authored classification.
11427 for populated in CalmClassification::ALL {
11428 let mut classification = Classification::gate_compute();
11429 classification.calm = populated;
11430 let mut eph = empty_ephemeral();
11431 eph.classification = Some(classification);
11432 let lowered: ProcessSpec = eph.clone().into();
11433 assert_eq!(
11434 eph.calm_is_monotone(),
11435 lowered.classification.calm_is_monotone(),
11436 "authored calm={populated:?}: parity drift",
11437 );
11438 }
11439 }
11440
11441 /// MUTEX pin — [`Self::calm_requires_coordination`] AND
11442 /// [`Self::calm_is_monotone`] are NEVER simultaneously true for
11443 /// ANY [`EphemeralSpec`] (authored or defaulted). FIRST
11444 /// ephemeral-surface `calm`-axis corner-peer MUTEX pin — the
11445 /// calm axis's counterpart to the sibling substrate-axis
11446 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
11447 /// on a binary (rather than ternary) closed set.
11448 #[test]
11449 fn ephemeral_calm_requires_coordination_and_calm_is_monotone_are_mutex_over_all() {
11450 // Absent classification.
11451 let eph = empty_ephemeral();
11452 assert!(
11453 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
11454 "None-classification: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
11455 );
11456 // Authored classification.
11457 for populated in CalmClassification::ALL {
11458 let mut classification = Classification::gate_compute();
11459 classification.calm = populated;
11460 let mut eph = empty_ephemeral();
11461 eph.classification = Some(classification);
11462 assert!(
11463 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
11464 "authored calm={populated:?}: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
11465 );
11466 }
11467 }
11468
11469 /// BINARY XOR PARTITION pin — for the absent-classification
11470 /// baseline AND every
11471 /// [`crate::classification::CalmClassification::ALL`] variant,
11472 /// EXACTLY ONE of [`Self::calm_is_monotone`] and
11473 /// [`Self::calm_requires_coordination`] returns `true`. CLOSES
11474 /// the calm-axis MUTEX pin
11475 /// (`calm_requires_coordination ⇒ ¬calm_is_monotone`) into the
11476 /// FULL binary XOR partition contract on the ephemeral surface
11477 /// — the resolver-hop peer of the parent-composed
11478 /// `classification_calm_probes_form_binary_xor_partition_over_all`
11479 /// test. Binary counterpart of the ternary XOR partitions sealed
11480 /// on the sibling `point_type` and `substrate` axes by
11481 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11482 /// and
11483 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
11484 /// Guarantees the absent-classification case lands in the
11485 /// monotone bucket (`gate_compute` → CalmClassification::Monotone
11486 /// → is_monotone = true), so every unadorned `(defephemeral …)`
11487 /// audits under a definite non-empty CALM bucket.
11488 #[test]
11489 fn ephemeral_calm_probes_form_binary_xor_partition_over_all() {
11490 // Absent classification.
11491 let eph = empty_ephemeral();
11492 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
11493 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11494 assert_eq!(
11495 hits, 1,
11496 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11497 );
11498 // Authored classification.
11499 for populated in CalmClassification::ALL {
11500 let mut classification = Classification::gate_compute();
11501 classification.calm = populated;
11502 let mut eph = empty_ephemeral();
11503 eph.classification = Some(classification);
11504 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
11505 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11506 assert_eq!(
11507 hits, 1,
11508 "authored calm={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11509 );
11510 }
11511 }
11512
11513 // ── EphemeralSpec::data_is_public pins ───────────────────────────
11514 //
11515 // Fail-before-pass-after granularity: `data_is_public` did not
11516 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11517 // the "is this ephemeral spec's dataset publicly distributable?"
11518 // question went through the antisymmetric
11519 // `!self.data_is_restricted()` or through
11520 // `.resolved_classification().data_classification.is_public()`.
11521 // Post-lift the THIRTEENTH derived-nullary-boolean peer on the
11522 // ephemeral surface (THIRD on the data axis, closing that axis
11523 // into a binary XOR partition on this surface) routes through the
11524 // SAME [`Self::resolved_classification`] resolver + the sibling
11525 // substrate primitive
11526 // [`crate::classification::Classification::data_is_public`], so
11527 // the two-surface parity contract holds by construction, AND the
11528 // two-way public/restricted split on this surface CLOSES the
11529 // data axis into the FULL binary XOR partition contract via
11530 // `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11531
11532 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11533 /// [`Classification`] carries a specific
11534 /// [`crate::classification::DataClassification`] variant answers
11535 /// [`Self::data_is_public`] matching the closed set's own
11536 /// [`crate::classification::DataClassification::is_public`] truth
11537 /// table. Sweep
11538 /// [`crate::classification::DataClassification::ALL`] so a
11539 /// regression that (a) hard-coded the body to a fixed answer,
11540 /// (b) inverted the projection, or (c) crossed the wires with
11541 /// the sibling
11542 /// [`crate::classification::DataClassification::is_restricted`]
11543 /// projection fails HERE at the substrate primitive before
11544 /// drifting through the `public-data` fixed tag or the peer
11545 /// point surface.
11546 #[test]
11547 fn data_is_public_returns_data_projection_per_kind() {
11548 for populated in DataClassification::ALL {
11549 let mut classification = Classification::gate_compute();
11550 classification.data_classification = populated;
11551 let mut spec = empty_ephemeral();
11552 spec.classification = Some(classification);
11553 assert_eq!(
11554 spec.data_is_public(),
11555 populated.is_public(),
11556 "authored data_classification={populated:?}: data_is_public() drift",
11557 );
11558 }
11559 }
11560
11561 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11562 /// with `classification: None` routes through the
11563 /// [`Self::resolved_classification`] resolver's substrate default
11564 /// [`Classification::gate_compute`], which carries
11565 /// [`crate::classification::DataClassification::default = Internal`]
11566 /// via `#[default]`, and
11567 /// [`crate::classification::DataClassification::Internal::is_public`]
11568 /// projects `false`, so [`Self::data_is_public`] returns `false`.
11569 /// Pins the resolver's default-arm short-circuit through TWO
11570 /// layers of `Default` ([`Classification::gate_compute`] →
11571 /// [`crate::classification::DataClassification::default`])
11572 /// reaching this derived-nullary predicate. Mirror-inverted from
11573 /// the sibling
11574 /// `data_is_restricted_probes_true_on_absent_classification`
11575 /// (both walk the SAME defaulted `data_classification` field, so
11576 /// `is_restricted = true` ⇒ `is_public = false` on the closed
11577 /// set's disjoint XOR partition). Guarantees every unadorned
11578 /// `(defephemeral …)` audits under the access-controlled default
11579 /// rather than silently promoting an unadorned dataset onto the
11580 /// freely-distributable path.
11581 #[test]
11582 fn data_is_public_probes_false_on_absent_classification() {
11583 let spec = empty_ephemeral();
11584 assert!(spec.classification.is_none());
11585 assert!(
11586 !spec.data_is_public(),
11587 "absent classification (defaults to gate_compute, data_classification=Internal → is_public=false)",
11588 );
11589 }
11590
11591 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11592 /// identically through [`Self::data_is_public`] AND through
11593 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_public()`
11594 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11595 /// classification, `Some(_)` classification on every
11596 /// [`crate::classification::DataClassification::ALL`] variant) so
11597 /// a future regression on either side of the resolver fails HERE
11598 /// at the parity boundary. Byte-for-byte peer of
11599 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
11600 /// on the SAME closed-set axis via the antisymmetric projection.
11601 #[test]
11602 fn data_is_public_matches_point_peer_through_lowered_classification() {
11603 // Absent classification.
11604 let eph = empty_ephemeral();
11605 let lowered: ProcessSpec = eph.clone().into();
11606 assert_eq!(
11607 eph.data_is_public(),
11608 lowered.classification.data_is_public(),
11609 "None-classification parity drift",
11610 );
11611 // Authored classification.
11612 for populated in DataClassification::ALL {
11613 let mut classification = Classification::gate_compute();
11614 classification.data_classification = populated;
11615 let mut eph = empty_ephemeral();
11616 eph.classification = Some(classification);
11617 let lowered: ProcessSpec = eph.clone().into();
11618 assert_eq!(
11619 eph.data_is_public(),
11620 lowered.classification.data_is_public(),
11621 "authored data_classification={populated:?}: parity drift",
11622 );
11623 }
11624 }
11625
11626 /// MUTEX pin — [`Self::data_is_regulated`] AND
11627 /// [`Self::data_is_public`] are NEVER simultaneously true for ANY
11628 /// [`EphemeralSpec`] (authored or defaulted). FIRST ephemeral-
11629 /// surface data-axis antisymmetric MUTEX pin against the
11630 /// positive-distribution framing: sealed on the closed set by
11631 /// `data_classification_regulated_implies_not_public` and lifted
11632 /// through the resolver hop as a substrate-wide contract on this
11633 /// surface.
11634 #[test]
11635 fn ephemeral_data_is_regulated_and_data_is_public_are_mutex_over_all() {
11636 // Absent classification.
11637 let eph = empty_ephemeral();
11638 assert!(
11639 !(eph.data_is_regulated() && eph.data_is_public()),
11640 "None-classification: data_is_regulated AND data_is_public both true (mutex violated)",
11641 );
11642 // Authored classification.
11643 for populated in DataClassification::ALL {
11644 let mut classification = Classification::gate_compute();
11645 classification.data_classification = populated;
11646 let mut eph = empty_ephemeral();
11647 eph.classification = Some(classification);
11648 assert!(
11649 !(eph.data_is_regulated() && eph.data_is_public()),
11650 "authored data_classification={populated:?}: data_is_regulated AND data_is_public both true (mutex violated)",
11651 );
11652 }
11653 }
11654
11655 /// BINARY XOR PARTITION pin — for the absent-classification
11656 /// baseline AND every
11657 /// [`crate::classification::DataClassification::ALL`] variant,
11658 /// EXACTLY ONE of [`Self::data_is_public`] and
11659 /// [`Self::data_is_restricted`] returns `true`. CLOSES the data-
11660 /// axis MUTEX pin (`data_is_regulated ⇒ ¬data_is_public`) into
11661 /// the FULL binary XOR partition contract on the ephemeral
11662 /// surface — the resolver-hop peer of the parent-composed
11663 /// `classification_data_probes_form_binary_xor_partition_over_all`
11664 /// test. Binary counterpart of the ternary XOR partitions sealed
11665 /// on the sibling `point_type` and `substrate` axes by
11666 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11667 /// and
11668 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
11669 /// Guarantees the absent-classification case lands in the
11670 /// access-controlled bucket (`gate_compute` →
11671 /// DataClassification::Internal → is_public = false,
11672 /// is_restricted = true), so every unadorned `(defephemeral …)`
11673 /// audits under a definite non-empty distribution bucket.
11674 #[test]
11675 fn ephemeral_data_probes_form_binary_xor_partition_over_all() {
11676 // Absent classification.
11677 let eph = empty_ephemeral();
11678 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
11679 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11680 assert_eq!(
11681 hits, 1,
11682 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11683 );
11684 // Authored classification.
11685 for populated in DataClassification::ALL {
11686 let mut classification = Classification::gate_compute();
11687 classification.data_classification = populated;
11688 let mut eph = empty_ephemeral();
11689 eph.classification = Some(classification);
11690 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
11691 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11692 assert_eq!(
11693 hits, 1,
11694 "authored data_classification={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11695 );
11696 }
11697 }
11698
11699 // ── EphemeralSpec::direction_prefers_lower pins ─────────────────
11700 //
11701 // Fail-before-pass-after granularity: `direction_prefers_lower`
11702 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
11703 // walking the "does this ephemeral spec's rate-window evaluator
11704 // treat decreasing values as improvement?" question went through
11705 // `.resolved_classification().horizon.direction.unwrap_or_default().prefers_lower()`.
11706 // Post-lift the FOURTEENTH derived-nullary-boolean peer on the
11707 // ephemeral surface (FIRST on the optimization-direction axis,
11708 // opening the SIXTH classification axis into the fixed-tag algebra)
11709 // routes through the SAME [`Self::resolved_classification`] resolver
11710 // + the sibling substrate primitive
11711 // [`crate::classification::Classification::direction_prefers_lower`],
11712 // so the two-surface parity contract holds by construction.
11713
11714 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11715 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
11716 /// answers [`Self::direction_prefers_lower`] matching the closed
11717 /// set's own
11718 /// [`crate::classification::OptimizationDirection::prefers_lower`]
11719 /// truth table. Sweep
11720 /// [`crate::classification::OptimizationDirection::ALL`] so a
11721 /// regression that (a) hard-coded the body to a fixed answer,
11722 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
11723 /// hop, or (d) crossed the wires with a sibling classification-axis
11724 /// probe fails HERE at the substrate primitive before drifting
11725 /// through the `prefers-lower-direction` fixed tag or the peer
11726 /// point surface.
11727 #[test]
11728 fn direction_prefers_lower_returns_direction_projection_per_kind() {
11729 for populated in OptimizationDirection::ALL {
11730 let mut classification = Classification::gate_compute();
11731 classification.horizon.direction = Some(populated);
11732 let mut spec = empty_ephemeral();
11733 spec.classification = Some(classification);
11734 assert_eq!(
11735 spec.direction_prefers_lower(),
11736 populated.prefers_lower(),
11737 "authored horizon.direction={populated:?}: direction_prefers_lower() drift",
11738 );
11739 }
11740 }
11741
11742 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11743 /// with `classification: None` routes through the
11744 /// [`Self::resolved_classification`] resolver's substrate default
11745 /// [`Classification::gate_compute`], which carries
11746 /// `horizon: Horizon::default()` whose `direction` field is `None`,
11747 /// so `unwrap_or_default()` defaults to
11748 /// [`crate::classification::OptimizationDirection::Minimize`] via
11749 /// `#[default]`, and `Minimize.prefers_lower()` projects `true`,
11750 /// so [`Self::direction_prefers_lower`] returns `true`. Pins the
11751 /// resolver's default-arm short-circuit through THREE layers of
11752 /// `Default` ([`Classification::gate_compute`] →
11753 /// [`crate::classification::Horizon::default`] with `direction: None`
11754 /// → [`crate::classification::OptimizationDirection::default =
11755 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
11756 /// every unadorned `(defephemeral …)` reads under the lower-is-
11757 /// better polarity default (safe under the asymptotic-health
11758 /// rate-window evaluator convention: an operator must deliberately
11759 /// opt into Maximize polarity).
11760 #[test]
11761 fn direction_prefers_lower_probes_true_on_absent_classification() {
11762 let spec = empty_ephemeral();
11763 assert!(spec.classification.is_none());
11764 assert!(
11765 spec.direction_prefers_lower(),
11766 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_lower=true)",
11767 );
11768 }
11769
11770 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11771 /// identically through [`Self::direction_prefers_lower`] AND through
11772 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_lower()`
11773 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11774 /// classification, `Some(_)` classification on every
11775 /// [`crate::classification::OptimizationDirection::ALL`] variant) so
11776 /// a future regression on either side of the resolver fails HERE
11777 /// at the parity boundary. Byte-for-byte peer of
11778 /// `calm_is_monotone_matches_point_peer_through_lowered_classification`
11779 /// on the analog closed-set axis via the same resolver-hop shape.
11780 #[test]
11781 fn direction_prefers_lower_matches_point_peer_through_lowered_classification() {
11782 // Absent classification.
11783 let eph = empty_ephemeral();
11784 let lowered: ProcessSpec = eph.clone().into();
11785 assert_eq!(
11786 eph.direction_prefers_lower(),
11787 lowered.classification.direction_prefers_lower(),
11788 "None-classification parity drift",
11789 );
11790 // Authored classification.
11791 for populated in OptimizationDirection::ALL {
11792 let mut classification = Classification::gate_compute();
11793 classification.horizon.direction = Some(populated);
11794 let mut eph = empty_ephemeral();
11795 eph.classification = Some(classification);
11796 let lowered: ProcessSpec = eph.clone().into();
11797 assert_eq!(
11798 eph.direction_prefers_lower(),
11799 lowered.classification.direction_prefers_lower(),
11800 "authored horizon.direction={populated:?}: parity drift",
11801 );
11802 }
11803 }
11804
11805 // ── EphemeralSpec::direction_prefers_higher pins ────────────────
11806 //
11807 // Fail-before-pass-after granularity: `direction_prefers_higher`
11808 // did not exist pre-lift on `impl EphemeralSpec` — the positive
11809 // higher-is-better framing peer of
11810 // [`Self::direction_prefers_lower`] had no ephemeral-surface
11811 // substrate owner. Post-lift the FIFTEENTH derived-nullary-boolean
11812 // peer on the ephemeral surface (SECOND on the optimization-
11813 // direction axis, CLOSING the SIXTH classification axis into a
11814 // binary XOR partition on this surface) routes through the SAME
11815 // [`Self::resolved_classification`] resolver + the sibling
11816 // substrate primitive
11817 // [`crate::classification::Classification::direction_prefers_higher`],
11818 // so the two-surface parity contract holds by construction, AND
11819 // the two-way lower/higher split on this surface CLOSES the
11820 // optimization-direction axis into the FULL binary XOR partition
11821 // contract via
11822 // `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
11823
11824 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11825 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
11826 /// answers [`Self::direction_prefers_higher`] matching the closed
11827 /// set's own
11828 /// [`crate::classification::OptimizationDirection::prefers_higher`]
11829 /// truth table. Sweep
11830 /// [`crate::classification::OptimizationDirection::ALL`] so a
11831 /// regression that (a) hard-coded the body to a fixed answer,
11832 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
11833 /// hop, or (d) crossed the wires with a sibling classification-
11834 /// axis probe fails HERE at the substrate primitive before
11835 /// drifting through the `prefers-higher-direction` fixed tag or
11836 /// the peer point surface.
11837 #[test]
11838 fn direction_prefers_higher_returns_direction_projection_per_kind() {
11839 for populated in OptimizationDirection::ALL {
11840 let mut classification = Classification::gate_compute();
11841 classification.horizon.direction = Some(populated);
11842 let mut spec = empty_ephemeral();
11843 spec.classification = Some(classification);
11844 assert_eq!(
11845 spec.direction_prefers_higher(),
11846 populated.prefers_higher(),
11847 "authored horizon.direction={populated:?}: direction_prefers_higher() drift",
11848 );
11849 }
11850 }
11851
11852 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11853 /// with `classification: None` routes through the
11854 /// [`Self::resolved_classification`] resolver's substrate default
11855 /// [`Classification::gate_compute`], which carries
11856 /// `horizon: Horizon::default()` whose `direction` field is `None`,
11857 /// so `unwrap_or_default()` defaults to
11858 /// [`crate::classification::OptimizationDirection::Minimize`] via
11859 /// `#[default]`, and `Minimize.prefers_higher()` projects `false`,
11860 /// so [`Self::direction_prefers_higher`] returns `false`. Pins
11861 /// the resolver's default-arm short-circuit through THREE layers
11862 /// of `Default` ([`Classification::gate_compute`] →
11863 /// [`crate::classification::Horizon::default`] with `direction:
11864 /// None` → [`crate::classification::OptimizationDirection::default =
11865 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
11866 /// every unadorned `(defephemeral …)` reads UNDER the lower-is-
11867 /// better polarity default (safe under the asymptotic-health
11868 /// rate-window evaluator convention: an operator must
11869 /// deliberately opt into Maximize polarity). Mirror-inverted from
11870 /// the sibling `direction_prefers_lower_probes_true_on_absent_classification`
11871 /// baseline on the same resolver walk.
11872 #[test]
11873 fn direction_prefers_higher_probes_false_on_absent_classification() {
11874 let spec = empty_ephemeral();
11875 assert!(spec.classification.is_none());
11876 assert!(
11877 !spec.direction_prefers_higher(),
11878 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_higher=false)",
11879 );
11880 }
11881
11882 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11883 /// identically through [`Self::direction_prefers_higher`] AND
11884 /// through
11885 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_higher()`
11886 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11887 /// classification, `Some(_)` classification on every
11888 /// [`crate::classification::OptimizationDirection::ALL`] variant)
11889 /// so a future regression on either side of the resolver fails
11890 /// HERE at the parity boundary. Byte-for-byte peer of
11891 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
11892 /// on the antisymmetric closed-set arm via the same resolver-hop
11893 /// shape.
11894 #[test]
11895 fn direction_prefers_higher_matches_point_peer_through_lowered_classification() {
11896 // Absent classification.
11897 let eph = empty_ephemeral();
11898 let lowered: ProcessSpec = eph.clone().into();
11899 assert_eq!(
11900 eph.direction_prefers_higher(),
11901 lowered.classification.direction_prefers_higher(),
11902 "None-classification parity drift",
11903 );
11904 // Authored classification.
11905 for populated in OptimizationDirection::ALL {
11906 let mut classification = Classification::gate_compute();
11907 classification.horizon.direction = Some(populated);
11908 let mut eph = empty_ephemeral();
11909 eph.classification = Some(classification);
11910 let lowered: ProcessSpec = eph.clone().into();
11911 assert_eq!(
11912 eph.direction_prefers_higher(),
11913 lowered.classification.direction_prefers_higher(),
11914 "authored horizon.direction={populated:?}: parity drift",
11915 );
11916 }
11917 }
11918
11919 /// BINARY XOR PARTITION pin — for the absent-classification
11920 /// baseline AND every
11921 /// [`crate::classification::OptimizationDirection::ALL`] variant,
11922 /// EXACTLY ONE of [`Self::direction_prefers_lower`] and
11923 /// [`Self::direction_prefers_higher`] returns `true`. CLOSES the
11924 /// optimization-direction axis into the FULL binary XOR partition
11925 /// contract on the ephemeral surface — the resolver-hop peer of
11926 /// the parent-composed
11927 /// `classification_direction_probes_form_binary_xor_partition_over_all`
11928 /// test. Binary counterpart of the ternary XOR partitions sealed
11929 /// on the sibling `point_type` and `substrate` axes by
11930 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11931 /// and
11932 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11933 /// structural twin of the calm/data binary partitions
11934 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all` and
11935 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11936 /// This pin is the SIXTH (and final) classification axis to reach
11937 /// the closed XOR partition landmark on the ephemeral resolver-
11938 /// hop surface — ALL SIX classification axes (horizon, calm,
11939 /// data, point, substrate, optimization-direction) now have
11940 /// their partitions closed on the ephemeral surface at this
11941 /// corner. Guarantees the absent-classification case lands in
11942 /// the definite lower-is-better bucket (`gate_compute` →
11943 /// Horizon::default → direction: None →
11944 /// OptimizationDirection::default = Minimize → prefers_lower =
11945 /// true, prefers_higher = false), so every unadorned
11946 /// `(defephemeral …)` audits under a definite non-empty polarity
11947 /// bucket.
11948 #[test]
11949 fn ephemeral_direction_probes_form_binary_xor_partition_over_all() {
11950 // Absent classification.
11951 let eph = empty_ephemeral();
11952 let buckets = [
11953 eph.direction_prefers_lower(),
11954 eph.direction_prefers_higher(),
11955 ];
11956 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11957 assert_eq!(
11958 hits, 1,
11959 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11960 );
11961 // Authored classification.
11962 for populated in OptimizationDirection::ALL {
11963 let mut classification = Classification::gate_compute();
11964 classification.horizon.direction = Some(populated);
11965 let mut eph = empty_ephemeral();
11966 eph.classification = Some(classification);
11967 let buckets = [
11968 eph.direction_prefers_lower(),
11969 eph.direction_prefers_higher(),
11970 ];
11971 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11972 assert_eq!(
11973 hits, 1,
11974 "authored horizon.direction={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11975 );
11976 }
11977 }
11978
11979 // ── EphemeralSpec::input_arity_is_one pins ──────────────────────
11980 //
11981 // Fail-before-pass-after granularity: `input_arity_is_one` did not
11982 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11983 // the "does this ephemeral spec's DAG-composition input port
11984 // accept a single upstream edge?" question went through
11985 // `.resolved_classification().point_type.input_arity().is_one()`.
11986 // Post-lift the SIXTEENTH derived-nullary-boolean peer on the
11987 // ephemeral surface (FIRST on the input-arity axis, opening the
11988 // SEVENTH classification axis into the fixed-tag algebra + the
11989 // derived-typed-projection stratum on this surface for the first
11990 // time) routes through the SAME [`Self::resolved_classification`]
11991 // resolver + the sibling substrate primitive
11992 // [`crate::classification::Classification::input_arity_is_one`],
11993 // so the two-surface parity contract holds by construction.
11994
11995 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11996 /// [`Classification`] carries `point_type: kind` answers
11997 /// [`Self::input_arity_is_one`] matching the closed set's own
11998 /// [`crate::classification::ConvergencePointType::input_arity`]
11999 /// truth table projected through [`Arity::is_one`]. Sweep
12000 /// [`crate::classification::ConvergencePointType::ALL`] so a
12001 /// regression that (a) hard-coded the body to a fixed answer,
12002 /// (b) inverted the projection, (c) dropped the resolver hop, or
12003 /// (d) crossed the wires with the sibling `output_arity`
12004 /// projection (which disagrees on six of eight variants) fails
12005 /// HERE at the substrate primitive before drifting through the
12006 /// future `single-input-arity` fixed tag or the peer point
12007 /// surface.
12008 #[test]
12009 fn input_arity_is_one_returns_input_arity_projection_per_kind() {
12010 for populated in ConvergencePointType::ALL {
12011 let mut classification = Classification::gate_compute();
12012 classification.point_type = populated;
12013 let mut spec = empty_ephemeral();
12014 spec.classification = Some(classification);
12015 assert_eq!(
12016 spec.input_arity_is_one(),
12017 populated.input_arity().is_one(),
12018 "authored point_type={populated:?}: input_arity_is_one() drift",
12019 );
12020 }
12021 }
12022
12023 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
12024 /// with `classification: None` routes through the
12025 /// [`Self::resolved_classification`] resolver's substrate default
12026 /// [`Classification::gate_compute`], which carries `point_type:
12027 /// Gate` and `Gate.input_arity() = Many`, so
12028 /// [`Self::input_arity_is_one`] returns `false`. Pins the
12029 /// resolver's default-arm short-circuit reaching this derived-
12030 /// nullary predicate — every unadorned `(defephemeral …)` lands
12031 /// in the multi-input bucket under the substrate default. Mirror-
12032 /// inverted from the sibling `input_arity_is_many` baseline on
12033 /// the same resolver walk (the XOR partition forces exactly one
12034 /// bucket per baseline).
12035 #[test]
12036 fn input_arity_is_one_probes_false_on_absent_classification() {
12037 let spec = empty_ephemeral();
12038 assert!(spec.classification.is_none());
12039 assert!(
12040 !spec.input_arity_is_one(),
12041 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_one=false)",
12042 );
12043 }
12044
12045 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
12046 /// identically through [`Self::input_arity_is_one`] AND through
12047 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_one()`
12048 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
12049 /// classification, `Some(_)` classification on every
12050 /// [`crate::classification::ConvergencePointType::ALL`] variant)
12051 /// so a future regression on either side of the resolver fails
12052 /// HERE at the parity boundary. Byte-for-byte peer of
12053 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
12054 /// on the same resolver-hop shape.
12055 #[test]
12056 fn input_arity_is_one_matches_point_peer_through_lowered_classification() {
12057 // Absent classification.
12058 let eph = empty_ephemeral();
12059 let lowered: ProcessSpec = eph.clone().into();
12060 assert_eq!(
12061 eph.input_arity_is_one(),
12062 lowered.classification.input_arity_is_one(),
12063 "None-classification parity drift",
12064 );
12065 // Authored classification.
12066 for populated in ConvergencePointType::ALL {
12067 let mut classification = Classification::gate_compute();
12068 classification.point_type = populated;
12069 let mut eph = empty_ephemeral();
12070 eph.classification = Some(classification);
12071 let lowered: ProcessSpec = eph.clone().into();
12072 assert_eq!(
12073 eph.input_arity_is_one(),
12074 lowered.classification.input_arity_is_one(),
12075 "authored point_type={populated:?}: parity drift",
12076 );
12077 }
12078 }
12079
12080 // ── EphemeralSpec::input_arity_is_many pins ─────────────────────
12081 //
12082 // Fail-before-pass-after granularity: `input_arity_is_many` did
12083 // not exist pre-lift on `impl EphemeralSpec` — the multi-input
12084 // framing peer of [`Self::input_arity_is_one`] had no ephemeral-
12085 // surface substrate owner. Post-lift the SEVENTEENTH derived-
12086 // nullary-boolean peer on the ephemeral surface (SECOND on the
12087 // input-arity axis, CLOSING the SEVENTH classification axis into
12088 // a binary XOR partition on this surface) routes through the SAME
12089 // [`Self::resolved_classification`] resolver + the sibling
12090 // substrate primitive
12091 // [`crate::classification::Classification::input_arity_is_many`],
12092 // so the two-surface parity contract holds by construction, AND
12093 // the two-way single/many split on this surface CLOSES the
12094 // input-arity axis into the FULL binary XOR partition contract
12095 // via `ephemeral_input_arity_probes_form_binary_xor_partition_over_all`.
12096
12097 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
12098 /// [`Classification`] carries `point_type: kind` answers
12099 /// [`Self::input_arity_is_many`] matching the closed set's own
12100 /// [`crate::classification::ConvergencePointType::input_arity`]
12101 /// truth table projected through [`Arity::is_many`]. Sweep
12102 /// [`crate::classification::ConvergencePointType::ALL`] so a
12103 /// regression that (a) hard-coded the body to a fixed answer,
12104 /// (b) inverted the projection, (c) dropped the resolver hop, or
12105 /// (d) crossed the wires with the sibling `output_arity`
12106 /// projection fails HERE at the substrate primitive before
12107 /// drifting through the future `multi-input-arity` fixed tag or
12108 /// the peer point surface.
12109 #[test]
12110 fn input_arity_is_many_returns_input_arity_projection_per_kind() {
12111 for populated in ConvergencePointType::ALL {
12112 let mut classification = Classification::gate_compute();
12113 classification.point_type = populated;
12114 let mut spec = empty_ephemeral();
12115 spec.classification = Some(classification);
12116 assert_eq!(
12117 spec.input_arity_is_many(),
12118 populated.input_arity().is_many(),
12119 "authored point_type={populated:?}: input_arity_is_many() drift",
12120 );
12121 }
12122 }
12123
12124 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
12125 /// with `classification: None` routes through the
12126 /// [`Self::resolved_classification`] resolver's substrate default
12127 /// [`Classification::gate_compute`], which carries `point_type:
12128 /// Gate` and `Gate.input_arity() = Many`, so
12129 /// [`Self::input_arity_is_many`] returns `true`. Pins the
12130 /// resolver's default-arm short-circuit reaching this derived-
12131 /// nullary predicate — every unadorned `(defephemeral …)` lands
12132 /// in the multi-input bucket under the substrate default. Mirror-
12133 /// inverted from the sibling `input_arity_is_one` baseline on
12134 /// the same resolver walk (the XOR partition forces exactly one
12135 /// bucket per baseline).
12136 #[test]
12137 fn input_arity_is_many_probes_true_on_absent_classification() {
12138 let spec = empty_ephemeral();
12139 assert!(spec.classification.is_none());
12140 assert!(
12141 spec.input_arity_is_many(),
12142 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_many=true)",
12143 );
12144 }
12145
12146 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
12147 /// identically through [`Self::input_arity_is_many`] AND through
12148 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_many()`
12149 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
12150 /// classification, `Some(_)` classification on every
12151 /// [`crate::classification::ConvergencePointType::ALL`] variant)
12152 /// so a future regression on either side of the resolver fails
12153 /// HERE at the parity boundary. Byte-for-byte peer of
12154 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
12155 /// on the antisymmetric closed-set arm via the same resolver-hop
12156 /// shape.
12157 #[test]
12158 fn input_arity_is_many_matches_point_peer_through_lowered_classification() {
12159 // Absent classification.
12160 let eph = empty_ephemeral();
12161 let lowered: ProcessSpec = eph.clone().into();
12162 assert_eq!(
12163 eph.input_arity_is_many(),
12164 lowered.classification.input_arity_is_many(),
12165 "None-classification parity drift",
12166 );
12167 // Authored classification.
12168 for populated in ConvergencePointType::ALL {
12169 let mut classification = Classification::gate_compute();
12170 classification.point_type = populated;
12171 let mut eph = empty_ephemeral();
12172 eph.classification = Some(classification);
12173 let lowered: ProcessSpec = eph.clone().into();
12174 assert_eq!(
12175 eph.input_arity_is_many(),
12176 lowered.classification.input_arity_is_many(),
12177 "authored point_type={populated:?}: parity drift",
12178 );
12179 }
12180 }
12181
12182 /// BINARY XOR PARTITION pin — for the absent-classification
12183 /// baseline AND every
12184 /// [`crate::classification::ConvergencePointType::ALL`] variant,
12185 /// EXACTLY ONE of [`Self::input_arity_is_one`] and
12186 /// [`Self::input_arity_is_many`] returns `true`. CLOSES the
12187 /// input-arity axis into the FULL binary XOR partition contract
12188 /// on the ephemeral surface — the resolver-hop peer of the
12189 /// parent-composed
12190 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`
12191 /// test. Binary counterpart of the ternary XOR partitions sealed
12192 /// on the sibling `point_type` and `substrate` axes by
12193 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
12194 /// and
12195 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
12196 /// structural twin of the calm/data/direction binary partitions
12197 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
12198 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`,
12199 /// and
12200 /// `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
12201 /// This pin is the SEVENTH classification axis to reach the
12202 /// closed XOR partition landmark on the ephemeral resolver-hop
12203 /// surface — the FIRST closed axis on the derived-typed-
12204 /// projection stratum of this surface, opening the stratum beyond
12205 /// the six stored classification slots. Guarantees the absent-
12206 /// classification case lands in the definite multi-input bucket
12207 /// (`gate_compute` → point_type=Gate → input_arity=Many →
12208 /// is_one=false, is_many=true), so every unadorned
12209 /// `(defephemeral …)` audits under a definite non-empty input-
12210 /// arity bucket.
12211 #[test]
12212 fn ephemeral_input_arity_probes_form_binary_xor_partition_over_all() {
12213 // Absent classification.
12214 let eph = empty_ephemeral();
12215 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
12216 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12217 assert_eq!(
12218 hits, 1,
12219 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12220 );
12221 // Authored classification.
12222 for populated in ConvergencePointType::ALL {
12223 let mut classification = Classification::gate_compute();
12224 classification.point_type = populated;
12225 let mut eph = empty_ephemeral();
12226 eph.classification = Some(classification);
12227 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
12228 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12229 assert_eq!(
12230 hits, 1,
12231 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12232 );
12233 }
12234 }
12235
12236 // ── EphemeralSpec::output_arity_is_one pins ─────────────────────
12237 //
12238 // Fail-before-pass-after granularity: `output_arity_is_one` did not
12239 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
12240 // the "does this ephemeral spec's DAG-composition output port emit
12241 // to a single downstream edge?" question went through
12242 // `.resolved_classification().point_type.output_arity().is_one()`.
12243 // Post-lift the EIGHTEENTH derived-nullary-boolean peer on the
12244 // ephemeral surface (FIRST on the output-arity axis, opening the
12245 // EIGHTH classification axis into the fixed-tag algebra + the
12246 // SECOND peer on the derived-typed-projection stratum after
12247 // [`Self::input_arity_is_one`]) routes through the SAME
12248 // [`Self::resolved_classification`] resolver + the sibling
12249 // substrate primitive
12250 // [`crate::classification::Classification::output_arity_is_one`],
12251 // so the two-surface parity contract holds by construction.
12252
12253 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
12254 /// [`Classification`] carries `point_type: kind` answers
12255 /// [`Self::output_arity_is_one`] matching the closed set's own
12256 /// [`crate::classification::ConvergencePointType::output_arity`]
12257 /// truth table projected through [`Arity::is_one`]. Sweep
12258 /// [`crate::classification::ConvergencePointType::ALL`] so a
12259 /// regression that (a) hard-coded the body to a fixed answer,
12260 /// (b) inverted the projection, (c) dropped the resolver hop, or
12261 /// (d) crossed the wires with the sibling `input_arity`
12262 /// projection (which disagrees on six of eight variants) fails
12263 /// HERE at the substrate primitive before drifting through the
12264 /// future `single-output-arity` fixed tag or the peer point
12265 /// surface.
12266 #[test]
12267 fn output_arity_is_one_returns_output_arity_projection_per_kind() {
12268 for populated in ConvergencePointType::ALL {
12269 let mut classification = Classification::gate_compute();
12270 classification.point_type = populated;
12271 let mut spec = empty_ephemeral();
12272 spec.classification = Some(classification);
12273 assert_eq!(
12274 spec.output_arity_is_one(),
12275 populated.output_arity().is_one(),
12276 "authored point_type={populated:?}: output_arity_is_one() drift",
12277 );
12278 }
12279 }
12280
12281 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
12282 /// with `classification: None` routes through the
12283 /// [`Self::resolved_classification`] resolver's substrate default
12284 /// [`Classification::gate_compute`], which carries `point_type:
12285 /// Gate` and `Gate.output_arity() = One`, so
12286 /// [`Self::output_arity_is_one`] returns `true`. Pins the
12287 /// resolver's default-arm short-circuit reaching this derived-
12288 /// nullary predicate — every unadorned `(defephemeral …)` lands
12289 /// in the single-output bucket under the substrate default.
12290 /// Mirror-inverted from the sibling `output_arity_is_many`
12291 /// baseline on the same resolver walk (the XOR partition forces
12292 /// exactly one bucket per baseline). Note the workspace-baseline
12293 /// answer FLIPS between the input-arity and output-arity axes on
12294 /// the exact same absent-classification baseline: the input-arity
12295 /// sibling `input_arity_is_one` answers `false`, but this
12296 /// output-arity peer answers `true` — direct evidence at the
12297 /// resolver-hop layer that the two axes carve the closed set
12298 /// into structurally different partitions.
12299 #[test]
12300 fn output_arity_is_one_probes_true_on_absent_classification() {
12301 let spec = empty_ephemeral();
12302 assert!(spec.classification.is_none());
12303 assert!(
12304 spec.output_arity_is_one(),
12305 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_one=true)",
12306 );
12307 }
12308
12309 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
12310 /// identically through [`Self::output_arity_is_one`] AND through
12311 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_one()`
12312 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
12313 /// classification, `Some(_)` classification on every
12314 /// [`crate::classification::ConvergencePointType::ALL`] variant)
12315 /// so a future regression on either side of the resolver fails
12316 /// HERE at the parity boundary. Byte-for-byte peer of
12317 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
12318 /// on the sibling output-arity projection via the same
12319 /// resolver-hop shape.
12320 #[test]
12321 fn output_arity_is_one_matches_point_peer_through_lowered_classification() {
12322 // Absent classification.
12323 let eph = empty_ephemeral();
12324 let lowered: ProcessSpec = eph.clone().into();
12325 assert_eq!(
12326 eph.output_arity_is_one(),
12327 lowered.classification.output_arity_is_one(),
12328 "None-classification parity drift",
12329 );
12330 // Authored classification.
12331 for populated in ConvergencePointType::ALL {
12332 let mut classification = Classification::gate_compute();
12333 classification.point_type = populated;
12334 let mut eph = empty_ephemeral();
12335 eph.classification = Some(classification);
12336 let lowered: ProcessSpec = eph.clone().into();
12337 assert_eq!(
12338 eph.output_arity_is_one(),
12339 lowered.classification.output_arity_is_one(),
12340 "authored point_type={populated:?}: parity drift",
12341 );
12342 }
12343 }
12344
12345 // ── EphemeralSpec::output_arity_is_many pins ────────────────────
12346 //
12347 // Fail-before-pass-after granularity: `output_arity_is_many` did
12348 // not exist pre-lift on `impl EphemeralSpec` — the multi-output
12349 // framing peer of [`Self::output_arity_is_one`] had no ephemeral-
12350 // surface substrate owner. Post-lift the NINETEENTH derived-
12351 // nullary-boolean peer on the ephemeral surface (SECOND on the
12352 // output-arity axis, CLOSING the EIGHTH classification axis into
12353 // a binary XOR partition on this surface) routes through the SAME
12354 // [`Self::resolved_classification`] resolver + the sibling
12355 // substrate primitive
12356 // [`crate::classification::Classification::output_arity_is_many`],
12357 // so the two-surface parity contract holds by construction, AND
12358 // the two-way single/many split on this surface CLOSES the
12359 // output-arity axis into the FULL binary XOR partition contract
12360 // via `ephemeral_output_arity_probes_form_binary_xor_partition_over_all`,
12361 // completing the DAG-composition arity PAIR on the ephemeral
12362 // derived-typed-projection stratum.
12363
12364 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
12365 /// [`Classification`] carries `point_type: kind` answers
12366 /// [`Self::output_arity_is_many`] matching the closed set's own
12367 /// [`crate::classification::ConvergencePointType::output_arity`]
12368 /// truth table projected through [`Arity::is_many`]. Sweep
12369 /// [`crate::classification::ConvergencePointType::ALL`] so a
12370 /// regression that (a) hard-coded the body to a fixed answer,
12371 /// (b) inverted the projection, (c) dropped the resolver hop, or
12372 /// (d) crossed the wires with the sibling `input_arity`
12373 /// projection fails HERE at the substrate primitive before
12374 /// drifting through the future `multi-output-arity` fixed tag or
12375 /// the peer point surface.
12376 #[test]
12377 fn output_arity_is_many_returns_output_arity_projection_per_kind() {
12378 for populated in ConvergencePointType::ALL {
12379 let mut classification = Classification::gate_compute();
12380 classification.point_type = populated;
12381 let mut spec = empty_ephemeral();
12382 spec.classification = Some(classification);
12383 assert_eq!(
12384 spec.output_arity_is_many(),
12385 populated.output_arity().is_many(),
12386 "authored point_type={populated:?}: output_arity_is_many() drift",
12387 );
12388 }
12389 }
12390
12391 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
12392 /// with `classification: None` routes through the
12393 /// [`Self::resolved_classification`] resolver's substrate default
12394 /// [`Classification::gate_compute`], which carries `point_type:
12395 /// Gate` and `Gate.output_arity() = One`, so
12396 /// [`Self::output_arity_is_many`] returns `false`. Pins the
12397 /// resolver's default-arm short-circuit reaching this derived-
12398 /// nullary predicate — every unadorned `(defephemeral …)` lands
12399 /// in the single-output bucket under the substrate default.
12400 /// Mirror-inverted from the sibling `output_arity_is_one`
12401 /// baseline on the same resolver walk (the XOR partition forces
12402 /// exactly one bucket per baseline).
12403 #[test]
12404 fn output_arity_is_many_probes_false_on_absent_classification() {
12405 let spec = empty_ephemeral();
12406 assert!(spec.classification.is_none());
12407 assert!(
12408 !spec.output_arity_is_many(),
12409 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_many=false)",
12410 );
12411 }
12412
12413 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
12414 /// identically through [`Self::output_arity_is_many`] AND through
12415 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_many()`
12416 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
12417 /// classification, `Some(_)` classification on every
12418 /// [`crate::classification::ConvergencePointType::ALL`] variant)
12419 /// so a future regression on either side of the resolver fails
12420 /// HERE at the parity boundary. Byte-for-byte peer of
12421 /// `output_arity_is_one_matches_point_peer_through_lowered_classification`
12422 /// on the antisymmetric closed-set arm via the same resolver-hop
12423 /// shape.
12424 #[test]
12425 fn output_arity_is_many_matches_point_peer_through_lowered_classification() {
12426 // Absent classification.
12427 let eph = empty_ephemeral();
12428 let lowered: ProcessSpec = eph.clone().into();
12429 assert_eq!(
12430 eph.output_arity_is_many(),
12431 lowered.classification.output_arity_is_many(),
12432 "None-classification parity drift",
12433 );
12434 // Authored classification.
12435 for populated in ConvergencePointType::ALL {
12436 let mut classification = Classification::gate_compute();
12437 classification.point_type = populated;
12438 let mut eph = empty_ephemeral();
12439 eph.classification = Some(classification);
12440 let lowered: ProcessSpec = eph.clone().into();
12441 assert_eq!(
12442 eph.output_arity_is_many(),
12443 lowered.classification.output_arity_is_many(),
12444 "authored point_type={populated:?}: parity drift",
12445 );
12446 }
12447 }
12448
12449 /// BINARY XOR PARTITION pin — for the absent-classification
12450 /// baseline AND every
12451 /// [`crate::classification::ConvergencePointType::ALL`] variant,
12452 /// EXACTLY ONE of [`Self::output_arity_is_one`] and
12453 /// [`Self::output_arity_is_many`] returns `true`. CLOSES the
12454 /// output-arity axis into the FULL binary XOR partition contract
12455 /// on the ephemeral surface — the resolver-hop peer of the
12456 /// parent-composed
12457 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`
12458 /// test. Binary counterpart of the ternary XOR partitions sealed
12459 /// on the sibling `point_type` and `substrate` axes by
12460 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
12461 /// and
12462 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
12463 /// structural twin of the calm/data/direction/input-arity binary
12464 /// partitions on this surface. This pin is the EIGHTH
12465 /// classification axis to reach the closed XOR partition landmark
12466 /// on the ephemeral resolver-hop surface — the SECOND closed axis
12467 /// on the derived-typed-projection stratum of this surface,
12468 /// completing the DAG-composition arity PAIR on the ephemeral
12469 /// stratum after the input-arity closure. Guarantees the absent-
12470 /// classification case lands in the definite single-output bucket
12471 /// (`gate_compute` → point_type=Gate → output_arity=One →
12472 /// is_one=true, is_many=false), so every unadorned
12473 /// `(defephemeral …)` audits under a definite non-empty
12474 /// output-arity bucket.
12475 #[test]
12476 fn ephemeral_output_arity_probes_form_binary_xor_partition_over_all() {
12477 // Absent classification.
12478 let eph = empty_ephemeral();
12479 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
12480 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12481 assert_eq!(
12482 hits, 1,
12483 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12484 );
12485 // Authored classification.
12486 for populated in ConvergencePointType::ALL {
12487 let mut classification = Classification::gate_compute();
12488 classification.point_type = populated;
12489 let mut eph = empty_ephemeral();
12490 eph.classification = Some(classification);
12491 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
12492 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12493 assert_eq!(
12494 hits, 1,
12495 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12496 );
12497 }
12498 }
12499
12500 /// BINARY XOR PARTITION pin — for the absent-classification
12501 /// baseline AND every
12502 /// [`crate::classification::HorizonKind::ALL`] variant, EXACTLY
12503 /// ONE of [`Self::horizon_terminates`] and
12504 /// [`Self::horizon_requires_metric_axes`] returns `true`. CLOSES
12505 /// the horizon axis into the FULL binary XOR partition contract
12506 /// on the ephemeral surface — the resolver-hop peer of the
12507 /// parent-composed
12508 /// `classification_horizon_probes_form_binary_xor_partition_over_all`
12509 /// test. Binary counterpart of the ternary XOR partitions sealed
12510 /// on the sibling `point_type` and `substrate` axes by
12511 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
12512 /// and
12513 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
12514 /// structural twin of the calm/data binary partitions
12515 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`
12516 /// and
12517 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
12518 /// This pin is the FIFTH (and final) classification axis to reach
12519 /// the closed XOR partition landmark on the ephemeral resolver-
12520 /// hop surface, sealing every classification axis under the
12521 /// SAME `hits == 1` bucket-array contract. Guarantees the absent-
12522 /// classification case lands in the definite terminating bucket
12523 /// (`gate_compute` → HorizonKind::Bounded → terminates = true,
12524 /// requires_metric_axes = false), so every unadorned
12525 /// `(defephemeral …)` audits under a definite non-empty horizon
12526 /// bucket. Rewritten from the earlier binary-XOR-only form
12527 /// (walked as `a ^ b`) into the canonical bucket-array shape
12528 /// shared with the calm/data partitions.
12529 #[test]
12530 fn ephemeral_horizon_probes_form_binary_xor_partition_over_all() {
12531 // Absent classification.
12532 let eph = empty_ephemeral();
12533 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
12534 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12535 assert_eq!(
12536 hits, 1,
12537 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12538 );
12539 // Authored classification.
12540 for populated in HorizonKind::ALL {
12541 let classification = Classification::gate_compute_with_axis(populated);
12542 let mut eph = empty_ephemeral();
12543 eph.classification = Some(classification);
12544 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
12545 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12546 assert_eq!(
12547 hits, 1,
12548 "authored horizon.kind={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12549 );
12550 }
12551 }
12552
12553 // ── EphemeralSpec::has_routing_form pins ─────────────────────────
12554 //
12555 // Fail-before-pass-after granularity: `has_routing_form` did not
12556 // exist pre-lift on `impl EphemeralSpec` — the point-surface
12557 // `routing-form-<kind>` prefix family in tatara-check routed
12558 // through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`
12559 // inline, so the ephemeral surface had no matching primitive to
12560 // publish the SAME `routing-form-<kind>` prefix family through
12561 // the `strip_and_classify_prefixed_kind` substrate. Post-lift the
12562 // Option-gated derived-scalar-child probe body lives at ONE
12563 // inherent site on [`EphemeralSpec`] and every consumer (this
12564 // module's peer-symmetry tests, tatara-check's ephemeral
12565 // require-tag classifier, any future audit dispatcher walking
12566 // [`RoutingForm::ALL`] over the ephemeral surface) binds through
12567 // the SAME `has_routing_form(kind)` shape.
12568
12569 fn routing_spec(is_stable: bool) -> RoutingSpec {
12570 use crate::routing::{RoutingBackend, RoutingHostname};
12571 RoutingSpec {
12572 hostnames: vec![RoutingHostname::content_hashed("api")],
12573 backend: RoutingBackend::plain("svc", 80),
12574 stable_name_claim: is_stable,
12575 priority: 0,
12576 }
12577 }
12578
12579 /// POPULATED-slot pin — a populated `routing` slot answers `true`
12580 /// exactly for the [`RoutingForm`] variant its
12581 /// [`RoutingSpec::has_form`] derived-scalar arm agrees with, and
12582 /// `false` for every other variant. Sweep the two-boolean × ALL
12583 /// cross so a regression that (a) hard-coded the arm to a single
12584 /// variant, (b) dropped the Option-parent gate (silently reading
12585 /// through `.unwrap_or_default()` on an absent routing slot), or
12586 /// (c) crossed the wires from
12587 /// [`RoutingForm::from_is_stable`] to a fixed variant fails
12588 /// HERE before landing at the operator-facing checks.lisp
12589 /// surface.
12590 #[test]
12591 fn has_routing_form_returns_true_iff_populated_routing_derives_form_per_kind() {
12592 for is_stable in [true, false] {
12593 let populated = RoutingForm::from_is_stable(is_stable);
12594 let mut spec = empty_ephemeral();
12595 spec.routing = Some(routing_spec(is_stable));
12596 for query in RoutingForm::ALL {
12597 let expected = query == populated;
12598 assert_eq!(
12599 spec.has_routing_form(query),
12600 expected,
12601 "ephemeral routing.stable_name_claim={is_stable} (derives {populated:?}): query {query:?} drifted",
12602 );
12603 }
12604 }
12605 }
12606
12607 /// OPTION-PARENT SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
12608 /// `routing` slot is `None` returns `false` for every
12609 /// [`RoutingForm`] variant, INCLUDING the closed set's
12610 /// derived-default [`RoutingForm::Instance`]. Locks the
12611 /// Option-parent silencing contract so a regression that dropped
12612 /// the `spec.routing.as_ref()` gate (silently probing an absent
12613 /// routing slot as if it carried the defaulted `Instance` form)
12614 /// fails HERE. Peer to
12615 /// [`evaluate_point_require_tag_returns_false_on_absent_routing_for_every_routing_form_kind`]
12616 /// on the point surface — the two-surface symmetry means both
12617 /// classifiers publish the SAME Option-parent silencing at ONE
12618 /// substrate site per surface.
12619 #[test]
12620 fn has_routing_form_returns_false_on_absent_routing_for_every_kind() {
12621 let spec = empty_ephemeral();
12622 assert!(spec.routing.is_none());
12623 for kind in RoutingForm::ALL {
12624 assert!(
12625 !spec.has_routing_form(kind),
12626 "absent ephemeral routing must return false for {kind:?}",
12627 );
12628 }
12629 }
12630
12631 /// DEFAULT-ARM SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
12632 /// `routing` slot is a [`RoutingSpec`] with `stable_name_claim`
12633 /// at its `#[serde(default)]` (bool default = `false`) answers
12634 /// `true` on [`RoutingForm::Instance`] and `false` on every other
12635 /// variant WITHOUT the operator naming the routing-form axis on
12636 /// the routing spec. Peer to
12637 /// [`evaluate_point_require_tag_returns_true_on_default_routing_form_for_instance_only`]
12638 /// on the point surface — both surfaces read the derived-child
12639 /// arm through the ONE substrate composer
12640 /// [`RoutingForm::from_is_stable`], so a future normalization at
12641 /// the derivation lands at ONE site and every downstream
12642 /// (routing-form require-tag families on both surfaces,
12643 /// closed-set audit dispatchers) picks it up mechanically.
12644 #[test]
12645 fn has_routing_form_probes_instance_only_on_default_populated_routing() {
12646 let mut spec = empty_ephemeral();
12647 spec.routing = Some(routing_spec(bool::default()));
12648 for kind in RoutingForm::ALL {
12649 let expected = kind == RoutingForm::Instance;
12650 assert_eq!(
12651 spec.has_routing_form(kind),
12652 expected,
12653 "default-populated ephemeral routing (stable_name_claim=false → Instance) baseline: query {kind:?} must be {expected}",
12654 );
12655 }
12656 }
12657
12658 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
12659 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
12660 /// answer identically on every [`RoutingForm`] × `is_stable`
12661 /// combination. Locks the byte-for-byte parity between
12662 /// [`EphemeralSpec::has_routing_form`] (this new primitive) and
12663 /// the point surface's `spec.routing.as_ref().is_some_and(|r|
12664 /// r.has_form(k))` inline projection at the tatara-check dispatch
12665 /// site. A regression that (a) diverged the ephemeral probe from
12666 /// the lowered point probe (e.g., dropped the Option-parent gate
12667 /// on ONE side, crossed the derived-child arm on the OTHER), or
12668 /// (b) diverged the `From<EphemeralSpec>` lowering's
12669 /// `routing: e.routing` copy from byte-for-byte forwarding, fails
12670 /// HERE at the two-surface boundary.
12671 #[test]
12672 fn has_routing_form_matches_point_peer_through_lowered_routing() {
12673 for is_stable in [true, false] {
12674 let mut authored = empty_ephemeral();
12675 authored.routing = Some(routing_spec(is_stable));
12676 let lowered: ProcessSpec = authored.clone().into();
12677 for kind in RoutingForm::ALL {
12678 let ephemeral_answer = authored.has_routing_form(kind);
12679 let point_answer = lowered.routing.as_ref().is_some_and(|r| r.has_form(kind));
12680 assert_eq!(
12681 ephemeral_answer, point_answer,
12682 "two-surface routing-form parity drift: stable_name_claim={is_stable}, kind={kind:?}",
12683 );
12684 }
12685 }
12686 }
12687
12688 // ── EphemeralSpec::has_applicable_exports_at substrate pins ───────
12689 //
12690 // Fail-before-pass-after granularity: `has_applicable_exports_at`
12691 // did not exist pre-lift on `impl EphemeralSpec` — the peer
12692 // `EphemeralLifetime::has_applicable_exports` on the lowered
12693 // `ProcessSpec` surface routed through the compound
12694 // `.iter().any(|e| e.when.fires_on(phase))` chain inline, so the
12695 // sugar surface had no matching primitive to publish an
12696 // `exports-fire-on-<phase>` prefix family through the
12697 // `strip_and_classify_prefixed_kind` substrate. Post-lift the
12698 // compound-`(when, phase) → fires_on(phase)` probe body lives at
12699 // ONE slice-level substrate site (`ExportSpecSliceExt::has_applicable_at`),
12700 // this ephemeral surface routes through it directly, and the
12701 // point surface reaches the same primitive through
12702 // `spec.lifetime.resolved_ephemeral().is_some_and(|e|
12703 // e.exports.has_applicable_at(phase))`.
12704
12705 fn export_at(when: crate::export::ExportTrigger) -> ExportSpec {
12706 use crate::export::{ArtifactSource, ReceiptsSource, StdoutChannel, VectorChannel};
12707 ExportSpec {
12708 source: ArtifactSource {
12709 receipts: Some(ReceiptsSource::default()),
12710 ..ArtifactSource::default()
12711 },
12712 channel: VectorChannel {
12713 stdout: Some(StdoutChannel::default()),
12714 ..VectorChannel::default()
12715 },
12716 when,
12717 experiment_id_override: None,
12718 }
12719 }
12720
12721 /// EMPTY-EXPORTS pin — an ephemeral spec with an empty `exports`
12722 /// vec returns `false` for EVERY [`ProcessPhase`]. Sweep
12723 /// [`ProcessPhase::ALL`] so a new variant added without a matching
12724 /// arm in [`crate::export::ExportTrigger::fires_on`] surfaces at
12725 /// rustc's exhaustiveness gate on the `ALL` literal (arity forced
12726 /// by `[Self; 11]`) rather than as a silent false-positive at
12727 /// every downstream `exports-fire-on-<phase>` ephemeral require-tag
12728 /// callsite.
12729 #[test]
12730 fn has_applicable_exports_at_returns_false_on_empty_exports_for_every_phase() {
12731 let spec = empty_ephemeral();
12732 assert!(spec.exports.is_empty());
12733 for phase in ProcessPhase::ALL {
12734 assert!(
12735 !spec.has_applicable_exports_at(phase),
12736 "empty-exports ephemeral must return false for {phase:?}",
12737 );
12738 }
12739 }
12740
12741 /// PER-TRIGGER × PER-PHASE pin — an ephemeral spec with a single
12742 /// export answers `has_applicable_exports_at` identically to the
12743 /// [`crate::export::ExportTrigger::fires_on`] truth table on that
12744 /// (trigger, phase) pair, for every combination. Sweep the
12745 /// [`crate::export::ExportTrigger::ALL`] × [`ProcessPhase::ALL`]
12746 /// cross so a regression that (a) short-circuited to raw `when ==
12747 /// kind` equality, (b) missed `Always`'s dual-phase coverage, or
12748 /// (c) inverted a non-terminal phase to return `true` fails HERE
12749 /// at the substrate primitive rather than at each downstream
12750 /// `exports-fire-on-<phase>` classifier callsite.
12751 #[test]
12752 fn has_applicable_exports_at_matches_fires_on_truth_table_per_pair() {
12753 for trigger in crate::export::ExportTrigger::ALL {
12754 let mut spec = empty_ephemeral();
12755 spec.exports = vec![export_at(trigger)];
12756 for phase in ProcessPhase::ALL {
12757 let expected = trigger.fires_on(phase);
12758 assert_eq!(
12759 spec.has_applicable_exports_at(phase),
12760 expected,
12761 "ephemeral trigger={trigger:?} phase={phase:?} drifted from fires_on",
12762 );
12763 }
12764 }
12765 }
12766
12767 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
12768 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
12769 /// answer identically on every [`ProcessPhase`] × trigger
12770 /// combination. Locks the byte-for-byte parity between
12771 /// [`EphemeralSpec::has_applicable_exports_at`] (this new primitive)
12772 /// and the point surface's `spec.lifetime.resolved_ephemeral()
12773 /// .is_some_and(|e| e.exports.has_applicable_at(phase))` projection
12774 /// at the tatara-check dispatch site. A regression that (a)
12775 /// diverged the ephemeral probe from the lowered-lifetime probe,
12776 /// (b) diverged the `From<EphemeralSpec>` lowering's
12777 /// `exports: e.exports` copy from byte-for-byte forwarding, fails
12778 /// HERE at the two-surface boundary.
12779 #[test]
12780 fn has_applicable_exports_at_matches_point_peer_through_lowered_exports() {
12781 for trigger in crate::export::ExportTrigger::ALL {
12782 let mut authored = empty_ephemeral();
12783 authored.exports = vec![export_at(trigger)];
12784 let lowered: ProcessSpec = authored.clone().into();
12785 for phase in ProcessPhase::ALL {
12786 let ephemeral_answer = authored.has_applicable_exports_at(phase);
12787 let point_answer = lowered
12788 .lifetime
12789 .resolved_ephemeral()
12790 .is_some_and(|e| e.exports.has_applicable_at(phase));
12791 assert_eq!(
12792 ephemeral_answer, point_answer,
12793 "two-surface exports-fire-on parity drift: trigger={trigger:?}, phase={phase:?}",
12794 );
12795 }
12796 }
12797 }
12798
12799 /// SUBSTRATE-DELEGATION pin (EphemeralSpec saturation-predicate
12800 /// triad) — the three `is_*_kind_saturated` methods on
12801 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
12802 /// [`ConditionSliceExt::is_kind_saturated`] over the two
12803 /// `Vec<Condition>` slots (precondition + postcondition) and
12804 /// compose the union via `ConditionKind::ALL.iter().all(|k|
12805 /// has_condition_kind(*k))`. Two-surface parity pin against
12806 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on the
12807 /// point-domain [`ProcessSpec`] surface — the two struct-level
12808 /// saturation callers compose against the SAME slice-level
12809 /// substrate primitive so a regression at the per-slice `all`
12810 /// short-circuit fails at that primitive's tests rather than as
12811 /// silent drift at either sugar-surface arm.
12812 #[test]
12813 fn is_condition_kind_saturated_triad_delegates_to_slice_is_kind_saturated() {
12814 // Empty ephemeral spec — every arm returns false.
12815 let spec = empty_ephemeral();
12816 assert!(
12817 !spec.is_precondition_kind_saturated(),
12818 "empty ephemeral must return false on is_precondition_kind_saturated",
12819 );
12820 assert!(
12821 !spec.is_postcondition_kind_saturated(),
12822 "empty ephemeral must return false on is_postcondition_kind_saturated",
12823 );
12824 assert!(
12825 !spec.is_condition_kind_saturated(),
12826 "empty ephemeral must return false on is_condition_kind_saturated",
12827 );
12828 assert_eq!(
12829 spec.is_condition_kind_saturated(),
12830 spec.missing_condition_kinds().is_empty(),
12831 "empty is_condition_kind_saturated must equal missing_condition_kinds().is_empty()",
12832 );
12833
12834 // Single-populated per side — sweep ALL × ALL.
12835 for pre_kind in ConditionKind::ALL {
12836 for post_kind in ConditionKind::ALL {
12837 let mut spec = empty_ephemeral();
12838 spec.preconditions.push(cond(pre_kind));
12839 spec.postconditions.push(cond(post_kind));
12840 assert_eq!(
12841 spec.is_precondition_kind_saturated(),
12842 spec.preconditions.is_kind_saturated(),
12843 "EphemeralSpec::is_precondition_kind_saturated must delegate verbatim to \
12844 preconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
12845 );
12846 assert_eq!(
12847 spec.is_postcondition_kind_saturated(),
12848 spec.postconditions.is_kind_saturated(),
12849 "EphemeralSpec::is_postcondition_kind_saturated must delegate verbatim to \
12850 postconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
12851 );
12852 let expected_union = ConditionKind::ALL
12853 .iter()
12854 .all(|k| pre_kind == *k || post_kind == *k);
12855 assert_eq!(
12856 spec.is_condition_kind_saturated(),
12857 expected_union,
12858 "EphemeralSpec::is_condition_kind_saturated must equal all-ALL-covered-by-either-slice \
12859 for pre={pre_kind:?} post={post_kind:?}",
12860 );
12861
12862 // Two-surface parity: lowered ProcessSpec's Boundary
12863 // must agree bit-for-bit with the ephemeral sugar
12864 // triad on every arm.
12865 let lowered: ProcessSpec = spec.clone().into();
12866 assert_eq!(
12867 spec.is_precondition_kind_saturated(),
12868 lowered.boundary.is_precondition_kind_saturated(),
12869 "two-surface is_precondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12870 );
12871 assert_eq!(
12872 spec.is_postcondition_kind_saturated(),
12873 lowered.boundary.is_postcondition_kind_saturated(),
12874 "two-surface is_postcondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12875 );
12876 assert_eq!(
12877 spec.is_condition_kind_saturated(),
12878 lowered.boundary.is_condition_kind_saturated(),
12879 "two-surface is_condition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12880 );
12881 }
12882 }
12883
12884 // Saturated ephemeral — both slices carry every ConditionKind,
12885 // every arm returns true.
12886 let mut spec = empty_ephemeral();
12887 for k in ConditionKind::ALL {
12888 spec.preconditions.push(cond(k));
12889 spec.postconditions.push(cond(k));
12890 }
12891 assert!(
12892 spec.is_precondition_kind_saturated(),
12893 "saturated ephemeral must return true on is_precondition_kind_saturated",
12894 );
12895 assert!(
12896 spec.is_postcondition_kind_saturated(),
12897 "saturated ephemeral must return true on is_postcondition_kind_saturated",
12898 );
12899 assert!(
12900 spec.is_condition_kind_saturated(),
12901 "saturated ephemeral must return true on is_condition_kind_saturated",
12902 );
12903 }
12904
12905 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
12906 /// triad) — the three `has_any_missing_*_condition_kind` methods
12907 /// on [`EphemeralSpec`] delegate to the slice-level substrate
12908 /// primitive
12909 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
12910 /// over the two `Vec<Condition>` slots (precondition +
12911 /// postcondition) and compose the union via
12912 /// `!self.is_condition_kind_saturated()`. Two-surface parity pin
12913 /// against
12914 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
12915 /// the point-domain [`ProcessSpec`] surface — the two struct-level
12916 /// at-least-one halfspace callers compose against the SAME slice-
12917 /// level substrate primitive so a regression at the per-slice
12918 /// `all` short-circuit under negation fails at that primitive's
12919 /// tests rather than as silent drift at either sugar-surface arm.
12920 #[test]
12921 fn has_any_missing_condition_kind_triad_delegates_to_slice_has_any_missing_kind() {
12922 // Empty ephemeral spec — every arm returns true (every kind is
12923 // missing from every slice + from the union).
12924 let spec = empty_ephemeral();
12925 assert!(
12926 spec.has_any_missing_precondition_kind(),
12927 "empty ephemeral must return true on has_any_missing_precondition_kind",
12928 );
12929 assert!(
12930 spec.has_any_missing_postcondition_kind(),
12931 "empty ephemeral must return true on has_any_missing_postcondition_kind",
12932 );
12933 assert!(
12934 spec.has_any_missing_condition_kind(),
12935 "empty ephemeral must return true on has_any_missing_condition_kind",
12936 );
12937 assert_eq!(
12938 spec.has_any_missing_condition_kind(),
12939 !spec.is_condition_kind_saturated(),
12940 "empty has_any_missing_condition_kind must equal !is_condition_kind_saturated()",
12941 );
12942
12943 // Single-populated per side — sweep ALL × ALL, then pin the
12944 // (pre, post, union) triad + two-surface parity against the
12945 // lowered ProcessSpec's Boundary.
12946 for pre_kind in ConditionKind::ALL {
12947 for post_kind in ConditionKind::ALL {
12948 let mut spec = empty_ephemeral();
12949 spec.preconditions.push(cond(pre_kind));
12950 spec.postconditions.push(cond(post_kind));
12951 assert_eq!(
12952 spec.has_any_missing_precondition_kind(),
12953 spec.preconditions.has_any_missing_kind(),
12954 "EphemeralSpec::has_any_missing_precondition_kind must delegate verbatim to \
12955 preconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12956 );
12957 assert_eq!(
12958 spec.has_any_missing_postcondition_kind(),
12959 spec.postconditions.has_any_missing_kind(),
12960 "EphemeralSpec::has_any_missing_postcondition_kind must delegate verbatim to \
12961 postconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12962 );
12963 let expected_union = !ConditionKind::ALL
12964 .iter()
12965 .all(|k| pre_kind == *k || post_kind == *k);
12966 assert_eq!(
12967 spec.has_any_missing_condition_kind(),
12968 expected_union,
12969 "EphemeralSpec::has_any_missing_condition_kind must equal \
12970 !all-ALL-covered-by-either-slice \
12971 for pre={pre_kind:?} post={post_kind:?}",
12972 );
12973
12974 // Two-surface parity: lowered ProcessSpec's Boundary
12975 // must agree bit-for-bit with the ephemeral sugar
12976 // triad on every arm.
12977 let lowered: ProcessSpec = spec.clone().into();
12978 assert_eq!(
12979 spec.has_any_missing_precondition_kind(),
12980 lowered.boundary.has_any_missing_precondition_kind(),
12981 "two-surface has_any_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12982 );
12983 assert_eq!(
12984 spec.has_any_missing_postcondition_kind(),
12985 lowered.boundary.has_any_missing_postcondition_kind(),
12986 "two-surface has_any_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12987 );
12988 assert_eq!(
12989 spec.has_any_missing_condition_kind(),
12990 lowered.boundary.has_any_missing_condition_kind(),
12991 "two-surface has_any_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12992 );
12993 }
12994 }
12995
12996 // Saturated ephemeral — both slices carry every ConditionKind,
12997 // every arm returns false.
12998 let mut spec = empty_ephemeral();
12999 for k in ConditionKind::ALL {
13000 spec.preconditions.push(cond(k));
13001 spec.postconditions.push(cond(k));
13002 }
13003 assert!(
13004 !spec.has_any_missing_precondition_kind(),
13005 "saturated ephemeral must return false on has_any_missing_precondition_kind",
13006 );
13007 assert!(
13008 !spec.has_any_missing_postcondition_kind(),
13009 "saturated ephemeral must return false on has_any_missing_postcondition_kind",
13010 );
13011 assert!(
13012 !spec.has_any_missing_condition_kind(),
13013 "saturated ephemeral must return false on has_any_missing_condition_kind",
13014 );
13015 }
13016
13017 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
13018 /// triad on the closed-set-inversion axis) — the three
13019 /// `has_any_distinct_*_condition_kind` methods on
13020 /// [`EphemeralSpec`] delegate to the slice-level substrate
13021 /// primitive
13022 /// [`crate::boundary::ConditionSliceExt::has_any_distinct_kind`]
13023 /// over the two `Vec<Condition>` slots (precondition +
13024 /// postcondition) and compose the union via a SHORT-CIRCUITING
13025 /// closed-set walk over [`ConditionKind::ALL`] under
13026 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13027 /// against
13028 /// [`crate::boundary::Boundary::has_any_distinct_condition_kind`]
13029 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13030 /// level at-least-one halfspace callers compose against the SAME
13031 /// slice-level substrate primitive so a regression at the per-
13032 /// slice `any` short-circuit fails at that primitive's tests
13033 /// rather than as silent drift at either sugar-surface arm.
13034 #[test]
13035 fn has_any_distinct_condition_kind_triad_delegates_to_slice_has_any_distinct_kind() {
13036 // Empty ephemeral spec — every arm returns false (no kind
13037 // present in either slice).
13038 let spec = empty_ephemeral();
13039 assert!(
13040 !spec.has_any_distinct_precondition_kind(),
13041 "empty ephemeral must return false on has_any_distinct_precondition_kind",
13042 );
13043 assert!(
13044 !spec.has_any_distinct_postcondition_kind(),
13045 "empty ephemeral must return false on has_any_distinct_postcondition_kind",
13046 );
13047 assert!(
13048 !spec.has_any_distinct_condition_kind(),
13049 "empty ephemeral must return false on has_any_distinct_condition_kind",
13050 );
13051
13052 // Single-populated per side — sweep ALL × ALL, then pin the
13053 // (pre, post, union) triad + two-surface parity against the
13054 // lowered ProcessSpec's Boundary.
13055 for pre_kind in ConditionKind::ALL {
13056 for post_kind in ConditionKind::ALL {
13057 let mut spec = empty_ephemeral();
13058 spec.preconditions.push(cond(pre_kind));
13059 spec.postconditions.push(cond(post_kind));
13060 assert_eq!(
13061 spec.has_any_distinct_precondition_kind(),
13062 spec.preconditions.has_any_distinct_kind(),
13063 "EphemeralSpec::has_any_distinct_precondition_kind must delegate verbatim to \
13064 preconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13065 );
13066 assert_eq!(
13067 spec.has_any_distinct_postcondition_kind(),
13068 spec.postconditions.has_any_distinct_kind(),
13069 "EphemeralSpec::has_any_distinct_postcondition_kind must delegate verbatim to \
13070 postconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13071 );
13072 assert!(
13073 spec.has_any_distinct_precondition_kind(),
13074 "single-populated preconditions must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
13075 );
13076 assert!(
13077 spec.has_any_distinct_postcondition_kind(),
13078 "single-populated postconditions must return true on has_any_distinct_postcondition_kind for post={post_kind:?}",
13079 );
13080 assert!(
13081 spec.has_any_distinct_condition_kind(),
13082 "single-populated-per-side must return true on has_any_distinct_condition_kind for pre={pre_kind:?} post={post_kind:?}",
13083 );
13084
13085 // Two-surface parity: lowered ProcessSpec's Boundary
13086 // must agree bit-for-bit with the ephemeral sugar
13087 // triad on every arm.
13088 let lowered: ProcessSpec = spec.clone().into();
13089 assert_eq!(
13090 spec.has_any_distinct_precondition_kind(),
13091 lowered.boundary.has_any_distinct_precondition_kind(),
13092 "two-surface has_any_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13093 );
13094 assert_eq!(
13095 spec.has_any_distinct_postcondition_kind(),
13096 lowered.boundary.has_any_distinct_postcondition_kind(),
13097 "two-surface has_any_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13098 );
13099 assert_eq!(
13100 spec.has_any_distinct_condition_kind(),
13101 lowered.boundary.has_any_distinct_condition_kind(),
13102 "two-surface has_any_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13103 );
13104 }
13105 }
13106
13107 // Single-populated precondition only — precondition arm true,
13108 // postcondition arm false, union true.
13109 for pre_kind in ConditionKind::ALL {
13110 let mut spec = empty_ephemeral();
13111 spec.preconditions.push(cond(pre_kind));
13112 assert!(
13113 spec.has_any_distinct_precondition_kind(),
13114 "pre-only ephemeral must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
13115 );
13116 assert!(
13117 !spec.has_any_distinct_postcondition_kind(),
13118 "pre-only ephemeral must return false on has_any_distinct_postcondition_kind for pre={pre_kind:?}",
13119 );
13120 assert!(
13121 spec.has_any_distinct_condition_kind(),
13122 "pre-only ephemeral must return true on has_any_distinct_condition_kind for pre={pre_kind:?}",
13123 );
13124 }
13125
13126 // Saturated ephemeral — both slices carry every ConditionKind,
13127 // every arm returns true.
13128 let mut spec = empty_ephemeral();
13129 for k in ConditionKind::ALL {
13130 spec.preconditions.push(cond(k));
13131 spec.postconditions.push(cond(k));
13132 }
13133 assert!(
13134 spec.has_any_distinct_precondition_kind(),
13135 "saturated ephemeral must return true on has_any_distinct_precondition_kind",
13136 );
13137 assert!(
13138 spec.has_any_distinct_postcondition_kind(),
13139 "saturated ephemeral must return true on has_any_distinct_postcondition_kind",
13140 );
13141 assert!(
13142 spec.has_any_distinct_condition_kind(),
13143 "saturated ephemeral must return true on has_any_distinct_condition_kind",
13144 );
13145 }
13146
13147 /// SUBSTRATE-DELEGATION pin (EphemeralSpec singleton-coverage
13148 /// triad on the closed-set-inversion axis) — the three
13149 /// `has_unique_distinct_*_condition_kind` methods on
13150 /// [`EphemeralSpec`] delegate to the slice-level substrate
13151 /// primitive
13152 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
13153 /// over the two `Vec<Condition>` slots (precondition +
13154 /// postcondition) and compose the union via a two-step-short-
13155 /// circuit walk over [`ConditionKind::ALL`] under
13156 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13157 /// against
13158 /// [`crate::boundary::Boundary::has_unique_distinct_condition_kind`]
13159 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13160 /// level singleton-coverage callers compose against the SAME
13161 /// slice-level substrate primitive so a regression at the per-
13162 /// slice two-step short-circuit walk fails at that primitive's
13163 /// tests rather than as silent drift at either sugar-surface arm.
13164 #[test]
13165 fn has_unique_distinct_condition_kind_triad_delegates_to_slice_has_unique_distinct_kind() {
13166 // Empty ephemeral spec — every arm returns false (0 distinct,
13167 // not exactly 1).
13168 let spec = empty_ephemeral();
13169 assert!(
13170 !spec.has_unique_distinct_precondition_kind(),
13171 "empty ephemeral must return false on has_unique_distinct_precondition_kind",
13172 );
13173 assert!(
13174 !spec.has_unique_distinct_postcondition_kind(),
13175 "empty ephemeral must return false on has_unique_distinct_postcondition_kind",
13176 );
13177 assert!(
13178 !spec.has_unique_distinct_condition_kind(),
13179 "empty ephemeral must return false on has_unique_distinct_condition_kind",
13180 );
13181 assert_eq!(
13182 spec.has_unique_distinct_condition_kind(),
13183 spec.distinct_condition_kind_count() == 1,
13184 "empty has_unique_distinct_condition_kind must equal (distinct_condition_kind_count() == 1)",
13185 );
13186
13187 // Single-populated per side — sweep ALL × ALL. Every per-
13188 // slice arm returns true; the union returns true iff the two
13189 // populated kinds coincide (union covers exactly one kind).
13190 for pre_kind in ConditionKind::ALL {
13191 for post_kind in ConditionKind::ALL {
13192 let mut spec = empty_ephemeral();
13193 spec.preconditions.push(cond(pre_kind));
13194 spec.postconditions.push(cond(post_kind));
13195 assert_eq!(
13196 spec.has_unique_distinct_precondition_kind(),
13197 spec.preconditions.has_unique_distinct_kind(),
13198 "EphemeralSpec::has_unique_distinct_precondition_kind must delegate verbatim to \
13199 preconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13200 );
13201 assert_eq!(
13202 spec.has_unique_distinct_postcondition_kind(),
13203 spec.postconditions.has_unique_distinct_kind(),
13204 "EphemeralSpec::has_unique_distinct_postcondition_kind must delegate verbatim to \
13205 postconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13206 );
13207 let covered_count = ConditionKind::ALL
13208 .into_iter()
13209 .filter(|k| *k == pre_kind || *k == post_kind)
13210 .count();
13211 let expected_union = covered_count == 1;
13212 assert_eq!(
13213 spec.has_unique_distinct_condition_kind(),
13214 expected_union,
13215 "EphemeralSpec::has_unique_distinct_condition_kind must equal \
13216 (covered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
13217 );
13218
13219 // Two-surface parity: lowered ProcessSpec's Boundary
13220 // must agree bit-for-bit with the ephemeral sugar
13221 // triad on every arm.
13222 let lowered: ProcessSpec = spec.clone().into();
13223 assert_eq!(
13224 spec.has_unique_distinct_precondition_kind(),
13225 lowered.boundary.has_unique_distinct_precondition_kind(),
13226 "two-surface has_unique_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13227 );
13228 assert_eq!(
13229 spec.has_unique_distinct_postcondition_kind(),
13230 lowered.boundary.has_unique_distinct_postcondition_kind(),
13231 "two-surface has_unique_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13232 );
13233 assert_eq!(
13234 spec.has_unique_distinct_condition_kind(),
13235 lowered.boundary.has_unique_distinct_condition_kind(),
13236 "two-surface has_unique_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13237 );
13238 }
13239 }
13240
13241 // Saturated ephemeral — every arm returns false on N ≥ 2 (N
13242 // distinct, not exactly 1).
13243 if ConditionKind::ALL.len() >= 2 {
13244 let mut spec = empty_ephemeral();
13245 for k in ConditionKind::ALL {
13246 spec.preconditions.push(cond(k));
13247 spec.postconditions.push(cond(k));
13248 }
13249 assert!(
13250 !spec.has_unique_distinct_precondition_kind(),
13251 "saturated ephemeral must return false on has_unique_distinct_precondition_kind",
13252 );
13253 assert!(
13254 !spec.has_unique_distinct_postcondition_kind(),
13255 "saturated ephemeral must return false on has_unique_distinct_postcondition_kind",
13256 );
13257 assert!(
13258 !spec.has_unique_distinct_condition_kind(),
13259 "saturated ephemeral must return false on has_unique_distinct_condition_kind",
13260 );
13261 }
13262 }
13263
13264 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
13265 /// triad on the closed-set-inversion axis) — the three
13266 /// `has_multiple_distinct_*_condition_kind` methods on
13267 /// [`EphemeralSpec`] delegate to the slice-level substrate
13268 /// primitive
13269 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
13270 /// over the two `Vec<Condition>` slots (precondition +
13271 /// postcondition) and compose the union via a two-step-short-
13272 /// circuit walk over [`ConditionKind::ALL`] under
13273 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13274 /// against
13275 /// [`crate::boundary::Boundary::has_multiple_distinct_condition_kind`]
13276 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13277 /// level many-distinct callers compose against the SAME slice-
13278 /// level substrate primitive so a regression at the per-slice
13279 /// two-step short-circuit walk fails at that primitive's tests
13280 /// rather than as silent drift at either sugar-surface arm.
13281 #[test]
13282 fn has_multiple_distinct_condition_kind_triad_delegates_to_slice_has_multiple_distinct_kinds() {
13283 // Empty ephemeral spec — every arm returns false (0 distinct,
13284 // not ≥ 2).
13285 let spec = empty_ephemeral();
13286 assert!(
13287 !spec.has_multiple_distinct_precondition_kind(),
13288 "empty ephemeral must return false on has_multiple_distinct_precondition_kind",
13289 );
13290 assert!(
13291 !spec.has_multiple_distinct_postcondition_kind(),
13292 "empty ephemeral must return false on has_multiple_distinct_postcondition_kind",
13293 );
13294 assert!(
13295 !spec.has_multiple_distinct_condition_kind(),
13296 "empty ephemeral must return false on has_multiple_distinct_condition_kind",
13297 );
13298 assert_eq!(
13299 spec.has_multiple_distinct_condition_kind(),
13300 spec.distinct_condition_kind_count() >= 2,
13301 "empty has_multiple_distinct_condition_kind must equal (distinct_condition_kind_count() >= 2)",
13302 );
13303
13304 // Single-populated per side — sweep ALL × ALL. Every per-slice
13305 // arm returns false (1 distinct per slice, not ≥ 2); the
13306 // union returns true iff the two kinds DIFFER (union covers 2
13307 // distinct kinds).
13308 assert!(
13309 ConditionKind::ALL.len() >= 2,
13310 "test assumes ConditionKind::ALL has ≥ 2 variants",
13311 );
13312 for pre_kind in ConditionKind::ALL {
13313 for post_kind in ConditionKind::ALL {
13314 let mut spec = empty_ephemeral();
13315 spec.preconditions.push(cond(pre_kind));
13316 spec.postconditions.push(cond(post_kind));
13317 assert_eq!(
13318 spec.has_multiple_distinct_precondition_kind(),
13319 spec.preconditions.has_multiple_distinct_kinds(),
13320 "EphemeralSpec::has_multiple_distinct_precondition_kind must delegate verbatim to \
13321 preconditions.has_multiple_distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
13322 );
13323 assert_eq!(
13324 spec.has_multiple_distinct_postcondition_kind(),
13325 spec.postconditions.has_multiple_distinct_kinds(),
13326 "EphemeralSpec::has_multiple_distinct_postcondition_kind must delegate verbatim to \
13327 postconditions.has_multiple_distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
13328 );
13329 let covered_count = ConditionKind::ALL
13330 .into_iter()
13331 .filter(|k| *k == pre_kind || *k == post_kind)
13332 .count();
13333 let expected_union = covered_count >= 2;
13334 assert_eq!(
13335 spec.has_multiple_distinct_condition_kind(),
13336 expected_union,
13337 "EphemeralSpec::has_multiple_distinct_condition_kind must equal \
13338 (covered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
13339 );
13340
13341 // Two-surface parity: lowered ProcessSpec's Boundary
13342 // must agree bit-for-bit with the ephemeral sugar
13343 // triad on every arm.
13344 let lowered: ProcessSpec = spec.clone().into();
13345 assert_eq!(
13346 spec.has_multiple_distinct_precondition_kind(),
13347 lowered.boundary.has_multiple_distinct_precondition_kind(),
13348 "two-surface has_multiple_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13349 );
13350 assert_eq!(
13351 spec.has_multiple_distinct_postcondition_kind(),
13352 lowered.boundary.has_multiple_distinct_postcondition_kind(),
13353 "two-surface has_multiple_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13354 );
13355 assert_eq!(
13356 spec.has_multiple_distinct_condition_kind(),
13357 lowered.boundary.has_multiple_distinct_condition_kind(),
13358 "two-surface has_multiple_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13359 );
13360 }
13361 }
13362
13363 // Saturated ephemeral — every arm returns true on N ≥ 2 (N
13364 // distinct, ≥ 2).
13365 let mut spec = empty_ephemeral();
13366 for k in ConditionKind::ALL {
13367 spec.preconditions.push(cond(k));
13368 spec.postconditions.push(cond(k));
13369 }
13370 assert!(
13371 spec.has_multiple_distinct_precondition_kind(),
13372 "saturated ephemeral must return true on has_multiple_distinct_precondition_kind",
13373 );
13374 assert!(
13375 spec.has_multiple_distinct_postcondition_kind(),
13376 "saturated ephemeral must return true on has_multiple_distinct_postcondition_kind",
13377 );
13378 assert!(
13379 spec.has_multiple_distinct_condition_kind(),
13380 "saturated ephemeral must return true on has_multiple_distinct_condition_kind",
13381 );
13382 }
13383
13384 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1" triad
13385 /// on the closed-set-inversion axis) — the three
13386 /// `has_at_most_one_distinct_*_condition_kind` methods on
13387 /// [`EphemeralSpec`] delegate to the slice-level substrate
13388 /// primitive
13389 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
13390 /// over the two `Vec<Condition>` slots (precondition +
13391 /// postcondition) and compose the union via a definitional
13392 /// negation of the many-arm two-step-short-circuit walk over
13393 /// [`ConditionKind::ALL`] under
13394 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13395 /// against
13396 /// [`crate::boundary::Boundary::has_at_most_one_distinct_condition_kind`]
13397 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13398 /// level empty-or-singleton callers compose against the SAME
13399 /// slice-level substrate primitive so a regression at the per-
13400 /// slice "≤ 1" negation fails at that primitive's tests rather
13401 /// than as silent drift at either sugar-surface arm.
13402 #[test]
13403 fn has_at_most_one_distinct_condition_kind_triad_delegates_to_slice_has_at_most_one_distinct_kind(
13404 ) {
13405 // Empty ephemeral spec — every arm returns true (0 distinct,
13406 // ≤ 1).
13407 let spec = empty_ephemeral();
13408 assert!(
13409 spec.has_at_most_one_distinct_precondition_kind(),
13410 "empty ephemeral must return true on has_at_most_one_distinct_precondition_kind",
13411 );
13412 assert!(
13413 spec.has_at_most_one_distinct_postcondition_kind(),
13414 "empty ephemeral must return true on has_at_most_one_distinct_postcondition_kind",
13415 );
13416 assert!(
13417 spec.has_at_most_one_distinct_condition_kind(),
13418 "empty ephemeral must return true on has_at_most_one_distinct_condition_kind",
13419 );
13420 assert_eq!(
13421 spec.has_at_most_one_distinct_condition_kind(),
13422 spec.distinct_condition_kind_count() <= 1,
13423 "empty has_at_most_one_distinct_condition_kind must equal (distinct_condition_kind_count() <= 1)",
13424 );
13425
13426 // Single-populated per side — sweep ALL × ALL. Every per-slice
13427 // arm returns true (1 distinct per slice, ≤ 1); the union
13428 // returns true iff the two kinds COINCIDE (union has 1
13429 // distinct), otherwise the union has 2 distinct and drops to
13430 // false.
13431 assert!(
13432 ConditionKind::ALL.len() >= 2,
13433 "test assumes ConditionKind::ALL has ≥ 2 variants",
13434 );
13435 for pre_kind in ConditionKind::ALL {
13436 for post_kind in ConditionKind::ALL {
13437 let mut spec = empty_ephemeral();
13438 spec.preconditions.push(cond(pre_kind));
13439 spec.postconditions.push(cond(post_kind));
13440 assert_eq!(
13441 spec.has_at_most_one_distinct_precondition_kind(),
13442 spec.preconditions.has_at_most_one_distinct_kind(),
13443 "EphemeralSpec::has_at_most_one_distinct_precondition_kind must delegate verbatim to \
13444 preconditions.has_at_most_one_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13445 );
13446 assert_eq!(
13447 spec.has_at_most_one_distinct_postcondition_kind(),
13448 spec.postconditions.has_at_most_one_distinct_kind(),
13449 "EphemeralSpec::has_at_most_one_distinct_postcondition_kind must delegate verbatim to \
13450 postconditions.has_at_most_one_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13451 );
13452 let covered_count = ConditionKind::ALL
13453 .into_iter()
13454 .filter(|k| *k == pre_kind || *k == post_kind)
13455 .count();
13456 let expected_union = covered_count <= 1;
13457 assert_eq!(
13458 spec.has_at_most_one_distinct_condition_kind(),
13459 expected_union,
13460 "EphemeralSpec::has_at_most_one_distinct_condition_kind must equal \
13461 (covered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
13462 );
13463
13464 // Two-surface parity: lowered ProcessSpec's Boundary
13465 // must agree bit-for-bit with the ephemeral sugar
13466 // triad on every arm.
13467 let lowered: ProcessSpec = spec.clone().into();
13468 assert_eq!(
13469 spec.has_at_most_one_distinct_precondition_kind(),
13470 lowered.boundary.has_at_most_one_distinct_precondition_kind(),
13471 "two-surface has_at_most_one_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13472 );
13473 assert_eq!(
13474 spec.has_at_most_one_distinct_postcondition_kind(),
13475 lowered.boundary.has_at_most_one_distinct_postcondition_kind(),
13476 "two-surface has_at_most_one_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13477 );
13478 assert_eq!(
13479 spec.has_at_most_one_distinct_condition_kind(),
13480 lowered.boundary.has_at_most_one_distinct_condition_kind(),
13481 "two-surface has_at_most_one_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13482 );
13483 }
13484 }
13485
13486 // Saturated ephemeral — every arm returns false on N ≥ 2 (N
13487 // distinct, not ≤ 1).
13488 let mut spec = empty_ephemeral();
13489 for k in ConditionKind::ALL {
13490 spec.preconditions.push(cond(k));
13491 spec.postconditions.push(cond(k));
13492 }
13493 assert!(
13494 !spec.has_at_most_one_distinct_precondition_kind(),
13495 "saturated ephemeral must return false on has_at_most_one_distinct_precondition_kind",
13496 );
13497 assert!(
13498 !spec.has_at_most_one_distinct_postcondition_kind(),
13499 "saturated ephemeral must return false on has_at_most_one_distinct_postcondition_kind",
13500 );
13501 assert!(
13502 !spec.has_at_most_one_distinct_condition_kind(),
13503 "saturated ephemeral must return false on has_at_most_one_distinct_condition_kind",
13504 );
13505 }
13506
13507 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality zero-
13508 /// endpoint triad) — the three `is_*_condition_kind_empty` methods
13509 /// on [`EphemeralSpec`] delegate to the slice-level substrate
13510 /// primitive
13511 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] over the
13512 /// two `Vec<Condition>` slots (precondition + postcondition) and
13513 /// compose the union via a definitional negation of the at-least-
13514 /// one halfspace primitive
13515 /// [`EphemeralSpec::has_any_distinct_condition_kind`]. Two-surface
13516 /// parity pin against
13517 /// [`crate::boundary::Boundary::is_condition_kind_empty`] on the
13518 /// point-domain [`ProcessSpec`] surface — the two struct-level
13519 /// zero-endpoint callers compose against the SAME slice-level
13520 /// substrate primitive so a regression at the per-slice zero-
13521 /// endpoint short-circuit fails at that primitive's tests rather
13522 /// than as silent drift at either sugar-surface arm.
13523 #[test]
13524 fn is_condition_kind_empty_triad_delegates_to_slice_is_kind_empty() {
13525 // Empty ephemeral spec — every arm returns true (0 distinct,
13526 // = 0).
13527 let spec = empty_ephemeral();
13528 assert!(
13529 spec.is_precondition_kind_empty(),
13530 "empty ephemeral must return true on is_precondition_kind_empty",
13531 );
13532 assert!(
13533 spec.is_postcondition_kind_empty(),
13534 "empty ephemeral must return true on is_postcondition_kind_empty",
13535 );
13536 assert!(
13537 spec.is_condition_kind_empty(),
13538 "empty ephemeral must return true on is_condition_kind_empty",
13539 );
13540
13541 // Two-surface parity: EphemeralSpec's three arms are byte-for-
13542 // byte equal to the lowered ProcessSpec's Boundary arms across
13543 // every sweep arm.
13544 let lowered: ProcessSpec = spec.clone().into();
13545 assert_eq!(
13546 spec.is_precondition_kind_empty(),
13547 lowered.boundary.is_precondition_kind_empty(),
13548 "empty ephemeral is_precondition_kind_empty must equal lowered Boundary is_precondition_kind_empty",
13549 );
13550 assert_eq!(
13551 spec.is_postcondition_kind_empty(),
13552 lowered.boundary.is_postcondition_kind_empty(),
13553 "empty ephemeral is_postcondition_kind_empty must equal lowered Boundary is_postcondition_kind_empty",
13554 );
13555 assert_eq!(
13556 spec.is_condition_kind_empty(),
13557 lowered.boundary.is_condition_kind_empty(),
13558 "empty ephemeral is_condition_kind_empty must equal lowered Boundary is_condition_kind_empty",
13559 );
13560
13561 // Single-populated per side — every per-slice arm returns
13562 // false; the union always returns false.
13563 assert!(
13564 !ConditionKind::ALL.is_empty(),
13565 "test assumes ConditionKind::ALL has ≥ 1 variants",
13566 );
13567 for pre_kind in ConditionKind::ALL {
13568 for post_kind in ConditionKind::ALL {
13569 let mut spec = empty_ephemeral();
13570 spec.preconditions.push(cond(pre_kind));
13571 spec.postconditions.push(cond(post_kind));
13572 assert_eq!(
13573 spec.is_precondition_kind_empty(),
13574 spec.preconditions.is_kind_empty(),
13575 "EphemeralSpec::is_precondition_kind_empty must delegate verbatim to \
13576 preconditions.is_kind_empty() for pre={pre_kind:?} post={post_kind:?}",
13577 );
13578 assert_eq!(
13579 spec.is_postcondition_kind_empty(),
13580 spec.postconditions.is_kind_empty(),
13581 "EphemeralSpec::is_postcondition_kind_empty must delegate verbatim to \
13582 postconditions.is_kind_empty() for pre={pre_kind:?} post={post_kind:?}",
13583 );
13584 assert!(
13585 !spec.is_precondition_kind_empty(),
13586 "single-populated preconditions must return false on is_precondition_kind_empty for pre={pre_kind:?}",
13587 );
13588 assert!(
13589 !spec.is_postcondition_kind_empty(),
13590 "single-populated postconditions must return false on is_postcondition_kind_empty for post={post_kind:?}",
13591 );
13592 assert!(
13593 !spec.is_condition_kind_empty(),
13594 "single-populated union must return false on is_condition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13595 );
13596 assert_eq!(
13597 spec.is_condition_kind_empty(),
13598 !spec.has_any_distinct_condition_kind(),
13599 "EphemeralSpec::is_condition_kind_empty must equal !has_any_distinct_condition_kind() for pre={pre_kind:?} post={post_kind:?}",
13600 );
13601 // Two-surface parity with lowered Boundary.
13602 let lowered: ProcessSpec = spec.clone().into();
13603 assert_eq!(
13604 spec.is_precondition_kind_empty(),
13605 lowered.boundary.is_precondition_kind_empty(),
13606 "EphemeralSpec::is_precondition_kind_empty must equal lowered Boundary::is_precondition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13607 );
13608 assert_eq!(
13609 spec.is_postcondition_kind_empty(),
13610 lowered.boundary.is_postcondition_kind_empty(),
13611 "EphemeralSpec::is_postcondition_kind_empty must equal lowered Boundary::is_postcondition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13612 );
13613 assert_eq!(
13614 spec.is_condition_kind_empty(),
13615 lowered.boundary.is_condition_kind_empty(),
13616 "EphemeralSpec::is_condition_kind_empty must equal lowered Boundary::is_condition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13617 );
13618 }
13619 }
13620
13621 // Saturated ephemeral spec — every arm returns false on N ≥ 1
13622 // (every kind PRESENT across the union, not = 0).
13623 let mut spec = empty_ephemeral();
13624 for k in ConditionKind::ALL {
13625 spec.preconditions.push(cond(k));
13626 spec.postconditions.push(cond(k));
13627 }
13628 assert!(
13629 !spec.is_precondition_kind_empty(),
13630 "saturated ephemeral must return false on is_precondition_kind_empty",
13631 );
13632 assert!(
13633 !spec.is_postcondition_kind_empty(),
13634 "saturated ephemeral must return false on is_postcondition_kind_empty",
13635 );
13636 assert!(
13637 !spec.is_condition_kind_empty(),
13638 "saturated ephemeral must return false on is_condition_kind_empty",
13639 );
13640 }
13641
13642 /// SUBSTRATE-DELEGATION pin (EphemeralSpec parent-state middle-arm
13643 /// triad) — the three `is_*_condition_kind_partially_covered`
13644 /// methods on [`EphemeralSpec`] delegate to the slice-level
13645 /// substrate primitive
13646 /// [`crate::boundary::ConditionSliceExt::is_kind_partially_covered`]
13647 /// over the two `Vec<Condition>` slots (precondition +
13648 /// postcondition) and compose the union via the paired-halfspace
13649 /// body `has_any_distinct_condition_kind() && has_any_missing_condition_kind()`.
13650 /// Two-surface parity pin against
13651 /// [`crate::boundary::Boundary::is_condition_kind_partially_covered`]
13652 /// on the point-domain [`ProcessSpec`] surface — the two
13653 /// struct-level middle-arm callers compose against the SAME
13654 /// slice-level substrate primitive so a regression at the per-
13655 /// slice fused short-circuit walk fails at that primitive's tests
13656 /// rather than as silent drift at either sugar-surface arm.
13657 #[test]
13658 fn is_condition_kind_partially_covered_triad_delegates_to_slice_is_kind_partially_covered() {
13659 // Empty ephemeral spec — every arm returns false on any N ≥ 1
13660 // closed set (0 distinct hits the empty arm).
13661 assert!(
13662 !ConditionKind::ALL.is_empty(),
13663 "test assumes ConditionKind::ALL has ≥ 1 variants",
13664 );
13665 let spec = empty_ephemeral();
13666 assert!(
13667 !spec.is_precondition_kind_partially_covered(),
13668 "empty ephemeral must return false on is_precondition_kind_partially_covered",
13669 );
13670 assert!(
13671 !spec.is_postcondition_kind_partially_covered(),
13672 "empty ephemeral must return false on is_postcondition_kind_partially_covered",
13673 );
13674 assert!(
13675 !spec.is_condition_kind_partially_covered(),
13676 "empty ephemeral must return false on is_condition_kind_partially_covered",
13677 );
13678
13679 // Two-surface parity: EphemeralSpec's three arms are byte-for-
13680 // byte equal to the lowered ProcessSpec's Boundary arms.
13681 let lowered: ProcessSpec = spec.clone().into();
13682 assert_eq!(
13683 spec.is_precondition_kind_partially_covered(),
13684 lowered.boundary.is_precondition_kind_partially_covered(),
13685 "empty ephemeral is_precondition_kind_partially_covered must equal lowered Boundary is_precondition_kind_partially_covered",
13686 );
13687 assert_eq!(
13688 spec.is_postcondition_kind_partially_covered(),
13689 lowered.boundary.is_postcondition_kind_partially_covered(),
13690 "empty ephemeral is_postcondition_kind_partially_covered must equal lowered Boundary is_postcondition_kind_partially_covered",
13691 );
13692 assert_eq!(
13693 spec.is_condition_kind_partially_covered(),
13694 lowered.boundary.is_condition_kind_partially_covered(),
13695 "empty ephemeral is_condition_kind_partially_covered must equal lowered Boundary is_condition_kind_partially_covered",
13696 );
13697
13698 // Single-populated per side — every per-slice arm returns
13699 // true on any N ≥ 2 closed set; union true iff coverage
13700 // leaves ≥ 1 ALL variant uncovered.
13701 if ConditionKind::ALL.len() >= 2 {
13702 for pre_kind in ConditionKind::ALL {
13703 for post_kind in ConditionKind::ALL {
13704 let mut spec = empty_ephemeral();
13705 spec.preconditions.push(cond(pre_kind));
13706 spec.postconditions.push(cond(post_kind));
13707 assert_eq!(
13708 spec.is_precondition_kind_partially_covered(),
13709 spec.preconditions.is_kind_partially_covered(),
13710 "EphemeralSpec::is_precondition_kind_partially_covered must delegate verbatim to \
13711 preconditions.is_kind_partially_covered() for pre={pre_kind:?} post={post_kind:?}",
13712 );
13713 assert_eq!(
13714 spec.is_postcondition_kind_partially_covered(),
13715 spec.postconditions.is_kind_partially_covered(),
13716 "EphemeralSpec::is_postcondition_kind_partially_covered must delegate verbatim to \
13717 postconditions.is_kind_partially_covered() for pre={pre_kind:?} post={post_kind:?}",
13718 );
13719 assert!(
13720 spec.is_precondition_kind_partially_covered(),
13721 "single-populated preconditions must return true on is_precondition_kind_partially_covered for pre={pre_kind:?}",
13722 );
13723 assert!(
13724 spec.is_postcondition_kind_partially_covered(),
13725 "single-populated postconditions must return true on is_postcondition_kind_partially_covered for post={post_kind:?}",
13726 );
13727 let covered_count = if pre_kind == post_kind { 1 } else { 2 };
13728 let expected_union = ConditionKind::ALL.len() > covered_count;
13729 assert_eq!(
13730 spec.is_condition_kind_partially_covered(),
13731 expected_union,
13732 "EphemeralSpec::is_condition_kind_partially_covered must equal \
13733 (ConditionKind::ALL.len() > covered-kinds-count) for pre={pre_kind:?} post={post_kind:?}",
13734 );
13735 // Two-surface parity with lowered Boundary.
13736 let lowered: ProcessSpec = spec.clone().into();
13737 assert_eq!(
13738 spec.is_precondition_kind_partially_covered(),
13739 lowered.boundary.is_precondition_kind_partially_covered(),
13740 "EphemeralSpec::is_precondition_kind_partially_covered must equal lowered Boundary::is_precondition_kind_partially_covered for pre={pre_kind:?} post={post_kind:?}",
13741 );
13742 assert_eq!(
13743 spec.is_postcondition_kind_partially_covered(),
13744 lowered.boundary.is_postcondition_kind_partially_covered(),
13745 "EphemeralSpec::is_postcondition_kind_partially_covered must equal lowered Boundary::is_postcondition_kind_partially_covered for pre={pre_kind:?} post={post_kind:?}",
13746 );
13747 assert_eq!(
13748 spec.is_condition_kind_partially_covered(),
13749 lowered.boundary.is_condition_kind_partially_covered(),
13750 "EphemeralSpec::is_condition_kind_partially_covered must equal lowered Boundary::is_condition_kind_partially_covered for pre={pre_kind:?} post={post_kind:?}",
13751 );
13752 // Trichotomy partition on the union axis.
13753 assert_eq!(
13754 usize::from(spec.is_condition_kind_empty())
13755 + usize::from(spec.is_condition_kind_partially_covered())
13756 + usize::from(spec.is_condition_kind_saturated()),
13757 1,
13758 "EphemeralSpec union trichotomy partition violated for pre={pre_kind:?} post={post_kind:?}",
13759 );
13760 }
13761 }
13762 }
13763
13764 // Saturated ephemeral spec — every arm returns false on any
13765 // N ≥ 1 closed set (0 missing hits the saturated arm).
13766 let mut spec = empty_ephemeral();
13767 for k in ConditionKind::ALL {
13768 spec.preconditions.push(cond(k));
13769 spec.postconditions.push(cond(k));
13770 }
13771 assert!(
13772 !spec.is_precondition_kind_partially_covered(),
13773 "saturated ephemeral must return false on is_precondition_kind_partially_covered",
13774 );
13775 assert!(
13776 !spec.is_postcondition_kind_partially_covered(),
13777 "saturated ephemeral must return false on is_postcondition_kind_partially_covered",
13778 );
13779 assert!(
13780 !spec.is_condition_kind_partially_covered(),
13781 "saturated ephemeral must return false on is_condition_kind_partially_covered",
13782 );
13783 }
13784
13785 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-mid-endpoint
13786 /// triad) — the three `has_unique_missing_*_condition_kind`
13787 /// methods on [`EphemeralSpec`] delegate to the slice-level
13788 /// substrate primitive
13789 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
13790 /// over the two `Vec<Condition>` slots (precondition +
13791 /// postcondition) and compose the union via a two-step-short-
13792 /// circuit walk over [`ConditionKind::ALL`] under negated
13793 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13794 /// against
13795 /// [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
13796 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13797 /// level near-saturation-endpoint callers compose against the
13798 /// SAME slice-level substrate primitive so a regression at the
13799 /// per-slice two-step short-circuit walk under negation fails at
13800 /// that primitive's tests rather than as silent drift at either
13801 /// sugar-surface arm.
13802 #[test]
13803 fn has_unique_missing_condition_kind_triad_delegates_to_slice_has_unique_missing_kind() {
13804 // Empty ephemeral spec — every arm returns false (all N
13805 // missing, not exactly 1) on any N ≥ 2 closed set.
13806 assert!(
13807 ConditionKind::ALL.len() >= 2,
13808 "test assumes ConditionKind::ALL has ≥ 2 variants",
13809 );
13810 let spec = empty_ephemeral();
13811 assert!(
13812 !spec.has_unique_missing_precondition_kind(),
13813 "empty ephemeral must return false on has_unique_missing_precondition_kind",
13814 );
13815 assert!(
13816 !spec.has_unique_missing_postcondition_kind(),
13817 "empty ephemeral must return false on has_unique_missing_postcondition_kind",
13818 );
13819 assert!(
13820 !spec.has_unique_missing_condition_kind(),
13821 "empty ephemeral must return false on has_unique_missing_condition_kind",
13822 );
13823 assert_eq!(
13824 spec.has_unique_missing_condition_kind(),
13825 spec.missing_condition_kind_count() == 1,
13826 "empty has_unique_missing_condition_kind must equal (missing_condition_kind_count() == 1)",
13827 );
13828
13829 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
13830 // sets. Every per-slice arm returns false; the union returns
13831 // true iff exactly one ALL variant is uncovered.
13832 if ConditionKind::ALL.len() >= 3 {
13833 for pre_kind in ConditionKind::ALL {
13834 for post_kind in ConditionKind::ALL {
13835 let mut spec = empty_ephemeral();
13836 spec.preconditions.push(cond(pre_kind));
13837 spec.postconditions.push(cond(post_kind));
13838 assert_eq!(
13839 spec.has_unique_missing_precondition_kind(),
13840 spec.preconditions.has_unique_missing_kind(),
13841 "EphemeralSpec::has_unique_missing_precondition_kind must delegate verbatim to \
13842 preconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13843 );
13844 assert_eq!(
13845 spec.has_unique_missing_postcondition_kind(),
13846 spec.postconditions.has_unique_missing_kind(),
13847 "EphemeralSpec::has_unique_missing_postcondition_kind must delegate verbatim to \
13848 postconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13849 );
13850 let uncovered = ConditionKind::ALL
13851 .into_iter()
13852 .filter(|k| *k != pre_kind && *k != post_kind)
13853 .count();
13854 let expected_union = uncovered == 1;
13855 assert_eq!(
13856 spec.has_unique_missing_condition_kind(),
13857 expected_union,
13858 "EphemeralSpec::has_unique_missing_condition_kind must equal \
13859 (uncovered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
13860 );
13861
13862 // Two-surface parity: lowered ProcessSpec's
13863 // Boundary must agree bit-for-bit with the
13864 // ephemeral sugar triad on every arm.
13865 let lowered: ProcessSpec = spec.clone().into();
13866 assert_eq!(
13867 spec.has_unique_missing_precondition_kind(),
13868 lowered.boundary.has_unique_missing_precondition_kind(),
13869 "two-surface has_unique_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13870 );
13871 assert_eq!(
13872 spec.has_unique_missing_postcondition_kind(),
13873 lowered.boundary.has_unique_missing_postcondition_kind(),
13874 "two-surface has_unique_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13875 );
13876 assert_eq!(
13877 spec.has_unique_missing_condition_kind(),
13878 lowered.boundary.has_unique_missing_condition_kind(),
13879 "two-surface has_unique_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13880 );
13881 }
13882 }
13883 }
13884
13885 // Near-saturation-endpoint per side — each slice carries
13886 // every ConditionKind except one. Every per-slice arm returns
13887 // true; the union returns true iff BOTH slices omit the SAME
13888 // kind.
13889 for pre_omit in ConditionKind::ALL {
13890 for post_omit in ConditionKind::ALL {
13891 let mut spec = empty_ephemeral();
13892 for k in ConditionKind::ALL {
13893 if k != pre_omit {
13894 spec.preconditions.push(cond(k));
13895 }
13896 if k != post_omit {
13897 spec.postconditions.push(cond(k));
13898 }
13899 }
13900 assert!(
13901 spec.has_unique_missing_precondition_kind(),
13902 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_unique_missing_precondition_kind",
13903 );
13904 assert!(
13905 spec.has_unique_missing_postcondition_kind(),
13906 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_unique_missing_postcondition_kind",
13907 );
13908 let expected_union = pre_omit == post_omit;
13909 assert_eq!(
13910 spec.has_unique_missing_condition_kind(),
13911 expected_union,
13912 "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:?}",
13913 );
13914
13915 // Two-surface parity for near-saturation arm.
13916 let lowered: ProcessSpec = spec.clone().into();
13917 assert_eq!(
13918 spec.has_unique_missing_precondition_kind(),
13919 lowered.boundary.has_unique_missing_precondition_kind(),
13920 "two-surface has_unique_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13921 );
13922 assert_eq!(
13923 spec.has_unique_missing_postcondition_kind(),
13924 lowered.boundary.has_unique_missing_postcondition_kind(),
13925 "two-surface has_unique_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13926 );
13927 assert_eq!(
13928 spec.has_unique_missing_condition_kind(),
13929 lowered.boundary.has_unique_missing_condition_kind(),
13930 "two-surface has_unique_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13931 );
13932 }
13933 }
13934
13935 // Saturated ephemeral — every arm returns false (0 missing,
13936 // not exactly 1).
13937 let mut spec = empty_ephemeral();
13938 for k in ConditionKind::ALL {
13939 spec.preconditions.push(cond(k));
13940 spec.postconditions.push(cond(k));
13941 }
13942 assert!(
13943 !spec.has_unique_missing_precondition_kind(),
13944 "saturated ephemeral must return false on has_unique_missing_precondition_kind",
13945 );
13946 assert!(
13947 !spec.has_unique_missing_postcondition_kind(),
13948 "saturated ephemeral must return false on has_unique_missing_postcondition_kind",
13949 );
13950 assert!(
13951 !spec.has_unique_missing_condition_kind(),
13952 "saturated ephemeral must return false on has_unique_missing_condition_kind",
13953 );
13954 }
13955
13956 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
13957 /// triad) — the three `has_multiple_missing_*_condition_kind`
13958 /// methods on [`EphemeralSpec`] delegate to the slice-level
13959 /// substrate primitive
13960 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
13961 /// over the two `Vec<Condition>` slots (precondition +
13962 /// postcondition) and compose the union via a two-step-short-
13963 /// circuit walk over [`ConditionKind::ALL`] under negated
13964 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13965 /// against
13966 /// [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
13967 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13968 /// level cardinality-many-arm callers compose against the SAME
13969 /// slice-level substrate primitive so a regression at the per-
13970 /// slice two-step short-circuit walk under negation fails at that
13971 /// primitive's tests rather than as silent drift at either sugar-
13972 /// surface arm.
13973 #[test]
13974 fn has_multiple_missing_condition_kind_triad_delegates_to_slice_has_multiple_missing_kinds() {
13975 // Empty ephemeral spec — every arm returns true (all N
13976 // missing, ≥ 2) on any N ≥ 2 closed set.
13977 assert!(
13978 ConditionKind::ALL.len() >= 2,
13979 "test assumes ConditionKind::ALL has ≥ 2 variants",
13980 );
13981 let spec = empty_ephemeral();
13982 assert!(
13983 spec.has_multiple_missing_precondition_kind(),
13984 "empty ephemeral must return true on has_multiple_missing_precondition_kind",
13985 );
13986 assert!(
13987 spec.has_multiple_missing_postcondition_kind(),
13988 "empty ephemeral must return true on has_multiple_missing_postcondition_kind",
13989 );
13990 assert!(
13991 spec.has_multiple_missing_condition_kind(),
13992 "empty ephemeral must return true on has_multiple_missing_condition_kind",
13993 );
13994 assert_eq!(
13995 spec.has_multiple_missing_condition_kind(),
13996 spec.missing_condition_kind_count() >= 2,
13997 "empty has_multiple_missing_condition_kind must equal (missing_condition_kind_count() >= 2)",
13998 );
13999
14000 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
14001 // sets. Every per-slice arm returns true; the union returns
14002 // true iff ≥ 2 ALL variants are uncovered.
14003 if ConditionKind::ALL.len() >= 3 {
14004 for pre_kind in ConditionKind::ALL {
14005 for post_kind in ConditionKind::ALL {
14006 let mut spec = empty_ephemeral();
14007 spec.preconditions.push(cond(pre_kind));
14008 spec.postconditions.push(cond(post_kind));
14009 assert_eq!(
14010 spec.has_multiple_missing_precondition_kind(),
14011 spec.preconditions.has_multiple_missing_kinds(),
14012 "EphemeralSpec::has_multiple_missing_precondition_kind must delegate verbatim to \
14013 preconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
14014 );
14015 assert_eq!(
14016 spec.has_multiple_missing_postcondition_kind(),
14017 spec.postconditions.has_multiple_missing_kinds(),
14018 "EphemeralSpec::has_multiple_missing_postcondition_kind must delegate verbatim to \
14019 postconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
14020 );
14021 let uncovered = ConditionKind::ALL
14022 .into_iter()
14023 .filter(|k| *k != pre_kind && *k != post_kind)
14024 .count();
14025 let expected_union = uncovered >= 2;
14026 assert_eq!(
14027 spec.has_multiple_missing_condition_kind(),
14028 expected_union,
14029 "EphemeralSpec::has_multiple_missing_condition_kind must equal \
14030 (uncovered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
14031 );
14032
14033 // Two-surface parity: lowered ProcessSpec's
14034 // Boundary must agree bit-for-bit with the
14035 // ephemeral sugar triad on every arm.
14036 let lowered: ProcessSpec = spec.clone().into();
14037 assert_eq!(
14038 spec.has_multiple_missing_precondition_kind(),
14039 lowered.boundary.has_multiple_missing_precondition_kind(),
14040 "two-surface has_multiple_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14041 );
14042 assert_eq!(
14043 spec.has_multiple_missing_postcondition_kind(),
14044 lowered.boundary.has_multiple_missing_postcondition_kind(),
14045 "two-surface has_multiple_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14046 );
14047 assert_eq!(
14048 spec.has_multiple_missing_condition_kind(),
14049 lowered.boundary.has_multiple_missing_condition_kind(),
14050 "two-surface has_multiple_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14051 );
14052 }
14053 }
14054 }
14055
14056 // Near-saturation-endpoint per side — each slice carries
14057 // every ConditionKind except one. Every per-slice arm returns
14058 // false (exactly 1 missing per slice, not ≥ 2). The union
14059 // has at most 1 missing (pre and post's omissions either
14060 // coincide → 1 missing, or differ → 0 missing), so the union
14061 // is always false on this arm.
14062 for pre_omit in ConditionKind::ALL {
14063 for post_omit in ConditionKind::ALL {
14064 let mut spec = empty_ephemeral();
14065 for k in ConditionKind::ALL {
14066 if k != pre_omit {
14067 spec.preconditions.push(cond(k));
14068 }
14069 if k != post_omit {
14070 spec.postconditions.push(cond(k));
14071 }
14072 }
14073 assert!(
14074 !spec.has_multiple_missing_precondition_kind(),
14075 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return false on has_multiple_missing_precondition_kind",
14076 );
14077 assert!(
14078 !spec.has_multiple_missing_postcondition_kind(),
14079 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return false on has_multiple_missing_postcondition_kind",
14080 );
14081 assert!(
14082 !spec.has_multiple_missing_condition_kind(),
14083 "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:?}",
14084 );
14085
14086 // Two-surface parity for near-saturation arm.
14087 let lowered: ProcessSpec = spec.clone().into();
14088 assert_eq!(
14089 spec.has_multiple_missing_precondition_kind(),
14090 lowered.boundary.has_multiple_missing_precondition_kind(),
14091 "two-surface has_multiple_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14092 );
14093 assert_eq!(
14094 spec.has_multiple_missing_postcondition_kind(),
14095 lowered.boundary.has_multiple_missing_postcondition_kind(),
14096 "two-surface has_multiple_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14097 );
14098 assert_eq!(
14099 spec.has_multiple_missing_condition_kind(),
14100 lowered.boundary.has_multiple_missing_condition_kind(),
14101 "two-surface has_multiple_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14102 );
14103 }
14104 }
14105
14106 // Saturated ephemeral — every arm returns false (0 missing,
14107 // not ≥ 2).
14108 let mut spec = empty_ephemeral();
14109 for k in ConditionKind::ALL {
14110 spec.preconditions.push(cond(k));
14111 spec.postconditions.push(cond(k));
14112 }
14113 assert!(
14114 !spec.has_multiple_missing_precondition_kind(),
14115 "saturated ephemeral must return false on has_multiple_missing_precondition_kind",
14116 );
14117 assert!(
14118 !spec.has_multiple_missing_postcondition_kind(),
14119 "saturated ephemeral must return false on has_multiple_missing_postcondition_kind",
14120 );
14121 assert!(
14122 !spec.has_multiple_missing_condition_kind(),
14123 "saturated ephemeral must return false on has_multiple_missing_condition_kind",
14124 );
14125 }
14126
14127 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1"
14128 /// triad) — the three `has_at_most_one_missing_*_condition_kind`
14129 /// methods on [`EphemeralSpec`] delegate to the slice-level
14130 /// substrate primitive
14131 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
14132 /// over the two `Vec<Condition>` slots (precondition +
14133 /// postcondition) and compose the union via
14134 /// `!self.has_multiple_missing_condition_kind()` — a definitional
14135 /// negation of the many-arm union primitive. Two-surface parity
14136 /// pin against
14137 /// [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
14138 /// on the point-domain [`ProcessSpec`] surface — the two struct-
14139 /// level cardinality "≤ 1" callers compose against the SAME
14140 /// slice-level substrate primitive so a regression at the per-
14141 /// slice "≤ 1" negation fails at that primitive's tests rather
14142 /// than as silent drift at either sugar-surface arm.
14143 #[test]
14144 fn has_at_most_one_missing_condition_kind_triad_delegates_to_slice_has_at_most_one_missing_kind(
14145 ) {
14146 // Empty ephemeral spec — every arm returns false (all N
14147 // missing, not ≤ 1) on any N ≥ 2 closed set.
14148 assert!(
14149 ConditionKind::ALL.len() >= 2,
14150 "test assumes ConditionKind::ALL has ≥ 2 variants",
14151 );
14152 let spec = empty_ephemeral();
14153 assert!(
14154 !spec.has_at_most_one_missing_precondition_kind(),
14155 "empty ephemeral must return false on has_at_most_one_missing_precondition_kind",
14156 );
14157 assert!(
14158 !spec.has_at_most_one_missing_postcondition_kind(),
14159 "empty ephemeral must return false on has_at_most_one_missing_postcondition_kind",
14160 );
14161 assert!(
14162 !spec.has_at_most_one_missing_condition_kind(),
14163 "empty ephemeral must return false on has_at_most_one_missing_condition_kind",
14164 );
14165 assert_eq!(
14166 spec.has_at_most_one_missing_condition_kind(),
14167 spec.missing_condition_kind_count() <= 1,
14168 "empty has_at_most_one_missing_condition_kind must equal (missing_condition_kind_count() <= 1)",
14169 );
14170
14171 // Single-populated per side — sweep ALL × ALL on N ≥ 3
14172 // closed sets. Every per-slice arm returns false; the union
14173 // returns true iff ≤ 1 ALL variant is uncovered.
14174 if ConditionKind::ALL.len() >= 3 {
14175 for pre_kind in ConditionKind::ALL {
14176 for post_kind in ConditionKind::ALL {
14177 let mut spec = empty_ephemeral();
14178 spec.preconditions.push(cond(pre_kind));
14179 spec.postconditions.push(cond(post_kind));
14180 assert_eq!(
14181 spec.has_at_most_one_missing_precondition_kind(),
14182 spec.preconditions.has_at_most_one_missing_kind(),
14183 "EphemeralSpec::has_at_most_one_missing_precondition_kind must delegate verbatim to \
14184 preconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14185 );
14186 assert_eq!(
14187 spec.has_at_most_one_missing_postcondition_kind(),
14188 spec.postconditions.has_at_most_one_missing_kind(),
14189 "EphemeralSpec::has_at_most_one_missing_postcondition_kind must delegate verbatim to \
14190 postconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14191 );
14192 let uncovered = ConditionKind::ALL
14193 .into_iter()
14194 .filter(|k| *k != pre_kind && *k != post_kind)
14195 .count();
14196 let expected_union = uncovered <= 1;
14197 assert_eq!(
14198 spec.has_at_most_one_missing_condition_kind(),
14199 expected_union,
14200 "EphemeralSpec::has_at_most_one_missing_condition_kind must equal \
14201 (uncovered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
14202 );
14203
14204 // Two-surface parity: lowered ProcessSpec's
14205 // Boundary must agree bit-for-bit with the
14206 // ephemeral sugar triad on every arm.
14207 let lowered: ProcessSpec = spec.clone().into();
14208 assert_eq!(
14209 spec.has_at_most_one_missing_precondition_kind(),
14210 lowered.boundary.has_at_most_one_missing_precondition_kind(),
14211 "two-surface has_at_most_one_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14212 );
14213 assert_eq!(
14214 spec.has_at_most_one_missing_postcondition_kind(),
14215 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
14216 "two-surface has_at_most_one_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14217 );
14218 assert_eq!(
14219 spec.has_at_most_one_missing_condition_kind(),
14220 lowered.boundary.has_at_most_one_missing_condition_kind(),
14221 "two-surface has_at_most_one_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14222 );
14223 }
14224 }
14225 }
14226
14227 // Near-saturation-endpoint per side — each slice carries
14228 // every ConditionKind except one. Every per-slice arm returns
14229 // true (exactly 1 missing per slice, ≤ 1). The union has ≤ 1
14230 // missing (pre and post's omissions either coincide → 1
14231 // missing, or differ → 0 missing), so the union is always
14232 // true on this arm.
14233 for pre_omit in ConditionKind::ALL {
14234 for post_omit in ConditionKind::ALL {
14235 let mut spec = empty_ephemeral();
14236 for k in ConditionKind::ALL {
14237 if k != pre_omit {
14238 spec.preconditions.push(cond(k));
14239 }
14240 if k != post_omit {
14241 spec.postconditions.push(cond(k));
14242 }
14243 }
14244 assert!(
14245 spec.has_at_most_one_missing_precondition_kind(),
14246 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_at_most_one_missing_precondition_kind",
14247 );
14248 assert!(
14249 spec.has_at_most_one_missing_postcondition_kind(),
14250 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_at_most_one_missing_postcondition_kind",
14251 );
14252 assert!(
14253 spec.has_at_most_one_missing_condition_kind(),
14254 "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:?}",
14255 );
14256
14257 // Two-surface parity for near-saturation arm.
14258 let lowered: ProcessSpec = spec.clone().into();
14259 assert_eq!(
14260 spec.has_at_most_one_missing_precondition_kind(),
14261 lowered.boundary.has_at_most_one_missing_precondition_kind(),
14262 "two-surface has_at_most_one_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14263 );
14264 assert_eq!(
14265 spec.has_at_most_one_missing_postcondition_kind(),
14266 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
14267 "two-surface has_at_most_one_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14268 );
14269 assert_eq!(
14270 spec.has_at_most_one_missing_condition_kind(),
14271 lowered.boundary.has_at_most_one_missing_condition_kind(),
14272 "two-surface has_at_most_one_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14273 );
14274 }
14275 }
14276
14277 // Saturated ephemeral — every arm returns true (0 missing,
14278 // ≤ 1).
14279 let mut spec = empty_ephemeral();
14280 for k in ConditionKind::ALL {
14281 spec.preconditions.push(cond(k));
14282 spec.postconditions.push(cond(k));
14283 }
14284 assert!(
14285 spec.has_at_most_one_missing_precondition_kind(),
14286 "saturated ephemeral must return true on has_at_most_one_missing_precondition_kind",
14287 );
14288 assert!(
14289 spec.has_at_most_one_missing_postcondition_kind(),
14290 "saturated ephemeral must return true on has_at_most_one_missing_postcondition_kind",
14291 );
14292 assert!(
14293 spec.has_at_most_one_missing_condition_kind(),
14294 "saturated ephemeral must return true on has_at_most_one_missing_condition_kind",
14295 );
14296 }
14297
14298 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind-complement
14299 /// triad) — the three `lacks_*_condition_kind` methods on
14300 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
14301 /// [`ConditionSliceExt::lacks_kind`] over the two `Vec<Condition>`
14302 /// slots (precondition + postcondition) and compose the union via
14303 /// `!self.has_condition_kind(kind)`. Two-surface parity pin against
14304 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
14305 /// point-domain [`ProcessSpec`] surface — the two struct-level
14306 /// per-kind-complement callers compose against the SAME slice-level
14307 /// substrate primitive so a regression at the per-slice negation
14308 /// fails at that primitive's tests rather than as silent drift at
14309 /// either sugar-surface arm. Also pins the composition laws
14310 /// `lacks_*_condition_kind(k) == !has_*_condition_kind(k)` at each
14311 /// arm AND `lacks_condition_kind(k) == lacks_precondition_kind(k) &&
14312 /// lacks_postcondition_kind(k)` (the union AND-composition dual of
14313 /// `has`'s OR-composition).
14314 #[test]
14315 fn lacks_condition_kind_triad_delegates_to_slice_lacks_kind() {
14316 // Empty ephemeral spec — every arm returns true on every kind.
14317 let spec = empty_ephemeral();
14318 for kind in ConditionKind::ALL {
14319 assert!(
14320 spec.lacks_precondition_kind(kind),
14321 "empty ephemeral must return true on lacks_precondition_kind for {kind:?}",
14322 );
14323 assert!(
14324 spec.lacks_postcondition_kind(kind),
14325 "empty ephemeral must return true on lacks_postcondition_kind for {kind:?}",
14326 );
14327 assert!(
14328 spec.lacks_condition_kind(kind),
14329 "empty ephemeral must return true on lacks_condition_kind for {kind:?}",
14330 );
14331 assert_eq!(
14332 spec.lacks_condition_kind(kind),
14333 !spec.has_condition_kind(kind),
14334 "empty lacks_condition_kind must equal !has_condition_kind for {kind:?}",
14335 );
14336 }
14337
14338 // Single-populated per side — sweep ALL × ALL, then probe every
14339 // ConditionKind on the (pre, post, union) triad + two-surface
14340 // parity against the lowered ProcessSpec's Boundary.
14341 for pre_kind in ConditionKind::ALL {
14342 for post_kind in ConditionKind::ALL {
14343 let mut spec = empty_ephemeral();
14344 spec.preconditions.push(cond(pre_kind));
14345 spec.postconditions.push(cond(post_kind));
14346 let lowered: ProcessSpec = spec.clone().into();
14347 for probe in ConditionKind::ALL {
14348 assert_eq!(
14349 spec.lacks_precondition_kind(probe),
14350 spec.preconditions.lacks_kind(probe),
14351 "EphemeralSpec::lacks_precondition_kind must delegate verbatim to preconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14352 );
14353 assert_eq!(
14354 spec.lacks_postcondition_kind(probe),
14355 spec.postconditions.lacks_kind(probe),
14356 "EphemeralSpec::lacks_postcondition_kind must delegate verbatim to postconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14357 );
14358 let expected_union = pre_kind != probe && post_kind != probe;
14359 assert_eq!(
14360 spec.lacks_condition_kind(probe),
14361 expected_union,
14362 "EphemeralSpec::lacks_condition_kind must equal all-ALL-absent-in-both-slices for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14363 );
14364 assert_eq!(
14365 spec.lacks_condition_kind(probe),
14366 !spec.has_condition_kind(probe),
14367 "EphemeralSpec::lacks_condition_kind must equal !has_condition_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14368 );
14369 assert_eq!(
14370 spec.lacks_condition_kind(probe),
14371 spec.lacks_precondition_kind(probe)
14372 && spec.lacks_postcondition_kind(probe),
14373 "EphemeralSpec::lacks_condition_kind must equal AND-of-half-slice-arms for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14374 );
14375
14376 // Two-surface parity: lowered ProcessSpec's Boundary
14377 // must agree bit-for-bit with the ephemeral sugar
14378 // triad on every arm.
14379 assert_eq!(
14380 spec.lacks_precondition_kind(probe),
14381 lowered.boundary.lacks_precondition_kind(probe),
14382 "two-surface lacks_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14383 );
14384 assert_eq!(
14385 spec.lacks_postcondition_kind(probe),
14386 lowered.boundary.lacks_postcondition_kind(probe),
14387 "two-surface lacks_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14388 );
14389 assert_eq!(
14390 spec.lacks_condition_kind(probe),
14391 lowered.boundary.lacks_condition_kind(probe),
14392 "two-surface lacks_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14393 );
14394 }
14395 }
14396 }
14397
14398 // Saturated ephemeral — both slices carry every ConditionKind,
14399 // every arm returns false on every kind.
14400 let mut spec = empty_ephemeral();
14401 for k in ConditionKind::ALL {
14402 spec.preconditions.push(cond(k));
14403 spec.postconditions.push(cond(k));
14404 }
14405 for kind in ConditionKind::ALL {
14406 assert!(
14407 !spec.lacks_precondition_kind(kind),
14408 "saturated ephemeral must return false on lacks_precondition_kind for {kind:?}",
14409 );
14410 assert!(
14411 !spec.lacks_postcondition_kind(kind),
14412 "saturated ephemeral must return false on lacks_postcondition_kind for {kind:?}",
14413 );
14414 assert!(
14415 !spec.lacks_condition_kind(kind),
14416 "saturated ephemeral must return false on lacks_condition_kind for {kind:?}",
14417 );
14418 }
14419 }
14420
14421 /// TRIAD delegation pin — the (precondition, postcondition,
14422 /// condition-union) kind-scoped strict-refinement triad on
14423 /// [`EphemeralSpec`] agrees byte-for-byte with the slice-level
14424 /// substrate primitive
14425 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] on every
14426 /// authored arrangement AND with the lowered
14427 /// [`ProcessSpec::boundary`]'s kind-scoped strict-refinement
14428 /// triad through the `From<EphemeralSpec>` bridge — the two-
14429 /// surface parity contract at the well-formed-diagonal arm.
14430 ///
14431 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
14432 /// single-populated-per-side arrangements (the well-formed
14433 /// diagonal), probing every [`ConditionKind`] at the union arm
14434 /// against the DERIVED oracle `pre_kind == probe && post_kind ==
14435 /// probe`. Also sweeps the single-side-only-populated arms (the
14436 /// union carries a singleton distinct set — pins the union arm
14437 /// reaches the union primitive, not the (pre AND post) AND-
14438 /// composition). A regression at the union arm's fused walk or
14439 /// at the `From<EphemeralSpec>` bridge surfaces HERE.
14440 #[test]
14441 fn has_only_condition_kind_triad_delegates_to_slice_has_only_kind() {
14442 // Empty ephemeral spec — every arm returns false on every
14443 // kind (no kind is populated, so no kind is "only").
14444 let spec = empty_ephemeral();
14445 for kind in ConditionKind::ALL {
14446 assert!(
14447 !spec.has_only_precondition_kind(kind),
14448 "empty ephemeral must return false on has_only_precondition_kind for {kind:?}",
14449 );
14450 assert!(
14451 !spec.has_only_postcondition_kind(kind),
14452 "empty ephemeral must return false on has_only_postcondition_kind for {kind:?}",
14453 );
14454 assert!(
14455 !spec.has_only_condition_kind(kind),
14456 "empty ephemeral must return false on has_only_condition_kind for {kind:?}",
14457 );
14458 }
14459
14460 // Single-populated per side — sweep ALL × ALL, then probe
14461 // every ConditionKind on the (pre, post, union) triad + two-
14462 // surface parity against the lowered ProcessSpec's Boundary.
14463 for pre_kind in ConditionKind::ALL {
14464 for post_kind in ConditionKind::ALL {
14465 let mut spec = empty_ephemeral();
14466 spec.preconditions.push(cond(pre_kind));
14467 spec.postconditions.push(cond(post_kind));
14468 let lowered: ProcessSpec = spec.clone().into();
14469 for probe in ConditionKind::ALL {
14470 assert_eq!(
14471 spec.has_only_precondition_kind(probe),
14472 spec.preconditions.has_only_kind(probe),
14473 "EphemeralSpec::has_only_precondition_kind must delegate verbatim to preconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14474 );
14475 assert_eq!(
14476 spec.has_only_postcondition_kind(probe),
14477 spec.postconditions.has_only_kind(probe),
14478 "EphemeralSpec::has_only_postcondition_kind must delegate verbatim to postconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14479 );
14480 let expected_union = pre_kind == probe && post_kind == probe;
14481 assert_eq!(
14482 spec.has_only_condition_kind(probe),
14483 expected_union,
14484 "EphemeralSpec::has_only_condition_kind must equal (pre_kind == probe && post_kind == probe) for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14485 );
14486
14487 // Two-surface parity: lowered ProcessSpec's
14488 // Boundary must agree bit-for-bit with the
14489 // ephemeral sugar triad on every arm.
14490 assert_eq!(
14491 spec.has_only_precondition_kind(probe),
14492 lowered.boundary.has_only_precondition_kind(probe),
14493 "two-surface has_only_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14494 );
14495 assert_eq!(
14496 spec.has_only_postcondition_kind(probe),
14497 lowered.boundary.has_only_postcondition_kind(probe),
14498 "two-surface has_only_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14499 );
14500 assert_eq!(
14501 spec.has_only_condition_kind(probe),
14502 lowered.boundary.has_only_condition_kind(probe),
14503 "two-surface has_only_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14504 );
14505 }
14506 }
14507 }
14508
14509 // Single-side-only populated — the union carries a singleton
14510 // distinct set; the union arm returns `true` for the populated
14511 // kind and `false` for every other kind, DESPITE the empty
14512 // side's `has_only_kind` returning `false`. Pins that the
14513 // union arm reaches the union primitive
14514 // [`Self::has_condition_kind`], not the (pre AND post) AND-
14515 // composition of the per-slice arms. Also pins two-surface
14516 // parity on the single-side arrangement.
14517 for populated in ConditionKind::ALL {
14518 let mut spec = empty_ephemeral();
14519 spec.preconditions.push(cond(populated));
14520 let lowered: ProcessSpec = spec.clone().into();
14521 for probe in ConditionKind::ALL {
14522 let expected = probe == populated;
14523 assert_eq!(
14524 spec.has_only_condition_kind(probe),
14525 expected,
14526 "pre-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
14527 );
14528 assert_eq!(
14529 spec.has_only_condition_kind(probe),
14530 lowered.boundary.has_only_condition_kind(probe),
14531 "two-surface pre-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
14532 );
14533 }
14534
14535 let mut spec = empty_ephemeral();
14536 spec.postconditions.push(cond(populated));
14537 let lowered: ProcessSpec = spec.clone().into();
14538 for probe in ConditionKind::ALL {
14539 let expected = probe == populated;
14540 assert_eq!(
14541 spec.has_only_condition_kind(probe),
14542 expected,
14543 "post-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
14544 );
14545 assert_eq!(
14546 spec.has_only_condition_kind(probe),
14547 lowered.boundary.has_only_condition_kind(probe),
14548 "two-surface post-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
14549 );
14550 }
14551 }
14552
14553 // Saturated ephemeral — both slices carry every ConditionKind,
14554 // every arm returns false on every kind (N distinct kinds, no
14555 // kind is "only").
14556 let mut spec = empty_ephemeral();
14557 for k in ConditionKind::ALL {
14558 spec.preconditions.push(cond(k));
14559 spec.postconditions.push(cond(k));
14560 }
14561 for kind in ConditionKind::ALL {
14562 assert!(
14563 !spec.has_only_precondition_kind(kind),
14564 "saturated ephemeral must return false on has_only_precondition_kind for {kind:?}",
14565 );
14566 assert!(
14567 !spec.has_only_postcondition_kind(kind),
14568 "saturated ephemeral must return false on has_only_postcondition_kind for {kind:?}",
14569 );
14570 assert!(
14571 !spec.has_only_condition_kind(kind),
14572 "saturated ephemeral must return false on has_only_condition_kind for {kind:?}",
14573 );
14574 }
14575 }
14576
14577 /// TRIAD delegation pin — the (precondition, postcondition,
14578 /// condition-union) kind-scoped strict-refinement-on-missing triad
14579 /// on [`EphemeralSpec`] agrees byte-for-byte with the slice-level
14580 /// substrate primitive
14581 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] on every
14582 /// authored arrangement, AND agrees bit-for-bit with the lowered
14583 /// [`ProcessSpec::boundary`]'s triad via the [`From`] bridge.
14584 ///
14585 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
14586 /// single-populated-per-side arrangements + near-saturation-per-
14587 /// side arrangements + single-side-only near-saturation
14588 /// arrangements. The union arm is probed against the DERIVED
14589 /// oracle `spec.missing_condition_kinds() == vec![probe]`, and
14590 /// the per-slice arms delegate to the slice substrate primitive
14591 /// verbatim. Two-surface parity ensures a regression at the
14592 /// `From<EphemeralSpec>` bridge (a re-ordered condition Vec, a
14593 /// dropped ClosedLoopAuth default) surfaces HERE at the union arm.
14594 #[test]
14595 fn lacks_only_condition_kind_triad_delegates_to_slice_lacks_only_kind() {
14596 // Empty ephemeral spec — every kind is missing on N ≥ 2, so
14597 // no kind is "only" missing on any arm.
14598 let spec = empty_ephemeral();
14599 let lowered: ProcessSpec = spec.clone().into();
14600 for kind in ConditionKind::ALL {
14601 assert_eq!(
14602 spec.lacks_only_precondition_kind(kind),
14603 spec.preconditions.lacks_only_kind(kind),
14604 "empty ephemeral lacks_only_precondition_kind must delegate to preconditions.lacks_only_kind for {kind:?}",
14605 );
14606 assert_eq!(
14607 spec.lacks_only_postcondition_kind(kind),
14608 spec.postconditions.lacks_only_kind(kind),
14609 "empty ephemeral lacks_only_postcondition_kind must delegate to postconditions.lacks_only_kind for {kind:?}",
14610 );
14611 assert_eq!(
14612 spec.lacks_only_condition_kind(kind),
14613 lowered.boundary.lacks_only_condition_kind(kind),
14614 "two-surface empty lacks_only_condition_kind parity drift for {kind:?}",
14615 );
14616 }
14617
14618 // Near-saturation per side — build an ephemeral spec whose both
14619 // sides carry every kind except one; sweep every omitted kind
14620 // and probe every ConditionKind on the (pre, post, union) triad.
14621 for omitted in ConditionKind::ALL {
14622 let mut spec = empty_ephemeral();
14623 for k in ConditionKind::ALL {
14624 if k != omitted {
14625 spec.preconditions.push(cond(k));
14626 spec.postconditions.push(cond(k));
14627 }
14628 }
14629 let lowered: ProcessSpec = spec.clone().into();
14630 for probe in ConditionKind::ALL {
14631 let expected = probe == omitted;
14632 assert_eq!(
14633 spec.lacks_only_precondition_kind(probe),
14634 expected,
14635 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_precondition_kind({probe:?})",
14636 );
14637 assert_eq!(
14638 spec.lacks_only_postcondition_kind(probe),
14639 expected,
14640 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_postcondition_kind({probe:?})",
14641 );
14642 assert_eq!(
14643 spec.lacks_only_condition_kind(probe),
14644 expected,
14645 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
14646 );
14647 assert_eq!(
14648 spec.lacks_only_condition_kind(probe),
14649 spec.missing_condition_kinds() == vec![probe],
14650 "near-saturation ephemeral omitted={omitted:?} must agree with missing_condition_kinds() == vec![{probe:?}]",
14651 );
14652
14653 // Two-surface parity via lowered ProcessSpec.
14654 assert_eq!(
14655 spec.lacks_only_precondition_kind(probe),
14656 lowered.boundary.lacks_only_precondition_kind(probe),
14657 "two-surface lacks_only_precondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14658 );
14659 assert_eq!(
14660 spec.lacks_only_postcondition_kind(probe),
14661 lowered.boundary.lacks_only_postcondition_kind(probe),
14662 "two-surface lacks_only_postcondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14663 );
14664 assert_eq!(
14665 spec.lacks_only_condition_kind(probe),
14666 lowered.boundary.lacks_only_condition_kind(probe),
14667 "two-surface lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14668 );
14669 }
14670 }
14671
14672 // Single-side-only near-saturation — the populated side covers
14673 // every kind except one; the OTHER side is empty. The union
14674 // still has missing set `{omitted}` (the populated side's hole
14675 // wins), so the union arm returns `true` for `omitted` and
14676 // `false` for every other kind, DESPITE the empty side's
14677 // `lacks_only_kind` returning `false` on every kind for N ≥ 2.
14678 // Pins that the union arm reaches the union primitive, not the
14679 // (pre AND post) AND-composition.
14680 for omitted in ConditionKind::ALL {
14681 let mut spec = empty_ephemeral();
14682 for k in ConditionKind::ALL {
14683 if k != omitted {
14684 spec.preconditions.push(cond(k));
14685 }
14686 }
14687 let lowered: ProcessSpec = spec.clone().into();
14688 for probe in ConditionKind::ALL {
14689 let expected = probe == omitted;
14690 assert_eq!(
14691 spec.lacks_only_condition_kind(probe),
14692 expected,
14693 "pre-only near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
14694 );
14695 assert_eq!(
14696 spec.lacks_only_condition_kind(probe),
14697 lowered.boundary.lacks_only_condition_kind(probe),
14698 "two-surface pre-only near-saturation lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14699 );
14700 }
14701 }
14702
14703 // Saturated ephemeral — every kind populated, no kind missing,
14704 // every arm returns false on every kind.
14705 let mut spec = empty_ephemeral();
14706 for k in ConditionKind::ALL {
14707 spec.preconditions.push(cond(k));
14708 spec.postconditions.push(cond(k));
14709 }
14710 for kind in ConditionKind::ALL {
14711 assert!(
14712 !spec.lacks_only_precondition_kind(kind),
14713 "saturated ephemeral must return false on lacks_only_precondition_kind for {kind:?}",
14714 );
14715 assert!(
14716 !spec.lacks_only_postcondition_kind(kind),
14717 "saturated ephemeral must return false on lacks_only_postcondition_kind for {kind:?}",
14718 );
14719 assert!(
14720 !spec.lacks_only_condition_kind(kind),
14721 "saturated ephemeral must return false on lacks_only_condition_kind for {kind:?}",
14722 );
14723 }
14724 }
14725
14726 /// SUBSTRATE-DELEGATION pin (EphemeralSpec unique-distinct-kind
14727 /// witnessing triad on the closed-set-inversion axis) — the three
14728 /// `unique_distinct_*_condition_kind` methods on [`EphemeralSpec`]
14729 /// delegate to the slice-level substrate primitive
14730 /// [`crate::boundary::ConditionSliceExt::unique_distinct_kind`]
14731 /// over the two `Vec<Condition>` slots (precondition +
14732 /// postcondition) and compose the union via a two-step-short-
14733 /// circuit walk over [`ConditionKind::ALL`] under
14734 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
14735 /// against
14736 /// [`crate::boundary::Boundary::unique_distinct_condition_kind`]
14737 /// on the point-domain [`ProcessSpec`] surface — the two struct-
14738 /// level singleton-coverage witnesses compose against the SAME
14739 /// slice-level substrate primitive so a regression at the per-
14740 /// slice two-step short-circuit witnessing walk fails at that
14741 /// primitive's tests rather than as silent drift at either sugar-
14742 /// surface arm.
14743 #[test]
14744 fn unique_distinct_condition_kind_triad_delegates_to_slice_unique_distinct_kind() {
14745 // Empty ephemeral spec — every arm returns None.
14746 let spec = empty_ephemeral();
14747 assert_eq!(
14748 spec.unique_distinct_precondition_kind(),
14749 None,
14750 "empty ephemeral must return None on unique_distinct_precondition_kind",
14751 );
14752 assert_eq!(
14753 spec.unique_distinct_postcondition_kind(),
14754 None,
14755 "empty ephemeral must return None on unique_distinct_postcondition_kind",
14756 );
14757 assert_eq!(
14758 spec.unique_distinct_condition_kind(),
14759 None,
14760 "empty ephemeral must return None on unique_distinct_condition_kind",
14761 );
14762
14763 // Single-populated per side — sweep ALL × ALL.
14764 for pre_kind in ConditionKind::ALL {
14765 for post_kind in ConditionKind::ALL {
14766 let mut spec = empty_ephemeral();
14767 spec.preconditions.push(cond(pre_kind));
14768 spec.postconditions.push(cond(post_kind));
14769
14770 assert_eq!(
14771 spec.unique_distinct_precondition_kind(),
14772 spec.preconditions.unique_distinct_kind(),
14773 "EphemeralSpec::unique_distinct_precondition_kind must delegate verbatim to \
14774 preconditions.unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
14775 );
14776 assert_eq!(
14777 spec.unique_distinct_precondition_kind(),
14778 Some(pre_kind),
14779 "EphemeralSpec::unique_distinct_precondition_kind must equal Some(pre_kind) on \
14780 single-populated preconditions for pre={pre_kind:?} post={post_kind:?}",
14781 );
14782 assert_eq!(
14783 spec.unique_distinct_postcondition_kind(),
14784 spec.postconditions.unique_distinct_kind(),
14785 "EphemeralSpec::unique_distinct_postcondition_kind must delegate verbatim to \
14786 postconditions.unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
14787 );
14788 assert_eq!(
14789 spec.unique_distinct_postcondition_kind(),
14790 Some(post_kind),
14791 "EphemeralSpec::unique_distinct_postcondition_kind must equal Some(post_kind) on \
14792 single-populated postconditions for pre={pre_kind:?} post={post_kind:?}",
14793 );
14794
14795 let covered: Vec<ConditionKind> = ConditionKind::ALL
14796 .into_iter()
14797 .filter(|k| pre_kind == *k || post_kind == *k)
14798 .collect();
14799 let expected_union = if covered.len() == 1 {
14800 Some(covered[0])
14801 } else {
14802 None
14803 };
14804 assert_eq!(
14805 spec.unique_distinct_condition_kind(),
14806 expected_union,
14807 "EphemeralSpec::unique_distinct_condition_kind must equal Some(k) iff the \
14808 ALL-entries covered by either half-slice sum to exactly one for \
14809 pre={pre_kind:?} post={post_kind:?}",
14810 );
14811
14812 // Boolean-witness composition laws.
14813 assert_eq!(
14814 spec.unique_distinct_condition_kind().is_some(),
14815 spec.has_unique_distinct_condition_kind(),
14816 "unique_distinct_condition_kind().is_some() must equal \
14817 has_unique_distinct_condition_kind() for pre={pre_kind:?} post={post_kind:?}",
14818 );
14819
14820 // Two-surface parity — lowered ProcessSpec's Boundary
14821 // must agree bit-for-bit with the ephemeral sugar
14822 // triad on every arm.
14823 let lowered: ProcessSpec = spec.clone().into();
14824 assert_eq!(
14825 spec.unique_distinct_precondition_kind(),
14826 lowered.boundary.unique_distinct_precondition_kind(),
14827 "two-surface unique_distinct_precondition_kind parity drift for \
14828 pre={pre_kind:?} post={post_kind:?}",
14829 );
14830 assert_eq!(
14831 spec.unique_distinct_postcondition_kind(),
14832 lowered.boundary.unique_distinct_postcondition_kind(),
14833 "two-surface unique_distinct_postcondition_kind parity drift for \
14834 pre={pre_kind:?} post={post_kind:?}",
14835 );
14836 assert_eq!(
14837 spec.unique_distinct_condition_kind(),
14838 lowered.boundary.unique_distinct_condition_kind(),
14839 "two-surface unique_distinct_condition_kind parity drift for \
14840 pre={pre_kind:?} post={post_kind:?}",
14841 );
14842 }
14843 }
14844
14845 // Saturated ephemeral — every arm returns None on N ≥ 2.
14846 if ConditionKind::ALL.len() >= 2 {
14847 let mut spec = empty_ephemeral();
14848 for k in ConditionKind::ALL {
14849 spec.preconditions.push(cond(k));
14850 spec.postconditions.push(cond(k));
14851 }
14852 assert_eq!(
14853 spec.unique_distinct_precondition_kind(),
14854 None,
14855 "saturated ephemeral must return None on unique_distinct_precondition_kind",
14856 );
14857 assert_eq!(
14858 spec.unique_distinct_postcondition_kind(),
14859 None,
14860 "saturated ephemeral must return None on unique_distinct_postcondition_kind",
14861 );
14862 assert_eq!(
14863 spec.unique_distinct_condition_kind(),
14864 None,
14865 "saturated ephemeral must return None on unique_distinct_condition_kind",
14866 );
14867 }
14868 }
14869
14870 /// SUBSTRATE-DELEGATION pin (EphemeralSpec unique-missing-kind
14871 /// witnessing triad on the closed-set-complement axis) — the three
14872 /// `unique_missing_*_condition_kind` methods on [`EphemeralSpec`]
14873 /// delegate to the slice-level substrate primitive
14874 /// [`crate::boundary::ConditionSliceExt::unique_missing_kind`]
14875 /// over the two `Vec<Condition>` slots (precondition +
14876 /// postcondition) and compose the union via a two-step-short-
14877 /// circuit walk over [`ConditionKind::ALL`] under a NEGATED
14878 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
14879 /// against
14880 /// [`crate::boundary::Boundary::unique_missing_condition_kind`]
14881 /// on the point-domain [`ProcessSpec`] surface.
14882 #[test]
14883 fn unique_missing_condition_kind_triad_delegates_to_slice_unique_missing_kind() {
14884 // Empty ephemeral spec — every arm returns None on N ≥ 2
14885 // (every kind is missing, not exactly one).
14886 let spec = empty_ephemeral();
14887 if ConditionKind::ALL.len() >= 2 {
14888 assert_eq!(
14889 spec.unique_missing_precondition_kind(),
14890 None,
14891 "empty ephemeral must return None on unique_missing_precondition_kind on N ≥ 2",
14892 );
14893 assert_eq!(
14894 spec.unique_missing_postcondition_kind(),
14895 None,
14896 "empty ephemeral must return None on unique_missing_postcondition_kind on N ≥ 2",
14897 );
14898 assert_eq!(
14899 spec.unique_missing_condition_kind(),
14900 None,
14901 "empty ephemeral must return None on unique_missing_condition_kind on N ≥ 2",
14902 );
14903 }
14904
14905 // Single-populated per side — sweep ALL × ALL.
14906 for pre_kind in ConditionKind::ALL {
14907 for post_kind in ConditionKind::ALL {
14908 let mut spec = empty_ephemeral();
14909 spec.preconditions.push(cond(pre_kind));
14910 spec.postconditions.push(cond(post_kind));
14911
14912 assert_eq!(
14913 spec.unique_missing_precondition_kind(),
14914 spec.preconditions.unique_missing_kind(),
14915 "EphemeralSpec::unique_missing_precondition_kind must delegate verbatim to \
14916 preconditions.unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14917 );
14918 assert_eq!(
14919 spec.unique_missing_postcondition_kind(),
14920 spec.postconditions.unique_missing_kind(),
14921 "EphemeralSpec::unique_missing_postcondition_kind must delegate verbatim to \
14922 postconditions.unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14923 );
14924
14925 let missing: Vec<ConditionKind> = ConditionKind::ALL
14926 .into_iter()
14927 .filter(|k| pre_kind != *k && post_kind != *k)
14928 .collect();
14929 let expected_union = if missing.len() == 1 {
14930 Some(missing[0])
14931 } else {
14932 None
14933 };
14934 assert_eq!(
14935 spec.unique_missing_condition_kind(),
14936 expected_union,
14937 "EphemeralSpec::unique_missing_condition_kind must equal Some(k) iff the \
14938 ALL-entries NOT covered by either half-slice sum to exactly one for \
14939 pre={pre_kind:?} post={post_kind:?}",
14940 );
14941
14942 // Boolean-witness composition laws.
14943 assert_eq!(
14944 spec.unique_missing_condition_kind().is_some(),
14945 spec.has_unique_missing_condition_kind(),
14946 "unique_missing_condition_kind().is_some() must equal \
14947 has_unique_missing_condition_kind() for pre={pre_kind:?} post={post_kind:?}",
14948 );
14949
14950 // Two-surface parity.
14951 let lowered: ProcessSpec = spec.clone().into();
14952 assert_eq!(
14953 spec.unique_missing_precondition_kind(),
14954 lowered.boundary.unique_missing_precondition_kind(),
14955 "two-surface unique_missing_precondition_kind parity drift for \
14956 pre={pre_kind:?} post={post_kind:?}",
14957 );
14958 assert_eq!(
14959 spec.unique_missing_postcondition_kind(),
14960 lowered.boundary.unique_missing_postcondition_kind(),
14961 "two-surface unique_missing_postcondition_kind parity drift for \
14962 pre={pre_kind:?} post={post_kind:?}",
14963 );
14964 assert_eq!(
14965 spec.unique_missing_condition_kind(),
14966 lowered.boundary.unique_missing_condition_kind(),
14967 "two-surface unique_missing_condition_kind parity drift for \
14968 pre={pre_kind:?} post={post_kind:?}",
14969 );
14970 }
14971 }
14972
14973 // Saturated ephemeral — every arm returns None (zero missing).
14974 let mut spec = empty_ephemeral();
14975 for k in ConditionKind::ALL {
14976 spec.preconditions.push(cond(k));
14977 spec.postconditions.push(cond(k));
14978 }
14979 assert_eq!(
14980 spec.unique_missing_precondition_kind(),
14981 None,
14982 "saturated ephemeral must return None on unique_missing_precondition_kind",
14983 );
14984 assert_eq!(
14985 spec.unique_missing_postcondition_kind(),
14986 None,
14987 "saturated ephemeral must return None on unique_missing_postcondition_kind",
14988 );
14989 assert_eq!(
14990 spec.unique_missing_condition_kind(),
14991 None,
14992 "saturated ephemeral must return None on unique_missing_condition_kind",
14993 );
14994
14995 // Near-saturation arm: exactly one ALL entry missing on each
14996 // side (populate every kind except `hole`).
14997 for hole in ConditionKind::ALL {
14998 let mut spec = empty_ephemeral();
14999 for k in ConditionKind::ALL {
15000 if k != hole {
15001 spec.preconditions.push(cond(k));
15002 spec.postconditions.push(cond(k));
15003 }
15004 }
15005 assert_eq!(
15006 spec.unique_missing_precondition_kind(),
15007 Some(hole),
15008 "near-saturation ephemeral must return Some(hole={hole:?}) on unique_missing_precondition_kind",
15009 );
15010 assert_eq!(
15011 spec.unique_missing_postcondition_kind(),
15012 Some(hole),
15013 "near-saturation ephemeral must return Some(hole={hole:?}) on unique_missing_postcondition_kind",
15014 );
15015 assert_eq!(
15016 spec.unique_missing_condition_kind(),
15017 Some(hole),
15018 "near-saturation ephemeral must return Some(hole={hole:?}) on unique_missing_condition_kind",
15019 );
15020 }
15021 }
15022
15023 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind cardinality
15024 /// "≥ 2" many-arm triad on the count axis) — the three
15025 /// `has_multiple_of_*_condition_kind` methods on
15026 /// [`EphemeralSpec`] delegate to the slice-level substrate
15027 /// primitive
15028 /// [`crate::boundary::ConditionSliceExt::has_multiple_of_kind`]
15029 /// over the two `Vec<Condition>` slots and compose the union via
15030 /// a two-step-short-circuit walk over the chained per-kind
15031 /// iterator [`EphemeralSpec::iter_condition_kind`]. Sweeps: (a)
15032 /// the empty spec (every arm returns `false` on every kind); (b)
15033 /// a single-populated-per-side arrangement where each per-slice
15034 /// arm returns `false` but the union goes true iff pre and post
15035 /// carry the SAME kind; (c) the saturated-doubled spec (every
15036 /// arm returns `true` on every kind). Also verifies TWO-SURFACE
15037 /// PARITY — the ephemeral-side arm agrees with the lowered
15038 /// [`crate::boundary::Boundary`] arm through the same slice-
15039 /// level substrate primitive. A regression at either surface
15040 /// fails HERE rather than as silent drift between the two.
15041 #[test]
15042 fn has_multiple_of_condition_kind_triad_delegates_to_slice_has_multiple_of_kind() {
15043 // Empty ephemeral — every arm returns false on every kind.
15044 let spec = empty_ephemeral();
15045 for kind in ConditionKind::ALL {
15046 assert!(
15047 !spec.has_multiple_of_precondition_kind(kind),
15048 "empty ephemeral must return false on has_multiple_of_precondition_kind({kind:?})",
15049 );
15050 assert!(
15051 !spec.has_multiple_of_postcondition_kind(kind),
15052 "empty ephemeral must return false on has_multiple_of_postcondition_kind({kind:?})",
15053 );
15054 assert!(
15055 !spec.has_multiple_of_condition_kind(kind),
15056 "empty ephemeral must return false on has_multiple_of_condition_kind({kind:?})",
15057 );
15058 }
15059
15060 // Single-populated-per-side sweep — per-slice arms stay
15061 // false; union goes true iff pre and post carry the SAME
15062 // kind. Also verifies two-surface parity with Boundary.
15063 for pre_kind in ConditionKind::ALL {
15064 for post_kind in ConditionKind::ALL {
15065 let mut spec = empty_ephemeral();
15066 spec.preconditions.push(cond(pre_kind));
15067 spec.postconditions.push(cond(post_kind));
15068 let lowered: ProcessSpec = spec.clone().into();
15069
15070 for query in ConditionKind::ALL {
15071 assert_eq!(
15072 spec.has_multiple_of_precondition_kind(query),
15073 spec.preconditions.has_multiple_of_kind(query),
15074 "EphemeralSpec::has_multiple_of_precondition_kind must delegate \
15075 verbatim to preconditions.has_multiple_of_kind for \
15076 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15077 );
15078 assert_eq!(
15079 spec.has_multiple_of_postcondition_kind(query),
15080 spec.postconditions.has_multiple_of_kind(query),
15081 "EphemeralSpec::has_multiple_of_postcondition_kind must delegate \
15082 verbatim to postconditions.has_multiple_of_kind for \
15083 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15084 );
15085
15086 let expected_union = pre_kind == query && post_kind == query;
15087 assert_eq!(
15088 spec.has_multiple_of_condition_kind(query),
15089 expected_union,
15090 "EphemeralSpec::has_multiple_of_condition_kind({query:?}) must equal \
15091 (pre == query && post == query) for pre={pre_kind:?} post={post_kind:?}",
15092 );
15093
15094 // Two-surface parity with lowered Boundary.
15095 assert_eq!(
15096 spec.has_multiple_of_condition_kind(query),
15097 lowered.boundary.has_multiple_of_condition_kind(query),
15098 "two-surface has_multiple_of_condition_kind({query:?}) parity drift \
15099 for pre={pre_kind:?} post={post_kind:?}",
15100 );
15101 assert_eq!(
15102 spec.has_multiple_of_precondition_kind(query),
15103 lowered.boundary.has_multiple_of_precondition_kind(query),
15104 "two-surface has_multiple_of_precondition_kind({query:?}) parity drift",
15105 );
15106 assert_eq!(
15107 spec.has_multiple_of_postcondition_kind(query),
15108 lowered.boundary.has_multiple_of_postcondition_kind(query),
15109 "two-surface has_multiple_of_postcondition_kind({query:?}) parity drift",
15110 );
15111 }
15112 }
15113 }
15114
15115 // Saturated-doubled spec — every arm returns true on every
15116 // kind (every slice carries every kind twice).
15117 let mut spec = empty_ephemeral();
15118 for k in ConditionKind::ALL {
15119 spec.preconditions.push(cond(k));
15120 spec.preconditions.push(cond(k));
15121 spec.postconditions.push(cond(k));
15122 spec.postconditions.push(cond(k));
15123 }
15124 for kind in ConditionKind::ALL {
15125 assert!(
15126 spec.has_multiple_of_precondition_kind(kind),
15127 "saturated-doubled ephemeral must return true on has_multiple_of_precondition_kind({kind:?})",
15128 );
15129 assert!(
15130 spec.has_multiple_of_postcondition_kind(kind),
15131 "saturated-doubled ephemeral must return true on has_multiple_of_postcondition_kind({kind:?})",
15132 );
15133 assert!(
15134 spec.has_multiple_of_condition_kind(kind),
15135 "saturated-doubled ephemeral must return true on has_multiple_of_condition_kind({kind:?})",
15136 );
15137 }
15138 }
15139
15140 /// Every arm of the (precondition, postcondition, condition-union)
15141 /// per-kind cardinality "= 1" mid-endpoint triad on
15142 /// [`EphemeralSpec`] delegates verbatim to the slice-level
15143 /// substrate primitive
15144 /// [`crate::boundary::ConditionSliceExt::has_unique_of_kind`].
15145 /// Sweeps three arrangements: (a) an empty ephemeral (every arm
15146 /// returns `false` on every kind); (b) a single-populated-per-
15147 /// side sweep where per-slice arms fire iff their side's kind
15148 /// equals `query`, and the union arm fires iff EXACTLY ONE of
15149 /// `{pre, post}` equals `query` (chain sums to 1 on disjoint,
15150 /// 2 on shared); (c) the saturated-singleton spec (every kind
15151 /// appears exactly once on every slice — per-slice arms return
15152 /// `true` on every kind, union returns `false` on every kind
15153 /// as `= 2` chain matches). Also verifies TWO-SURFACE PARITY —
15154 /// the ephemeral-side arm agrees with the lowered
15155 /// [`crate::boundary::Boundary`] arm through the same slice-
15156 /// level substrate primitive.
15157 #[test]
15158 fn has_unique_of_condition_kind_triad_delegates_to_slice_has_unique_of_kind() {
15159 // Empty ephemeral — every arm returns false on every kind.
15160 let spec = empty_ephemeral();
15161 for kind in ConditionKind::ALL {
15162 assert!(
15163 !spec.has_unique_of_precondition_kind(kind),
15164 "empty ephemeral must return false on has_unique_of_precondition_kind({kind:?})",
15165 );
15166 assert!(
15167 !spec.has_unique_of_postcondition_kind(kind),
15168 "empty ephemeral must return false on has_unique_of_postcondition_kind({kind:?})",
15169 );
15170 assert!(
15171 !spec.has_unique_of_condition_kind(kind),
15172 "empty ephemeral must return false on has_unique_of_condition_kind({kind:?})",
15173 );
15174 }
15175
15176 // Single-populated-per-side sweep — per-slice arm fires iff
15177 // its side's kind equals `query`; union arm fires iff
15178 // EXACTLY ONE of {pre, post} equals `query`. Also verifies
15179 // two-surface parity with Boundary.
15180 for pre_kind in ConditionKind::ALL {
15181 for post_kind in ConditionKind::ALL {
15182 let mut spec = empty_ephemeral();
15183 spec.preconditions.push(cond(pre_kind));
15184 spec.postconditions.push(cond(post_kind));
15185 let lowered: ProcessSpec = spec.clone().into();
15186
15187 for query in ConditionKind::ALL {
15188 assert_eq!(
15189 spec.has_unique_of_precondition_kind(query),
15190 spec.preconditions.has_unique_of_kind(query),
15191 "EphemeralSpec::has_unique_of_precondition_kind must delegate \
15192 verbatim to preconditions.has_unique_of_kind for \
15193 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15194 );
15195 assert_eq!(
15196 spec.has_unique_of_postcondition_kind(query),
15197 spec.postconditions.has_unique_of_kind(query),
15198 "EphemeralSpec::has_unique_of_postcondition_kind must delegate \
15199 verbatim to postconditions.has_unique_of_kind for \
15200 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15201 );
15202
15203 let expected_union = (pre_kind == query) ^ (post_kind == query);
15204 assert_eq!(
15205 spec.has_unique_of_condition_kind(query),
15206 expected_union,
15207 "EphemeralSpec::has_unique_of_condition_kind({query:?}) must equal \
15208 ((pre == query) XOR (post == query)) for \
15209 pre={pre_kind:?} post={post_kind:?}",
15210 );
15211
15212 // Two-surface parity with lowered Boundary.
15213 assert_eq!(
15214 spec.has_unique_of_condition_kind(query),
15215 lowered.boundary.has_unique_of_condition_kind(query),
15216 "two-surface has_unique_of_condition_kind({query:?}) parity drift \
15217 for pre={pre_kind:?} post={post_kind:?}",
15218 );
15219 assert_eq!(
15220 spec.has_unique_of_precondition_kind(query),
15221 lowered.boundary.has_unique_of_precondition_kind(query),
15222 "two-surface has_unique_of_precondition_kind({query:?}) parity drift",
15223 );
15224 assert_eq!(
15225 spec.has_unique_of_postcondition_kind(query),
15226 lowered.boundary.has_unique_of_postcondition_kind(query),
15227 "two-surface has_unique_of_postcondition_kind({query:?}) parity drift",
15228 );
15229 }
15230 }
15231 }
15232
15233 // Saturated-singleton spec — every kind appears exactly once
15234 // on every slice; per-slice arms return true on every kind,
15235 // union returns false on every kind (= 2 chain matches).
15236 let mut spec = empty_ephemeral();
15237 for k in ConditionKind::ALL {
15238 spec.preconditions.push(cond(k));
15239 spec.postconditions.push(cond(k));
15240 }
15241 for kind in ConditionKind::ALL {
15242 assert!(
15243 spec.has_unique_of_precondition_kind(kind),
15244 "saturated-singleton ephemeral must return true on has_unique_of_precondition_kind({kind:?})",
15245 );
15246 assert!(
15247 spec.has_unique_of_postcondition_kind(kind),
15248 "saturated-singleton ephemeral must return true on has_unique_of_postcondition_kind({kind:?})",
15249 );
15250 assert!(
15251 !spec.has_unique_of_condition_kind(kind),
15252 "saturated-singleton ephemeral must return false on union has_unique_of_condition_kind({kind:?}) (2 chain matches)",
15253 );
15254 }
15255 }
15256
15257 // ── EphemeralSpec::has_at_most_one_of_(pre|post|)condition_kind ─
15258 //
15259 // Two-surface parity contract with
15260 // `Boundary::has_at_most_one_of_condition_kind` on the "≤ 1"
15261 // per-kind negation arm. Ephemeral composes against the SAME
15262 // slice-level substrate primitive
15263 // `ConditionSliceExt::has_at_most_one_of_kind` via delegation on
15264 // each side and via the definitional negation of
15265 // `has_multiple_of_condition_kind` on the union chain. Regression
15266 // at either the per-slice negation walk or the ephemeral→boundary
15267 // lowering fails here.
15268
15269 /// EphemeralSpec triad delegation + two-surface parity pin —
15270 /// sweeps every kind on every reachable arrangement of a single
15271 /// condition-per-side spec, asserts each per-slice arm delegates
15272 /// verbatim to the slice-level primitive, and asserts the union
15273 /// arm agrees with the lowered [`ProcessSpec`]'s
15274 /// [`Boundary::has_at_most_one_of_condition_kind`] on every
15275 /// arm. Also pins the trichotomy-union arm equivalence
15276 /// `has_at_most_one_of_condition_kind == lacks_condition_kind ||
15277 /// has_unique_of_condition_kind` and the tetrachotomy partition
15278 /// (`{≤ 1, ≥ 2}` exactly one arm on every arrangement).
15279 #[test]
15280 fn has_at_most_one_of_condition_kind_triad_delegates_to_slice_has_at_most_one_of_kind() {
15281 // Empty ephemeral — every arm returns true on every kind
15282 // (0 matches, `≤ 1`).
15283 let spec = empty_ephemeral();
15284 for kind in ConditionKind::ALL {
15285 assert!(
15286 spec.has_at_most_one_of_precondition_kind(kind),
15287 "empty ephemeral must return true on has_at_most_one_of_precondition_kind({kind:?})",
15288 );
15289 assert!(
15290 spec.has_at_most_one_of_postcondition_kind(kind),
15291 "empty ephemeral must return true on has_at_most_one_of_postcondition_kind({kind:?})",
15292 );
15293 assert!(
15294 spec.has_at_most_one_of_condition_kind(kind),
15295 "empty ephemeral must return true on has_at_most_one_of_condition_kind({kind:?})",
15296 );
15297 }
15298
15299 // Single-populated-per-side sweep — per-slice arms always
15300 // fire; union arm fires iff at most one of `{pre, post}`
15301 // equals `query` (`!(pre_hit && post_hit)`). Also verifies
15302 // two-surface parity with Boundary on every arm.
15303 for pre_kind in ConditionKind::ALL {
15304 for post_kind in ConditionKind::ALL {
15305 let mut spec = empty_ephemeral();
15306 spec.preconditions.push(cond(pre_kind));
15307 spec.postconditions.push(cond(post_kind));
15308 let lowered: ProcessSpec = spec.clone().into();
15309
15310 for query in ConditionKind::ALL {
15311 assert_eq!(
15312 spec.has_at_most_one_of_precondition_kind(query),
15313 spec.preconditions.has_at_most_one_of_kind(query),
15314 "EphemeralSpec::has_at_most_one_of_precondition_kind must delegate \
15315 verbatim to preconditions.has_at_most_one_of_kind for \
15316 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15317 );
15318 assert_eq!(
15319 spec.has_at_most_one_of_postcondition_kind(query),
15320 spec.postconditions.has_at_most_one_of_kind(query),
15321 "EphemeralSpec::has_at_most_one_of_postcondition_kind must delegate \
15322 verbatim to postconditions.has_at_most_one_of_kind for \
15323 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15324 );
15325
15326 let pre_hit = pre_kind == query;
15327 let post_hit = post_kind == query;
15328 let expected_union = !(pre_hit && post_hit);
15329 assert_eq!(
15330 spec.has_at_most_one_of_condition_kind(query),
15331 expected_union,
15332 "EphemeralSpec::has_at_most_one_of_condition_kind({query:?}) must equal \
15333 !(pre_hit && post_hit) for pre={pre_kind:?} post={post_kind:?}",
15334 );
15335
15336 // Definitional negation of the many-arm peer.
15337 assert_eq!(
15338 spec.has_at_most_one_of_condition_kind(query),
15339 !spec.has_multiple_of_condition_kind(query),
15340 "EphemeralSpec::has_at_most_one_of_condition_kind({query:?}) drifted \
15341 from !has_multiple_of_condition_kind for pre={pre_kind:?} \
15342 post={post_kind:?}",
15343 );
15344
15345 // Trichotomy-union arm: {= 0} ∪ {= 1} == {≤ 1}.
15346 assert_eq!(
15347 spec.has_at_most_one_of_condition_kind(query),
15348 spec.lacks_condition_kind(query)
15349 || spec.has_unique_of_condition_kind(query),
15350 "EphemeralSpec::has_at_most_one_of_condition_kind({query:?}) drifted \
15351 from (lacks || has_unique) trichotomy-union for pre={pre_kind:?} \
15352 post={post_kind:?}",
15353 );
15354
15355 // Two-surface parity with lowered Boundary.
15356 assert_eq!(
15357 spec.has_at_most_one_of_condition_kind(query),
15358 lowered.boundary.has_at_most_one_of_condition_kind(query),
15359 "two-surface has_at_most_one_of_condition_kind({query:?}) parity drift \
15360 for pre={pre_kind:?} post={post_kind:?}",
15361 );
15362 assert_eq!(
15363 spec.has_at_most_one_of_precondition_kind(query),
15364 lowered.boundary.has_at_most_one_of_precondition_kind(query),
15365 "two-surface has_at_most_one_of_precondition_kind({query:?}) parity \
15366 drift for pre={pre_kind:?} post={post_kind:?}",
15367 );
15368 assert_eq!(
15369 spec.has_at_most_one_of_postcondition_kind(query),
15370 lowered
15371 .boundary
15372 .has_at_most_one_of_postcondition_kind(query),
15373 "two-surface has_at_most_one_of_postcondition_kind({query:?}) parity \
15374 drift for pre={pre_kind:?} post={post_kind:?}",
15375 );
15376
15377 // {≤ 1, ≥ 2} Boolean-negation partition at the
15378 // union level — EXACTLY ONE arm fires.
15379 let at_most_one = spec.has_at_most_one_of_condition_kind(query);
15380 let multiple = spec.has_multiple_of_condition_kind(query);
15381 assert_ne!(
15382 at_most_one, multiple,
15383 "union {{≤ 1, ≥ 2}} Boolean-negation partition for query={query:?} \
15384 (pre={pre_kind:?} post={post_kind:?}) must fire EXACTLY one arm",
15385 );
15386 }
15387 }
15388 }
15389
15390 // Saturated-singleton spec — every kind appears exactly once
15391 // on every slice. Per-slice arms return true on every kind;
15392 // union returns false on every kind (2 chain matches, not ≤ 1).
15393 let mut spec = empty_ephemeral();
15394 for k in ConditionKind::ALL {
15395 spec.preconditions.push(cond(k));
15396 spec.postconditions.push(cond(k));
15397 }
15398 for kind in ConditionKind::ALL {
15399 assert!(
15400 spec.has_at_most_one_of_precondition_kind(kind),
15401 "saturated-singleton ephemeral must return true on has_at_most_one_of_precondition_kind({kind:?})",
15402 );
15403 assert!(
15404 spec.has_at_most_one_of_postcondition_kind(kind),
15405 "saturated-singleton ephemeral must return true on has_at_most_one_of_postcondition_kind({kind:?})",
15406 );
15407 assert!(
15408 !spec.has_at_most_one_of_condition_kind(kind),
15409 "saturated-singleton ephemeral must return false on union has_at_most_one_of_condition_kind({kind:?}) (2 chain matches)",
15410 );
15411 }
15412 }
15413
15414 // ── EphemeralSpec::unique_of_(pre|post|)condition_kind triad ────
15415 //
15416 // Two-surface parity contract with
15417 // `Boundary::unique_of_condition_kind` on the per-kind `= 1`
15418 // `Option<&Condition>` witnessing arm. Both surfaces compose
15419 // against the SAME slice-level substrate primitive
15420 // `ConditionSliceExt::unique_of_kind` via delegation on each side
15421 // and via a two-step short-circuit walk over
15422 // `iter_condition_kind` on the union chain.
15423
15424 /// Ephemeral triad delegation + two-surface parity pin — sweeps
15425 /// every kind on every reachable `(pre_kind, post_kind, query)`
15426 /// arrangement of a single-condition-per-side spec, asserts each
15427 /// per-slice arm delegates verbatim to the slice-level primitive,
15428 /// asserts the union arm equals the chained two-step short-
15429 /// circuit walk, and asserts the ephemeral-side arm agrees with
15430 /// the lowered [`Boundary`] arm through the same slice-level
15431 /// substrate primitive.
15432 #[test]
15433 fn unique_of_condition_kind_triad_delegates_to_slice_unique_of_kind() {
15434 use crate::boundary::ConditionSliceExt as _;
15435
15436 // Empty ephemeral — every arm returns None on every kind.
15437 let spec = empty_ephemeral();
15438 for kind in ConditionKind::ALL {
15439 assert!(
15440 spec.unique_of_precondition_kind(kind).is_none(),
15441 "empty ephemeral must return None on unique_of_precondition_kind({kind:?})",
15442 );
15443 assert!(
15444 spec.unique_of_postcondition_kind(kind).is_none(),
15445 "empty ephemeral must return None on unique_of_postcondition_kind({kind:?})",
15446 );
15447 assert!(
15448 spec.unique_of_condition_kind(kind).is_none(),
15449 "empty ephemeral must return None on unique_of_condition_kind({kind:?})",
15450 );
15451 }
15452
15453 // Single-populated-per-side sweep with two-surface parity.
15454 for pre_kind in ConditionKind::ALL {
15455 for post_kind in ConditionKind::ALL {
15456 let mut spec = empty_ephemeral();
15457 spec.preconditions.push(cond(pre_kind));
15458 spec.postconditions.push(cond(post_kind));
15459
15460 let lowered: ProcessSpec = spec.clone().into();
15461 let boundary = &lowered.boundary;
15462
15463 for query in ConditionKind::ALL {
15464 // Per-side delegation pins.
15465 assert_eq!(
15466 spec.unique_of_precondition_kind(query)
15467 .map(|c| c as *const Condition),
15468 spec.preconditions
15469 .unique_of_kind(query)
15470 .map(|c| c as *const Condition),
15471 "EphemeralSpec::unique_of_precondition_kind must delegate verbatim to \
15472 preconditions.unique_of_kind for pre={pre_kind:?} post={post_kind:?} \
15473 query={query:?}",
15474 );
15475 assert_eq!(
15476 spec.unique_of_postcondition_kind(query)
15477 .map(|c| c as *const Condition),
15478 spec.postconditions
15479 .unique_of_kind(query)
15480 .map(|c| c as *const Condition),
15481 "EphemeralSpec::unique_of_postcondition_kind must delegate verbatim to \
15482 postconditions.unique_of_kind for pre={pre_kind:?} post={post_kind:?} \
15483 query={query:?}",
15484 );
15485
15486 // Boolean-projection composition-law pin.
15487 assert_eq!(
15488 spec.unique_of_condition_kind(query).is_some(),
15489 spec.has_unique_of_condition_kind(query),
15490 "EphemeralSpec::unique_of_condition_kind({query:?}).is_some() drifted \
15491 from has_unique_of_condition_kind for pre={pre_kind:?} \
15492 post={post_kind:?}",
15493 );
15494 assert_eq!(
15495 spec.unique_of_condition_kind(query).map(|c| c.kind),
15496 if spec.has_unique_of_condition_kind(query) {
15497 Some(query)
15498 } else {
15499 None
15500 },
15501 "EphemeralSpec::unique_of_condition_kind({query:?}).map(kind) must yield \
15502 Some({query:?}) iff has_unique_of_condition_kind for pre={pre_kind:?} \
15503 post={post_kind:?}",
15504 );
15505
15506 // Union arm shape — XOR of side-hits.
15507 let pre_hit = pre_kind == query;
15508 let post_hit = post_kind == query;
15509 assert_eq!(
15510 spec.unique_of_condition_kind(query).is_some(),
15511 pre_hit ^ post_hit,
15512 "EphemeralSpec::unique_of_condition_kind({query:?}).is_some() must equal \
15513 (pre_hit XOR post_hit) for pre={pre_kind:?} post={post_kind:?}",
15514 );
15515
15516 // Two-surface parity — the lowered Boundary's
15517 // triad yields the SAME Option<kind> shape on
15518 // every arm. Pointer identities differ (the
15519 // lowered Boundary carries cloned Conditions),
15520 // so parity holds at the kind projection.
15521 assert_eq!(
15522 spec.unique_of_precondition_kind(query).map(|c| c.kind),
15523 boundary.unique_of_precondition_kind(query).map(|c| c.kind),
15524 "ephemeral unique_of_precondition_kind({query:?}) kind drifted from \
15525 lowered Boundary for pre={pre_kind:?} post={post_kind:?}",
15526 );
15527 assert_eq!(
15528 spec.unique_of_postcondition_kind(query).map(|c| c.kind),
15529 boundary.unique_of_postcondition_kind(query).map(|c| c.kind),
15530 "ephemeral unique_of_postcondition_kind({query:?}) kind drifted from \
15531 lowered Boundary for pre={pre_kind:?} post={post_kind:?}",
15532 );
15533 assert_eq!(
15534 spec.unique_of_condition_kind(query).map(|c| c.kind),
15535 boundary.unique_of_condition_kind(query).map(|c| c.kind),
15536 "ephemeral unique_of_condition_kind({query:?}) kind drifted from \
15537 lowered Boundary for pre={pre_kind:?} post={post_kind:?}",
15538 );
15539 }
15540 }
15541 }
15542
15543 // Doubled-post sweep — union collapses to None on the
15544 // doubled kind (`≥ 2` chain matches).
15545 for doubled in ConditionKind::ALL {
15546 let mut spec = empty_ephemeral();
15547 spec.postconditions.push(cond(doubled));
15548 spec.postconditions.push(cond(doubled));
15549 assert!(
15550 spec.unique_of_postcondition_kind(doubled).is_none(),
15551 "doubled postconditions must collapse unique_of_postcondition_kind({doubled:?}) \
15552 to None",
15553 );
15554 assert!(
15555 spec.unique_of_condition_kind(doubled).is_none(),
15556 "doubled postconditions must collapse union unique_of_condition_kind({doubled:?}) \
15557 to None",
15558 );
15559 }
15560 }
15561}