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 /// `true` iff `preconditions ∪ postconditions` COVERS AT LEAST
1708 /// TWO [`ConditionKind::ALL`] variants — the union arm of the
1709 /// (precondition, postcondition, condition-union) cardinality-
1710 /// many-arm triad on [`EphemeralSpec`] closing the "≥ 2 kinds
1711 /// covered" arm on the union of the two condition slots. The
1712 /// Boolean cardinality many-arm fast-path peer of
1713 /// [`Self::has_unique_distinct_condition_kind`] (=1 arm) and
1714 /// [`Self::has_any_distinct_condition_kind`] (≥1 halfspace):
1715 /// closes the {0, 1, ≥2} trichotomy on the distinct axis at the
1716 /// ephemeral union struct layer.
1717 ///
1718 /// Composed body: constructs a two-step-short-circuit walk over
1719 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
1720 /// union primitive — pulls up to two hits off the filtered
1721 /// iterator; the primitive returns `true` iff BOTH the first and
1722 /// the second are [`Some`]. Byte-for-byte peer of
1723 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1724 /// one slice-layer down, lifted to compose against
1725 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1726 /// against a single slice's `has_kind`.
1727 ///
1728 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_multiple_distinct_condition_kind`]
1729 ///
1730 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1731 /// two-step short-circuit body composed against the point-domain
1732 /// surface's own union primitive. Both methods compose against
1733 /// the SAME slice-level substrate primitive
1734 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1735 /// via the two-slice union — a regression at the per-slice many-
1736 /// arm walk fails at that primitive's tests rather than as silent
1737 /// drift at either struct-level many-distinct caller.
1738 ///
1739 /// # Sibling to [`Self::distinct_condition_kinds`] /
1740 /// [`Self::distinct_condition_kind_count`]
1741 ///
1742 /// Cardinality-many-arm Boolean projection of the widened +
1743 /// scalar closed-set-inversion primitives on the ephemeral-union
1744 /// surface — where those primitives return the FULL distinct SET
1745 /// (a `Vec` of every present kind) and its cardinality (a `usize`
1746 /// in `0..=ConditionKind::ALL.len()`),
1747 /// `has_multiple_distinct_condition_kind` collapses either the
1748 /// widened primitive to its ≥ 2-length Boolean or the scalar to
1749 /// its `>= 2` cardinality-many-arm Boolean. Strictly cheaper than
1750 /// either widened primitive on every arm with `≥ 2` distinct kinds
1751 /// because the walk short-circuits at the second distinct kind
1752 /// rather than allocating the closed-set-inversion scan or walking
1753 /// every slot to build the scalar cardinality.
1754 ///
1755 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1756 /// preserves proofs — the cardinality-many-arm projection on the
1757 /// distinct axis composes the SAME two-step short-circuit walk
1758 /// under a two-slice union on both this ephemeral surface and the
1759 /// point-domain [`crate::boundary::Boundary`] surface). THEORY.md
1760 /// §VI.1 (generation over composition — a new [`ConditionKind`]
1761 /// variant reaches both surfaces' cardinality-many-arm triads
1762 /// mechanically through the delegated union primitive).
1763 #[must_use]
1764 pub fn has_multiple_distinct_condition_kind(&self) -> bool {
1765 let mut it = ConditionKind::ALL
1766 .iter()
1767 .copied()
1768 .filter(|k| self.has_condition_kind(*k));
1769 it.next().is_some() && it.next().is_some()
1770 }
1771
1772 /// `true` iff [`Self::preconditions`] carries AT LEAST TWO
1773 /// [`ConditionKind::ALL`] variants — the precondition-side arm of
1774 /// the (precondition, postcondition, condition-union) cardinality-
1775 /// many-arm triad on [`EphemeralSpec`] on the closed-set-inversion
1776 /// axis. Thin typed delegate to
1777 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1778 /// over [`Self::preconditions`].
1779 ///
1780 /// Peer of
1781 /// [`crate::boundary::Boundary::has_multiple_distinct_precondition_kind`]
1782 /// on the point-domain surface — both peers compose against the
1783 /// SAME slice-level substrate primitive so a regression at the
1784 /// per-slice two-step short-circuit walk fails at that primitive's
1785 /// tests rather than as silent drift at either struct-level arm.
1786 #[must_use]
1787 pub fn has_multiple_distinct_precondition_kind(&self) -> bool {
1788 self.preconditions.has_multiple_distinct_kinds()
1789 }
1790
1791 /// `true` iff [`Self::postconditions`] carries AT LEAST TWO
1792 /// [`ConditionKind::ALL`] variants — the postcondition-side arm of
1793 /// the (precondition, postcondition, condition-union) cardinality-
1794 /// many-arm triad on [`EphemeralSpec`] on the closed-set-inversion
1795 /// axis. Thin typed delegate to
1796 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1797 /// over [`Self::postconditions`].
1798 ///
1799 /// Peer of
1800 /// [`crate::boundary::Boundary::has_multiple_distinct_postcondition_kind`]
1801 /// on the point-domain surface. See
1802 /// [`Self::has_multiple_distinct_precondition_kind`] for the full
1803 /// rationale — the two methods share ONE lift motivation, ONE
1804 /// fail-before-pass-after composition-law pin, and ONE two-surface
1805 /// parity contract with the point-domain
1806 /// [`crate::boundary::Boundary`] cardinality-many-arm peer
1807 /// methods.
1808 #[must_use]
1809 pub fn has_multiple_distinct_postcondition_kind(&self) -> bool {
1810 self.postconditions.has_multiple_distinct_kinds()
1811 }
1812
1813 /// `true` iff `preconditions ∪ postconditions` carries AT MOST ONE
1814 /// [`ConditionKind::ALL`] variant — the union arm of the
1815 /// (precondition, postcondition, condition-union) cardinality
1816 /// "≤ 1" triad on [`EphemeralSpec`] closing the "at most one kind
1817 /// covered" arm on the union of the two condition slots on the
1818 /// closed-set-inversion axis. The Boolean cardinality "≤ 1"
1819 /// negation peer of [`Self::has_multiple_distinct_condition_kind`]
1820 /// (≥ 2 many-arm) under the definitional negation
1821 /// `!has_multiple_distinct_condition_kind`, and the trichotomy-
1822 /// union peer of `!has_any_distinct_condition_kind` (=0 empty-
1823 /// endpoint) OR [`Self::has_unique_distinct_condition_kind`] (=1
1824 /// mid-endpoint) — names the arrangement space where the ephemeral
1825 /// spec is EMPTY-OR-SINGLETON on the union (zero or exactly one
1826 /// kind present across the union of the two slices).
1827 ///
1828 /// Composed body: `!self.has_multiple_distinct_condition_kind()`
1829 /// — a definitional negation of the many-arm union primitive.
1830 /// Short-circuits transitively through
1831 /// [`Self::has_multiple_distinct_condition_kind`]'s two-step
1832 /// short-circuit walk over [`ConditionKind::ALL`] under
1833 /// [`Self::has_condition_kind`]. Byte-for-byte peer of
1834 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1835 /// one slice-layer down, lifted to compose against
1836 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1837 /// against a single slice's `has_kind`.
1838 ///
1839 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_at_most_one_distinct_condition_kind`]
1840 ///
1841 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1842 /// definitional-negation body composed against the point-domain
1843 /// surface's own many-arm union primitive. Both methods compose
1844 /// against the SAME slice-level substrate primitive
1845 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1846 /// via the two-slice union — a regression at the per-slice "≤ 1"
1847 /// negation fails at that primitive's tests rather than as silent
1848 /// drift at either struct-level empty-or-singleton caller.
1849 ///
1850 /// # Sibling to [`Self::distinct_condition_kinds`] /
1851 /// [`Self::distinct_condition_kind_count`]
1852 ///
1853 /// Cardinality "≤ 1" Boolean projection of the widened + scalar
1854 /// closed-set-inversion primitives on the ephemeral-union
1855 /// surface — where those primitives return the FULL distinct SET
1856 /// (a `Vec` of every present kind) and its cardinality (a `usize`
1857 /// in `0..=ConditionKind::ALL.len()`),
1858 /// `has_at_most_one_distinct_condition_kind` collapses either the
1859 /// widened primitive to its `≤ 1`-length Boolean or the scalar
1860 /// to its `<= 1` cardinality-negation Boolean. Strictly cheaper
1861 /// than either widened primitive on every arm because the
1862 /// underlying many-arm walk short-circuits at the second distinct
1863 /// kind — a subsequent bit-flip surfaces at ONE substrate call
1864 /// with no allocation.
1865 ///
1866 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1867 /// preserves proofs — the cardinality "≤ 1" projection on the
1868 /// distinct axis composes the SAME definitional negation of the
1869 /// many-arm two-step short-circuit walk on both this ephemeral
1870 /// surface and the point-domain [`crate::boundary::Boundary`]
1871 /// surface). THEORY.md §VI.1 (generation over composition — a
1872 /// new [`ConditionKind`] variant reaches both surfaces'
1873 /// cardinality "≤ 1" triads mechanically through the delegated
1874 /// union primitive).
1875 #[must_use]
1876 pub fn has_at_most_one_distinct_condition_kind(&self) -> bool {
1877 !self.has_multiple_distinct_condition_kind()
1878 }
1879
1880 /// `true` iff [`Self::preconditions`] carries AT MOST ONE
1881 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1882 /// the (precondition, postcondition, condition-union) cardinality
1883 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
1884 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1885 /// over [`Self::preconditions`].
1886 ///
1887 /// Peer of
1888 /// [`crate::boundary::Boundary::has_at_most_one_distinct_precondition_kind`]
1889 /// on the point-domain surface — both peers compose against the
1890 /// SAME slice-level substrate primitive so a regression at the
1891 /// per-slice "≤ 1" negation fails at that primitive's tests
1892 /// rather than as silent drift at either struct-level arm.
1893 #[must_use]
1894 pub fn has_at_most_one_distinct_precondition_kind(&self) -> bool {
1895 self.preconditions.has_at_most_one_distinct_kind()
1896 }
1897
1898 /// `true` iff [`Self::postconditions`] carries AT MOST ONE
1899 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1900 /// the (precondition, postcondition, condition-union) cardinality
1901 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
1902 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1903 /// over [`Self::postconditions`].
1904 ///
1905 /// Peer of
1906 /// [`crate::boundary::Boundary::has_at_most_one_distinct_postcondition_kind`]
1907 /// on the point-domain surface. See
1908 /// [`Self::has_at_most_one_distinct_precondition_kind`] for the
1909 /// full rationale — the two methods share ONE lift motivation,
1910 /// ONE fail-before-pass-after composition-law pin, and ONE two-
1911 /// surface parity contract with the point-domain
1912 /// [`crate::boundary::Boundary`] cardinality "≤ 1" peer methods.
1913 #[must_use]
1914 pub fn has_at_most_one_distinct_postcondition_kind(&self) -> bool {
1915 self.postconditions.has_at_most_one_distinct_kind()
1916 }
1917
1918 /// `true` iff `preconditions ∪ postconditions` carries NO
1919 /// [`ConditionKind::ALL`] variant — the peer of
1920 /// [`crate::boundary::Boundary::is_condition_kind_empty`] on the
1921 /// [`EphemeralSpec`] sugar surface. Names the cardinality zero-
1922 /// endpoint on the closed-set-inversion axis at the union struct
1923 /// layer.
1924 ///
1925 /// # Composed body — byte-identical to
1926 /// [`crate::boundary::Boundary::is_condition_kind_empty`]
1927 ///
1928 /// `!self.has_any_distinct_condition_kind()` — a definitional
1929 /// negation of the at-least-one halfspace union primitive. Byte-
1930 /// identical to the peer method on the point-domain
1931 /// [`crate::boundary::Boundary`] surface — both compose against
1932 /// the SAME slice-level substrate primitive
1933 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] via the
1934 /// two-slice union so a regression at the per-slice zero-endpoint
1935 /// short-circuit fails at that primitive's tests rather than as
1936 /// silent drift at either struct-level empty caller.
1937 ///
1938 /// # Sibling to [`Self::is_condition_kind_saturated`]
1939 ///
1940 /// Axis-parity mirror of the closed-set-complement saturation-
1941 /// endpoint peer at the union struct layer — where
1942 /// `is_condition_kind_saturated` tests "every kind PRESENT across
1943 /// the union", this primitive tests "no kind PRESENT across the
1944 /// union". Both name a cardinality-endpoint on their respective
1945 /// axis under the same union struct layer.
1946 ///
1947 /// # Sibling to [`Self::distinct_condition_kinds`] /
1948 /// [`Self::distinct_condition_kind_count`]
1949 ///
1950 /// Cardinality zero-endpoint Boolean projection of the widened +
1951 /// scalar closed-set-inversion primitives on the ephemeral-union
1952 /// surface — where those primitives return the FULL distinct SET
1953 /// and its cardinality, `is_condition_kind_empty` collapses either
1954 /// the widened primitive to its emptiness Boolean or the scalar to
1955 /// its `== 0` cardinality-endpoint Boolean.
1956 ///
1957 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1958 /// preserves proofs — the cardinality zero-endpoint projection on
1959 /// the distinct axis composes the SAME definitional negation of
1960 /// the at-least-one halfspace short-circuit walk on both this
1961 /// ephemeral surface and the point-domain
1962 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
1963 /// (generation over composition — a new [`ConditionKind`] variant
1964 /// reaches both surfaces' cardinality zero-endpoint triads
1965 /// mechanically through the delegated union primitive).
1966 #[must_use]
1967 pub fn is_condition_kind_empty(&self) -> bool {
1968 !self.has_any_distinct_condition_kind()
1969 }
1970
1971 /// `true` iff [`Self::preconditions`] carries NO
1972 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1973 /// the (precondition, postcondition, condition-union) cardinality
1974 /// zero-endpoint triad on [`EphemeralSpec`]. Thin typed delegate to
1975 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] over
1976 /// [`Self::preconditions`].
1977 ///
1978 /// Peer of
1979 /// [`crate::boundary::Boundary::is_precondition_kind_empty`] on the
1980 /// point-domain surface — both peers compose against the SAME
1981 /// slice-level substrate primitive so a regression at the per-slice
1982 /// zero-endpoint short-circuit fails at that primitive's tests
1983 /// rather than as silent drift at either struct-level arm.
1984 #[must_use]
1985 pub fn is_precondition_kind_empty(&self) -> bool {
1986 self.preconditions.is_kind_empty()
1987 }
1988
1989 /// `true` iff [`Self::postconditions`] carries NO
1990 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1991 /// the (precondition, postcondition, condition-union) cardinality
1992 /// zero-endpoint triad on [`EphemeralSpec`]. Thin typed delegate to
1993 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] over
1994 /// [`Self::postconditions`].
1995 ///
1996 /// Peer of
1997 /// [`crate::boundary::Boundary::is_postcondition_kind_empty`] on
1998 /// the point-domain surface. See
1999 /// [`Self::is_precondition_kind_empty`] for the full rationale —
2000 /// the two methods share ONE lift motivation, ONE fail-before-pass-
2001 /// after composition-law pin, and ONE two-surface parity contract
2002 /// with the point-domain [`crate::boundary::Boundary`] cardinality
2003 /// zero-endpoint peer methods.
2004 #[must_use]
2005 pub fn is_postcondition_kind_empty(&self) -> bool {
2006 self.postconditions.is_kind_empty()
2007 }
2008
2009 /// `true` iff `preconditions ∪ postconditions` is MISSING EXACTLY
2010 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
2011 /// (precondition, postcondition, condition-union) cardinality-
2012 /// mid-endpoint triad on [`EphemeralSpec`] closing the near-
2013 /// saturation-endpoint on the union of the two condition slots.
2014 /// The Boolean cardinality-mid-endpoint fast-path peer of
2015 /// [`Self::is_condition_kind_saturated`]: where the saturation-
2016 /// endpoint predicate answers "is the union covered by every ALL
2017 /// variant?", `has_unique_missing_condition_kind` answers "is the
2018 /// union one kind away from covered?".
2019 ///
2020 /// Composed body: constructs a two-step-short-circuit walk over
2021 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
2022 /// union primitive negated — the first missing union arm surfaces,
2023 /// then the walk short-circuits at the second. Byte-for-byte peer
2024 /// of
2025 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2026 /// one slice-layer down, lifted to compose against
2027 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
2028 /// against a single slice's `has_kind`.
2029 ///
2030 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
2031 ///
2032 /// Byte-identical signature `(&Self) -> bool`, byte-identical
2033 /// two-step short-circuit body composed against the point-domain
2034 /// surface's own union primitive. Both methods compose against
2035 /// the SAME slice-level substrate primitive
2036 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2037 /// via the two-slice union — a regression at the per-slice
2038 /// near-saturation-endpoint walk fails at that primitive's tests
2039 /// rather than as silent drift at either struct-level near-
2040 /// saturation caller.
2041 ///
2042 /// # Sibling to [`Self::missing_condition_kinds`] /
2043 /// [`Self::missing_condition_kind_count`]
2044 ///
2045 /// Cardinality-mid-endpoint Boolean projection of the widened +
2046 /// scalar closed-set-complement primitives on the ephemeral-union
2047 /// surface — where those primitives return the FULL missing SET
2048 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
2049 /// in `0..=ConditionKind::ALL.len()`),
2050 /// `has_unique_missing_condition_kind` collapses either the
2051 /// widened primitive to its unit-length Boolean or the scalar to
2052 /// its `== 1` cardinality-mid-endpoint Boolean. Strictly cheaper
2053 /// than either widened primitive on every arm with `≥ 2` missing
2054 /// kinds because the negation short-circuits at the second
2055 /// missing kind rather than allocating the closed-set-complement
2056 /// scan or walking every slot to build the scalar cardinality.
2057 ///
2058 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2059 /// preserves proofs — the cardinality-mid-endpoint projection on
2060 /// the missing axis composes the SAME two-step short-circuit walk
2061 /// under a two-slice union negation on both this ephemeral
2062 /// surface and the point-domain
2063 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2064 /// (generation over composition — a new [`ConditionKind`]
2065 /// variant reaches both surfaces' cardinality-mid-endpoint triads
2066 /// mechanically through the delegated union primitive).
2067 #[must_use]
2068 pub fn has_unique_missing_condition_kind(&self) -> bool {
2069 let mut it = ConditionKind::ALL
2070 .iter()
2071 .copied()
2072 .filter(|k| !self.has_condition_kind(*k));
2073 it.next().is_some() && it.next().is_none()
2074 }
2075
2076 /// `true` iff [`Self::preconditions`] is MISSING EXACTLY ONE
2077 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
2078 /// the (precondition, postcondition, condition-union)
2079 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
2080 /// typed delegate to
2081 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2082 /// over [`Self::preconditions`].
2083 ///
2084 /// Peer of
2085 /// [`crate::boundary::Boundary::has_unique_missing_precondition_kind`]
2086 /// on the point-domain surface — both peers compose against the
2087 /// SAME slice-level substrate primitive so a regression at the
2088 /// per-slice two-step short-circuit walk under negation fails at
2089 /// that primitive's tests rather than as silent drift at either
2090 /// struct-level arm.
2091 #[must_use]
2092 pub fn has_unique_missing_precondition_kind(&self) -> bool {
2093 self.preconditions.has_unique_missing_kind()
2094 }
2095
2096 /// `true` iff [`Self::postconditions`] is MISSING EXACTLY ONE
2097 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
2098 /// the (precondition, postcondition, condition-union)
2099 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
2100 /// typed delegate to
2101 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2102 /// over [`Self::postconditions`].
2103 ///
2104 /// Peer of
2105 /// [`crate::boundary::Boundary::has_unique_missing_postcondition_kind`]
2106 /// on the point-domain surface. See
2107 /// [`Self::has_unique_missing_precondition_kind`] for the full
2108 /// rationale — the two methods share ONE lift motivation, ONE
2109 /// fail-before-pass-after composition-law pin, and ONE two-surface
2110 /// parity contract with the point-domain
2111 /// [`crate::boundary::Boundary`] cardinality-mid-endpoint peer
2112 /// methods.
2113 #[must_use]
2114 pub fn has_unique_missing_postcondition_kind(&self) -> bool {
2115 self.postconditions.has_unique_missing_kind()
2116 }
2117
2118 /// `true` iff `preconditions ∪ postconditions` is MISSING AT
2119 /// LEAST TWO [`ConditionKind::ALL`] variants — the union arm of
2120 /// the (precondition, postcondition, condition-union) cardinality-
2121 /// many-arm triad on [`EphemeralSpec`] closing the "≥ 2 holes
2122 /// remaining" arm on the union of the two condition slots. The
2123 /// Boolean cardinality many-arm fast-path peer of
2124 /// [`Self::has_unique_missing_condition_kind`] (=1 arm) and
2125 /// [`Self::is_condition_kind_saturated`] (=0 arm): closes the
2126 /// {0, 1, ≥2} trichotomy on the missing axis at the ephemeral
2127 /// union struct layer.
2128 ///
2129 /// Composed body: constructs a two-step-short-circuit walk over
2130 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
2131 /// union primitive negated — pulls up to two hits off the
2132 /// filtered iterator; the primitive returns `true` iff BOTH the
2133 /// first and the second are [`Some`]. Byte-for-byte peer of
2134 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2135 /// one slice-layer down, lifted to compose against
2136 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
2137 /// against a single slice's `has_kind`.
2138 ///
2139 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
2140 ///
2141 /// Byte-identical signature `(&Self) -> bool`, byte-identical
2142 /// two-step short-circuit body composed against the point-domain
2143 /// surface's own union primitive. Both methods compose against
2144 /// the SAME slice-level substrate primitive
2145 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2146 /// via the two-slice union — a regression at the per-slice many-
2147 /// arm walk fails at that primitive's tests rather than as silent
2148 /// drift at either struct-level many-missing caller.
2149 ///
2150 /// # Sibling to [`Self::missing_condition_kinds`] /
2151 /// [`Self::missing_condition_kind_count`]
2152 ///
2153 /// Cardinality-many-arm Boolean projection of the widened +
2154 /// scalar closed-set-complement primitives on the ephemeral-union
2155 /// surface — where those primitives return the FULL missing SET
2156 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
2157 /// in `0..=ConditionKind::ALL.len()`),
2158 /// `has_multiple_missing_condition_kind` collapses either the
2159 /// widened primitive to its ≥ 2-length Boolean or the scalar to
2160 /// its `>= 2` cardinality-many-arm Boolean. Strictly cheaper than
2161 /// either widened primitive on every arm with `≥ 2` missing kinds
2162 /// because the negation short-circuits at the second missing kind
2163 /// rather than allocating the closed-set-complement scan or
2164 /// walking every slot to build the scalar cardinality.
2165 ///
2166 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2167 /// preserves proofs — the cardinality-many-arm projection on the
2168 /// missing axis composes the SAME two-step short-circuit walk
2169 /// under a two-slice union negation on both this ephemeral
2170 /// surface and the point-domain
2171 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2172 /// (generation over composition — a new [`ConditionKind`]
2173 /// variant reaches both surfaces' cardinality-many-arm triads
2174 /// mechanically through the delegated union primitive).
2175 #[must_use]
2176 pub fn has_multiple_missing_condition_kind(&self) -> bool {
2177 let mut it = ConditionKind::ALL
2178 .iter()
2179 .copied()
2180 .filter(|k| !self.has_condition_kind(*k));
2181 it.next().is_some() && it.next().is_some()
2182 }
2183
2184 /// `true` iff [`Self::preconditions`] is MISSING AT LEAST TWO
2185 /// [`ConditionKind::ALL`] variants — the precondition-side arm of
2186 /// the (precondition, postcondition, condition-union) cardinality-
2187 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
2188 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2189 /// over [`Self::preconditions`].
2190 ///
2191 /// Peer of
2192 /// [`crate::boundary::Boundary::has_multiple_missing_precondition_kind`]
2193 /// on the point-domain surface — both peers compose against the
2194 /// SAME slice-level substrate primitive so a regression at the
2195 /// per-slice two-step short-circuit walk under negation fails at
2196 /// that primitive's tests rather than as silent drift at either
2197 /// struct-level arm.
2198 #[must_use]
2199 pub fn has_multiple_missing_precondition_kind(&self) -> bool {
2200 self.preconditions.has_multiple_missing_kinds()
2201 }
2202
2203 /// `true` iff [`Self::postconditions`] is MISSING AT LEAST TWO
2204 /// [`ConditionKind::ALL`] variants — the postcondition-side arm of
2205 /// the (precondition, postcondition, condition-union) cardinality-
2206 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
2207 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2208 /// over [`Self::postconditions`].
2209 ///
2210 /// Peer of
2211 /// [`crate::boundary::Boundary::has_multiple_missing_postcondition_kind`]
2212 /// on the point-domain surface. See
2213 /// [`Self::has_multiple_missing_precondition_kind`] for the full
2214 /// rationale — the two methods share ONE lift motivation, ONE
2215 /// fail-before-pass-after composition-law pin, and ONE two-surface
2216 /// parity contract with the point-domain
2217 /// [`crate::boundary::Boundary`] cardinality-many-arm peer
2218 /// methods.
2219 #[must_use]
2220 pub fn has_multiple_missing_postcondition_kind(&self) -> bool {
2221 self.postconditions.has_multiple_missing_kinds()
2222 }
2223
2224 /// `true` iff `preconditions ∪ postconditions` is MISSING AT MOST
2225 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
2226 /// (precondition, postcondition, condition-union) cardinality
2227 /// "≤ 1" triad on [`EphemeralSpec`] closing the "at most one hole
2228 /// remaining" arm on the union of the two condition slots. The
2229 /// Boolean cardinality "≤ 1" negation peer of
2230 /// [`Self::has_multiple_missing_condition_kind`] (≥ 2 many-arm)
2231 /// under the definitional negation
2232 /// `!has_multiple_missing_condition_kind`, and the trichotomy-
2233 /// union peer of [`Self::is_condition_kind_saturated`] (=0
2234 /// zero-arm) OR [`Self::has_unique_missing_condition_kind`] (=1
2235 /// mid-endpoint) — names the arrangement space where the
2236 /// ephemeral spec is SATURATED-OR-NEAR-SATURATED on the union
2237 /// (zero or exactly one kind missing across the union of the two
2238 /// slices).
2239 ///
2240 /// Composed body: `!self.has_multiple_missing_condition_kind()`
2241 /// — a definitional negation of the many-arm union primitive.
2242 /// Short-circuits transitively through
2243 /// [`Self::has_multiple_missing_condition_kind`]'s two-step short-
2244 /// circuit walk over [`ConditionKind::ALL`] under negated
2245 /// [`Self::has_condition_kind`]. Byte-for-byte peer of
2246 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2247 /// one slice-layer down, lifted to compose against
2248 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
2249 /// against a single slice's `has_kind`.
2250 ///
2251 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
2252 ///
2253 /// Byte-identical signature `(&Self) -> bool`, byte-identical
2254 /// definitional-negation body composed against the point-domain
2255 /// surface's own many-arm union primitive. Both methods compose
2256 /// against the SAME slice-level substrate primitive
2257 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2258 /// via the two-slice union — a regression at the per-slice "≤ 1"
2259 /// negation fails at that primitive's tests rather than as silent
2260 /// drift at either struct-level near-saturation-or-saturated
2261 /// caller.
2262 ///
2263 /// # Sibling to [`Self::missing_condition_kinds`] /
2264 /// [`Self::missing_condition_kind_count`]
2265 ///
2266 /// Cardinality "≤ 1" Boolean projection of the widened + scalar
2267 /// closed-set-complement primitives on the ephemeral-union
2268 /// surface — where those primitives return the FULL missing SET
2269 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
2270 /// in `0..=ConditionKind::ALL.len()`),
2271 /// `has_at_most_one_missing_condition_kind` collapses either the
2272 /// widened primitive to its `≤ 1`-length Boolean or the scalar
2273 /// to its `<= 1` cardinality-negation Boolean. Strictly cheaper
2274 /// than either widened primitive on every arm because the
2275 /// underlying many-arm walk short-circuits at the second missing
2276 /// kind — a subsequent bit-flip surfaces at ONE substrate call
2277 /// with no allocation.
2278 ///
2279 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2280 /// preserves proofs — the cardinality "≤ 1" projection on the
2281 /// missing axis composes the SAME definitional negation of the
2282 /// many-arm two-step short-circuit walk on both this ephemeral
2283 /// surface and the point-domain [`crate::boundary::Boundary`]
2284 /// surface). THEORY.md §VI.1 (generation over composition — a
2285 /// new [`ConditionKind`] variant reaches both surfaces'
2286 /// cardinality "≤ 1" triads mechanically through the delegated
2287 /// union primitive).
2288 #[must_use]
2289 pub fn has_at_most_one_missing_condition_kind(&self) -> bool {
2290 !self.has_multiple_missing_condition_kind()
2291 }
2292
2293 /// `true` iff [`Self::preconditions`] is MISSING AT MOST ONE
2294 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
2295 /// the (precondition, postcondition, condition-union) cardinality
2296 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
2297 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2298 /// over [`Self::preconditions`].
2299 ///
2300 /// Peer of
2301 /// [`crate::boundary::Boundary::has_at_most_one_missing_precondition_kind`]
2302 /// on the point-domain surface — both peers compose against the
2303 /// SAME slice-level substrate primitive so a regression at the
2304 /// per-slice "≤ 1" negation fails at that primitive's tests
2305 /// rather than as silent drift at either struct-level arm.
2306 #[must_use]
2307 pub fn has_at_most_one_missing_precondition_kind(&self) -> bool {
2308 self.preconditions.has_at_most_one_missing_kind()
2309 }
2310
2311 /// `true` iff [`Self::postconditions`] is MISSING AT MOST ONE
2312 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
2313 /// the (precondition, postcondition, condition-union) cardinality
2314 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
2315 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2316 /// over [`Self::postconditions`].
2317 ///
2318 /// Peer of
2319 /// [`crate::boundary::Boundary::has_at_most_one_missing_postcondition_kind`]
2320 /// on the point-domain surface. See
2321 /// [`Self::has_at_most_one_missing_precondition_kind`] for the
2322 /// full rationale — the two methods share ONE lift motivation,
2323 /// ONE fail-before-pass-after composition-law pin, and ONE two-
2324 /// surface parity contract with the point-domain
2325 /// [`crate::boundary::Boundary`] cardinality "≤ 1" peer methods.
2326 #[must_use]
2327 pub fn has_at_most_one_missing_postcondition_kind(&self) -> bool {
2328 self.postconditions.has_at_most_one_missing_kind()
2329 }
2330
2331 /// `true` iff `preconditions ∪ postconditions` carries NO
2332 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2333 /// — the peer of
2334 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
2335 /// [`EphemeralSpec`] sugar surface.
2336 ///
2337 /// # Composed body — byte-identical to
2338 /// [`crate::boundary::Boundary::lacks_condition_kind`]
2339 ///
2340 /// `!self.has_condition_kind(kind)` — the definitional negation of
2341 /// the two-slice union primitive [`Self::has_condition_kind`].
2342 /// Byte-identical to the peer method on the point-domain
2343 /// [`crate::boundary::Boundary`] surface — both compose against
2344 /// the SAME slice-level substrate primitive
2345 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] via the
2346 /// two-slice union so a regression at the per-slice negation
2347 /// fails at that primitive's tests rather than as silent drift at
2348 /// either struct-level complement caller.
2349 ///
2350 /// # Sibling to [`Self::missing_condition_kinds`] /
2351 /// [`Self::missing_condition_kind_count`]
2352 ///
2353 /// Per-kind Boolean projection of the widened + scalar closed-set-
2354 /// complement primitives on the ephemeral-union surface — where
2355 /// those primitives return the FULL missing SET (a `Vec` of every
2356 /// absent kind) and its cardinality (a `usize`),
2357 /// `lacks_condition_kind` collapses the missing SET to its
2358 /// per-kind membership Boolean for ONE addressed kind. Strictly
2359 /// cheaper than reaching for the widened primitive on every
2360 /// per-kind question because the negation short-circuits through
2361 /// [`Self::has_condition_kind`] rather than allocating the
2362 /// closed-set-complement scan.
2363 ///
2364 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2365 /// preserves proofs — the per-kind closed-set-complement
2366 /// projection composes the SAME two-slice union negation on both
2367 /// this ephemeral surface and the point-domain
2368 /// [`crate::boundary::Boundary`] surface under definitional
2369 /// negation). THEORY.md §VI.1 (generation over composition — a
2370 /// future [`ConditionKind`] variant reaches both surfaces'
2371 /// per-kind-complement triads mechanically through the delegated
2372 /// union primitive).
2373 #[must_use]
2374 pub fn lacks_condition_kind(&self, kind: ConditionKind) -> bool {
2375 !self.has_condition_kind(kind)
2376 }
2377
2378 /// `true` iff [`Self::preconditions`] carries NO
2379 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2380 /// — the precondition-side arm of the (precondition, postcondition,
2381 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
2382 /// Thin typed delegate to
2383 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
2384 /// [`Self::preconditions`].
2385 ///
2386 /// Peer of
2387 /// [`crate::boundary::Boundary::lacks_precondition_kind`] on the
2388 /// point-domain surface — both peers compose against the SAME
2389 /// slice-level substrate primitive so a regression at the
2390 /// per-slice negation fails at that primitive's tests rather than
2391 /// as silent drift at either struct-level arm.
2392 #[must_use]
2393 pub fn lacks_precondition_kind(&self, kind: ConditionKind) -> bool {
2394 self.preconditions.lacks_kind(kind)
2395 }
2396
2397 /// `true` iff [`Self::postconditions`] carries NO
2398 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2399 /// — the postcondition-side arm of the (precondition, postcondition,
2400 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
2401 /// Thin typed delegate to
2402 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
2403 /// [`Self::postconditions`].
2404 ///
2405 /// Peer of
2406 /// [`crate::boundary::Boundary::lacks_postcondition_kind`] on the
2407 /// point-domain surface. See [`Self::lacks_precondition_kind`] for
2408 /// the full rationale — the two methods share ONE lift motivation,
2409 /// ONE fail-before-pass-after composition-law pin, and ONE
2410 /// two-surface parity contract with the point-domain
2411 /// [`crate::boundary::Boundary`] per-kind-complement peer methods.
2412 #[must_use]
2413 pub fn lacks_postcondition_kind(&self, kind: ConditionKind) -> bool {
2414 self.postconditions.lacks_kind(kind)
2415 }
2416
2417 /// `true` iff `preconditions ∪ postconditions` carries at least
2418 /// one [`crate::boundary::Condition`] with the given
2419 /// [`ConditionKind`] AND carries no [`crate::boundary::Condition`]
2420 /// whose kind is anything OTHER than `kind` — the union arm of
2421 /// the (precondition, postcondition, condition-union) kind-scoped
2422 /// strict-refinement triad on [`EphemeralSpec`], byte-for-byte
2423 /// peer of the point-domain
2424 /// [`crate::boundary::Boundary::has_only_condition_kind`] under
2425 /// the same fused-closed-set-walk body.
2426 ///
2427 /// # Composed body
2428 ///
2429 /// A FUSED short-circuit closed-set walk over
2430 /// [`ConditionKind::ALL`] under [`Self::has_condition_kind`] that
2431 /// returns `false` at the EARLIEST kind whose presence spans
2432 /// either slice's populated set and is NOT `kind`, and returns
2433 /// `true` iff the sweep completes with `kind` seen as the sole
2434 /// distinct populated kind. Strictly cheaper than the widened
2435 /// composition
2436 /// `self.distinct_condition_kinds() == vec![kind]` (which
2437 /// allocates the distinct-kind Vec before the equality test) or
2438 /// the (pre, post) AND-of-strict-refinement
2439 /// `self.preconditions.has_only_kind(kind)
2440 /// && self.postconditions.has_only_kind(kind)` (which is TOO
2441 /// STRICT — a single-slice-populated arrangement whose empty side
2442 /// returns `false` fails this AND but IS well-formed on the
2443 /// union).
2444 ///
2445 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_only_condition_kind`]
2446 ///
2447 /// Byte-identical signature `(&Self, ConditionKind) -> bool`,
2448 /// byte-identical fused-closed-set-walk body, on the point-domain
2449 /// surface whose pre/post condition vectors live inside a
2450 /// [`crate::boundary::Boundary`] slot. Both methods compose
2451 /// against the SAME slice-level substrate primitive
2452 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] via the
2453 /// two-slice union composed through [`Self::has_condition_kind`]
2454 /// — a regression at the per-slice fused walk fails at that
2455 /// primitive's tests rather than as silent drift at either
2456 /// struct-level kind-scoped-strict-refinement caller.
2457 ///
2458 /// # Compounding
2459 ///
2460 /// A future coherence check verifying "every ephemeral spec whose
2461 /// postconditions carry ONLY `ClosedLoopAuth` (no `JobAttested`,
2462 /// no `Cel`, ...) is a well-formed closed-loop probe" reads
2463 /// `spec.has_only_condition_kind(ConditionKind::ClosedLoopAuth)`
2464 /// at ONE call site rather than restating either widened
2465 /// composition. A `has-only-<kind>` require-tag classifier arm on
2466 /// the ephemeral surface reaches this primitive at ONE substrate
2467 /// call — byte-for-byte peer of the tagged-union
2468 /// `has-only-<kind>` classifier one struct-layer up under the
2469 /// SAME fused short-circuit walk shape.
2470 ///
2471 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2472 /// preserves proofs — the kind-scoped strict-refinement projection
2473 /// composes the SAME fused short-circuit closed-set walk under
2474 /// [`Self::has_condition_kind`] on both this ephemeral surface
2475 /// and the point-domain [`crate::boundary::Boundary`] surface).
2476 /// THEORY.md §VI.1 (generation over composition — a future
2477 /// [`ConditionKind`] variant reaches both surfaces' kind-scoped
2478 /// strict-refinement triads mechanically through the delegated
2479 /// union primitive).
2480 #[must_use]
2481 pub fn has_only_condition_kind(&self, kind: ConditionKind) -> bool {
2482 let mut saw_kind = false;
2483 for k in ConditionKind::ALL {
2484 if !self.has_condition_kind(k) {
2485 continue;
2486 }
2487 if k == kind {
2488 saw_kind = true;
2489 } else {
2490 return false;
2491 }
2492 }
2493 saw_kind
2494 }
2495
2496 /// `true` iff [`Self::preconditions`] carries at least one
2497 /// [`crate::boundary::Condition`] with the given
2498 /// [`ConditionKind`] AND carries no
2499 /// [`crate::boundary::Condition`] whose kind is anything OTHER
2500 /// than `kind` — the precondition-side arm of the (precondition,
2501 /// postcondition, condition-union) kind-scoped strict-refinement
2502 /// triad on [`EphemeralSpec`]. Thin typed delegate to
2503 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] over
2504 /// [`Self::preconditions`].
2505 ///
2506 /// Peer of
2507 /// [`crate::boundary::Boundary::has_only_precondition_kind`] on
2508 /// the point-domain surface — both peers compose against the SAME
2509 /// slice-level substrate primitive so a regression at the per-
2510 /// slice fused walk fails at that primitive's tests rather than
2511 /// as silent drift at either struct-level arm.
2512 #[must_use]
2513 pub fn has_only_precondition_kind(&self, kind: ConditionKind) -> bool {
2514 self.preconditions.has_only_kind(kind)
2515 }
2516
2517 /// `true` iff [`Self::postconditions`] carries at least one
2518 /// [`crate::boundary::Condition`] with the given
2519 /// [`ConditionKind`] AND carries no
2520 /// [`crate::boundary::Condition`] whose kind is anything OTHER
2521 /// than `kind` — the postcondition-side arm of the (precondition,
2522 /// postcondition, condition-union) kind-scoped strict-refinement
2523 /// triad on [`EphemeralSpec`]. Thin typed delegate to
2524 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] over
2525 /// [`Self::postconditions`].
2526 ///
2527 /// Peer of
2528 /// [`crate::boundary::Boundary::has_only_postcondition_kind`] on
2529 /// the point-domain surface. See [`Self::has_only_precondition_kind`]
2530 /// for the full rationale — the two methods share ONE lift
2531 /// motivation, ONE fail-before-pass-after composition-law pin,
2532 /// and ONE two-surface parity contract with the point-domain
2533 /// [`crate::boundary::Boundary`] kind-scoped-strict-refinement
2534 /// peer methods.
2535 #[must_use]
2536 pub fn has_only_postcondition_kind(&self, kind: ConditionKind) -> bool {
2537 self.postconditions.has_only_kind(kind)
2538 }
2539
2540 /// `true` iff `preconditions ∪ postconditions` carries NO
2541 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2542 /// AND carries at least one [`crate::boundary::Condition`] for
2543 /// every OTHER [`ConditionKind`] — the union arm of the
2544 /// (precondition, postcondition, condition-union) kind-scoped
2545 /// strict-refinement-on-missing triad on [`EphemeralSpec`], byte-
2546 /// for-byte peer of the point-domain
2547 /// [`crate::boundary::Boundary::lacks_only_condition_kind`] under
2548 /// the same fused-closed-set-walk body on the missing axis.
2549 ///
2550 /// # Composed body
2551 ///
2552 /// A FUSED short-circuit closed-set walk over
2553 /// [`ConditionKind::ALL`] under [`Self::has_condition_kind`] that
2554 /// skips every populated kind, returns `false` at the EARLIEST
2555 /// kind whose absence spans both slices' missing sets and is NOT
2556 /// `kind`, and returns `true` iff the sweep completes with `kind`
2557 /// seen as the sole missing kind. Strictly cheaper than the
2558 /// widened composition
2559 /// `self.missing_condition_kinds() == vec![kind]` (which allocates
2560 /// the missing-kind Vec before the equality test) or the
2561 /// (pre AND post) AND-of-strict-refinement
2562 /// `self.preconditions.lacks_only_kind(kind)
2563 /// && self.postconditions.lacks_only_kind(kind)` (which is TOO
2564 /// STRICT — a single-slice-populated arrangement whose empty side
2565 /// returns `false` fails this AND but IS well-formed on the
2566 /// union).
2567 ///
2568 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::lacks_only_condition_kind`]
2569 ///
2570 /// Byte-identical signature `(&Self, ConditionKind) -> bool`,
2571 /// byte-identical fused-closed-set-walk body under complement, on
2572 /// the point-domain surface whose pre/post condition vectors live
2573 /// inside a [`crate::boundary::Boundary`] slot. Both methods
2574 /// compose against the SAME slice-level substrate primitive
2575 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] via
2576 /// the two-slice union composed through
2577 /// [`Self::has_condition_kind`] — a regression at the per-slice
2578 /// fused walk under complement fails at that primitive's tests
2579 /// rather than as silent drift at either struct-level kind-scoped-
2580 /// strict-refinement-on-missing caller.
2581 ///
2582 /// # Compounding
2583 ///
2584 /// A future coherence check verifying "every partially-attested
2585 /// ephemeral closed-loop probe is missing ONLY the
2586 /// `ClosedLoopAuth` postcondition" reads
2587 /// `spec.lacks_only_condition_kind(ConditionKind::ClosedLoopAuth)`
2588 /// at ONE call site rather than restating either widened
2589 /// composition. A `lacks-only-<kind>` require-tag classifier arm
2590 /// on the ephemeral surface reaches this primitive at ONE
2591 /// substrate call — byte-for-byte peer of the tagged-union
2592 /// `lacks-only-<kind>` classifier one struct-layer up under the
2593 /// SAME fused short-circuit walk shape.
2594 ///
2595 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2596 /// preserves proofs — the kind-scoped strict-refinement projection
2597 /// on the missing axis composes the SAME fused short-circuit
2598 /// closed-set walk under [`Self::has_condition_kind`] on both this
2599 /// ephemeral surface and the point-domain
2600 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2601 /// (generation over composition — a future [`ConditionKind`]
2602 /// variant reaches both surfaces' kind-scoped-strict-refinement-
2603 /// on-missing triads mechanically through the delegated union
2604 /// primitive).
2605 #[must_use]
2606 pub fn lacks_only_condition_kind(&self, kind: ConditionKind) -> bool {
2607 let mut saw_kind = false;
2608 for k in ConditionKind::ALL {
2609 if self.has_condition_kind(k) {
2610 continue;
2611 }
2612 if k == kind {
2613 saw_kind = true;
2614 } else {
2615 return false;
2616 }
2617 }
2618 saw_kind
2619 }
2620
2621 /// `true` iff [`Self::preconditions`] carries NO
2622 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2623 /// AND carries at least one [`crate::boundary::Condition`] for
2624 /// every OTHER [`ConditionKind`] — the precondition-side arm of
2625 /// the (precondition, postcondition, condition-union) kind-scoped-
2626 /// strict-refinement-on-missing triad on [`EphemeralSpec`]. Thin
2627 /// typed delegate to
2628 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] over
2629 /// [`Self::preconditions`].
2630 ///
2631 /// Peer of
2632 /// [`crate::boundary::Boundary::lacks_only_precondition_kind`] on
2633 /// the point-domain surface — both peers compose against the SAME
2634 /// slice-level substrate primitive so a regression at the per-
2635 /// slice fused walk under complement fails at that primitive's
2636 /// tests rather than as silent drift at either struct-level arm.
2637 #[must_use]
2638 pub fn lacks_only_precondition_kind(&self, kind: ConditionKind) -> bool {
2639 self.preconditions.lacks_only_kind(kind)
2640 }
2641
2642 /// `true` iff [`Self::postconditions`] carries NO
2643 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2644 /// AND carries at least one [`crate::boundary::Condition`] for
2645 /// every OTHER [`ConditionKind`] — the postcondition-side arm of
2646 /// the (precondition, postcondition, condition-union) kind-scoped-
2647 /// strict-refinement-on-missing triad on [`EphemeralSpec`]. Thin
2648 /// typed delegate to
2649 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] over
2650 /// [`Self::postconditions`].
2651 ///
2652 /// Peer of
2653 /// [`crate::boundary::Boundary::lacks_only_postcondition_kind`] on
2654 /// the point-domain surface. See [`Self::lacks_only_precondition_kind`]
2655 /// for the full rationale — the two methods share ONE lift
2656 /// motivation, ONE fail-before-pass-after composition-law pin,
2657 /// and ONE two-surface parity contract with the point-domain
2658 /// [`crate::boundary::Boundary`] kind-scoped-strict-refinement-
2659 /// on-missing peer methods.
2660 #[must_use]
2661 pub fn lacks_only_postcondition_kind(&self, kind: ConditionKind) -> bool {
2662 self.postconditions.lacks_only_kind(kind)
2663 }
2664
2665 /// True iff this ephemeral spec's stored [`TeardownPolicy`] equals
2666 /// `kind` — the substrate primitive that owns the
2667 /// (`&EphemeralSpec`, [`TeardownPolicy`]) → `bool` presence-probe
2668 /// shape on the sugar-surface type.
2669 ///
2670 /// # Peer to [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
2671 ///
2672 /// [`EphemeralLifetime::has_teardown_policy`] carries the same
2673 /// `(&self, TeardownPolicy) -> bool` signature on the point-surface
2674 /// carrier ([`ProcessSpec`]'s nested [`crate::lifetime::Lifetime`]
2675 /// slot reached through
2676 /// [`crate::lifetime::Lifetime::resolved_ephemeral`]); this peer
2677 /// composes byte-identical `==` semantics on
2678 /// [`EphemeralSpec`]'s direct `teardown: TeardownPolicy` scalar
2679 /// slot, so both surfaces' `teardown-policy-<kind>` require-tag
2680 /// families ([`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
2681 /// on the point surface, this peer on the ephemeral surface) route
2682 /// through the SAME scalar `==` shape. A future normalization at
2683 /// the probe shape (a widened return carrying a `TerminatePolicy`
2684 /// disambiguator, a debug-build assertion on operator-set vs
2685 /// defaulted overrides, a fleet-wide warn on `Never` combined with
2686 /// short TTLs) lands at ONE site per surface and every downstream
2687 /// `teardown-policy-<kind>` require-tag family + closed-set audit
2688 /// dispatcher picks it up mechanically.
2689 ///
2690 /// # Semantics — VARIANT match, not POPULATED slot
2691 ///
2692 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
2693 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
2694 /// absent state to detect. `has_teardown_policy(kind)` returns
2695 /// `true` iff `self.teardown == kind`. On a hand-authored
2696 /// [`EphemeralSpec`] that omits `:teardown` from the
2697 /// `(defephemeral …)` form (or a Rust builder that reaches
2698 /// [`TeardownPolicy::default`]) the probe returns `true` for
2699 /// [`TeardownPolicy::Always`] and `false` for every other variant
2700 /// — distinct from the Option-slot axis where a default carrier
2701 /// returns `false` for EVERY kind. An operator who left
2702 /// `:teardown` at the substrate default IS configured for
2703 /// `Always`, and a `:requires (teardown-policy-Always)` check
2704 /// should pass; only an operator who deliberately overrode the
2705 /// policy to `OnAttested` / `OnFailed` / `Never` fails the tag on
2706 /// this axis.
2707 ///
2708 /// # Corner — (required-scalar-child)
2709 ///
2710 /// Fresh corner on the ephemeral surface's presence-probe algebra:
2711 /// [`EphemeralSpec`] has no Option-parent hop between the sugar
2712 /// struct and the `teardown` scalar (the point surface reaches
2713 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
2714 /// through the Option-parent `resolved_ephemeral()` gate), so the
2715 /// probe body is a bare scalar `==` on a required field. Distinct
2716 /// from [`Self::has_condition_kind`] on this same surface, which
2717 /// walks a `Vec<Condition>` slice-child.
2718 ///
2719 /// # Compounding
2720 ///
2721 /// The ephemeral require-tag classifier composes this primitive
2722 /// with the closed-set `FromStr` autoderived on [`TeardownPolicy`]
2723 /// through the `strip_and_classify_prefixed_kind` substrate to
2724 /// publish a `teardown-policy-<kind>` prefix family byte-for-byte
2725 /// symmetrical with the point surface's family via
2726 /// [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]. A
2727 /// future fifth [`TeardownPolicy`] variant added to `ALL` (a
2728 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
2729 /// reaches BOTH surfaces' `teardown-policy-<kind>` prefix families
2730 /// through the SAME closed-set walk with no per-caller edit — the
2731 /// two-surface symmetry means adding a variant on the closed set
2732 /// publishes it in lockstep across every downstream consumer.
2733 ///
2734 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2735 /// preserves proofs — the scalar-carrier presence-probe body lives
2736 /// at ONE substrate site per surface so every downstream
2737 /// (`teardown-policy-<kind>` require-tag families on both surfaces
2738 /// in tatara-check, closed-set audit dispatchers, future variant
2739 /// additions on [`TeardownPolicy`]) binds through the SAME
2740 /// `has(kind)` shape rather than restating the `<eph>.teardown ==
2741 /// kind` closure body at each call site). THEORY.md §VI.1
2742 /// (generation over composition — a future variant lands at ONE
2743 /// `ALL` entry + one `as_str` arm on the closed set and the probe
2744 /// picks it up mechanically without further per-consumer edits).
2745 #[must_use]
2746 pub fn has_teardown_policy(&self, kind: TeardownPolicy) -> bool {
2747 self.teardown == kind
2748 }
2749
2750 /// Derived-bool-predicate presence probe on the stored
2751 /// [`Self::teardown`] slot — `true` iff this ephemeral sugar's
2752 /// [`TeardownPolicy`] would auto-SIGTERM the Process on the
2753 /// queried [`ProcessPhase`] transition (as read through
2754 /// [`TeardownPolicy::should_teardown_on`]).
2755 ///
2756 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
2757 ///
2758 /// Same shape, same axis, one refinement lower: the point-surface
2759 /// peer on [`crate::lifetime::EphemeralLifetime`] composes the SAME
2760 /// [`TeardownPolicy::should_teardown_on`] predicate against the
2761 /// SAME stored `teardown_policy` slot; this method composes the
2762 /// same predicate against the sugar surface's flattened
2763 /// [`Self::teardown`] slot. Both bodies delegate to the ONE
2764 /// substrate owner [`TeardownPolicy::should_teardown_on`], so a
2765 /// regression at the (policy, phase) → bool truth table surfaces
2766 /// at THAT primitive's tests rather than as silent drift at
2767 /// either struct-level caller.
2768 ///
2769 /// # Corner — (required-scalar-parent × derived-bool-predicate-child)
2770 ///
2771 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
2772 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
2773 /// Option-parent hop between the sugar struct and the `teardown`
2774 /// scalar (the point surface reaches
2775 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
2776 /// through the Option-parent `resolved_ephemeral()` gate). The
2777 /// probe body is a bare predicate application on a required
2778 /// field. Distinct from [`Self::has_teardown_policy`] on this
2779 /// same surface, which reads the raw stored variant for equality
2780 /// (`self.teardown == kind`) rather than the derived firing-arm
2781 /// predicate against a [`ProcessPhase`] argument.
2782 ///
2783 /// # Compounding
2784 ///
2785 /// The ephemeral require-tag classifier composes this primitive
2786 /// with the closed-set [`crate::phase::ProcessPhase`]'s
2787 /// autoderived `FromStr` through the
2788 /// `strip_and_classify_prefixed_kind` substrate to publish a
2789 /// `teardown-fires-on-<phase>` prefix family byte-for-byte
2790 /// symmetrical with the point surface's family via
2791 /// [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`].
2792 /// A future fifth [`TeardownPolicy`] variant added to `ALL` (a
2793 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
2794 /// reaches BOTH surfaces' `teardown-fires-on-<phase>` prefix
2795 /// families through the SAME
2796 /// [`TeardownPolicy::should_teardown_on`] match with no per-
2797 /// caller edit — the two-surface symmetry means adding a variant
2798 /// on the closed set publishes it in lockstep across every
2799 /// downstream consumer.
2800 ///
2801 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2802 /// preserves proofs — the derived-bool-predicate presence-probe
2803 /// body lives at ONE substrate site per surface, both composing
2804 /// the SAME [`TeardownPolicy::should_teardown_on`] projection, so
2805 /// every downstream (`teardown-fires-on-<phase>` require-tag
2806 /// families on both surfaces in tatara-check, closed-set audit
2807 /// dispatchers, future variant additions on either
2808 /// [`TeardownPolicy`] or [`crate::phase::ProcessPhase`]) binds
2809 /// through the SAME `has_teardown_firing_on(phase)` shape rather
2810 /// than restating the `<eph>.teardown.should_teardown_on(phase)`
2811 /// closure body at each call site). THEORY.md §VI.1 (generation
2812 /// over composition — a future variant lands at ONE `ALL` entry +
2813 /// one `as_str` arm + one `should_teardown_on` arm on the closed
2814 /// set and the probe picks it up mechanically without further
2815 /// per-consumer edits).
2816 #[must_use]
2817 pub const fn has_teardown_firing_on(&self, phase: ProcessPhase) -> bool {
2818 self.teardown.should_teardown_on(phase)
2819 }
2820
2821 /// Resolve the operator-authored [`Self::classification`] slot to
2822 /// the concrete [`Classification`] the point surface sees, filling
2823 /// `None` through the same [`default_ephemeral_class`] baseline the
2824 /// `From<EphemeralSpec> for ProcessSpec` lowering uses when the
2825 /// operator omits `:classification` from the `(defephemeral …)`
2826 /// form. Returns [`Cow::Borrowed`] on the populated arm (zero
2827 /// allocation), else [`Cow::Owned`] with the workspace-baseline
2828 /// `(Gate, Compute, Bounded, Monotone, Internal)` value the sibling
2829 /// primitive [`Classification::gate_compute`] owns.
2830 ///
2831 /// # ONE substrate primitive for `Option<Classification>` resolution
2832 ///
2833 /// This is the ONE `EphemeralSpec`-inherent primitive that owns the
2834 /// `Option<Classification>` → resolved-[`Classification`] walk.
2835 /// Every downstream classification-axis presence probe on the
2836 /// [`EphemeralSpec`] surface ([`Self::has_point_type`],
2837 /// [`Self::has_substrate`], [`Self::has_calm`],
2838 /// [`Self::has_data_classification`], [`Self::has_horizon_kind`],
2839 /// [`Self::has_optimization_direction`], [`Self::has_input_arity`],
2840 /// [`Self::has_output_arity`]) routes through THIS
2841 /// primitive so the "`None` fills through
2842 /// [`default_ephemeral_class`]" resolution lives at ONE site rather
2843 /// than being restated in each per-axis probe body. A future
2844 /// regression on the fill-through (a shift from the `(Gate,
2845 /// Compute, …)` baseline to a different `default_ephemeral_class`
2846 /// body, a shift from the `Option`-carrier shape to a
2847 /// serde-defaulted required-field carrier, an eventual audit hook
2848 /// naming the resolved-vs-authored provenance) lands at ONE site
2849 /// and every downstream axis-probe on the ephemeral surface picks
2850 /// it up mechanically.
2851 ///
2852 /// # Sibling to the `From<EphemeralSpec>` lowering
2853 ///
2854 /// The lowering `From<EphemeralSpec> for ProcessSpec` fills
2855 /// [`ProcessSpec::classification`] through the SAME
2856 /// `.unwrap_or_else(default_ephemeral_class)` walk that this
2857 /// primitive owns on the borrow-friendly `Cow` return. Both sites
2858 /// resolve the same operator-authored slot through the same default
2859 /// so a future two-surface parity contract on the classification
2860 /// axes (`point-type-<kind>` on both surfaces, `substrate-<kind>`
2861 /// on both surfaces, …) reads identically through the sibling
2862 /// point-surface probe [`Classification::has_<axis>`] on the
2863 /// lowered `ProcessSpec` and through THIS primitive on the same
2864 /// authored [`EphemeralSpec`].
2865 ///
2866 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2867 /// preserves proofs; the `Option<Classification>` resolution body
2868 /// lives at ONE substrate primitive on the ephemeral surface so
2869 /// every downstream classification-axis probe binds through the
2870 /// SAME `resolved_classification()` shape rather than restating
2871 /// the `self.classification.as_ref().unwrap_or(&default_…)`
2872 /// closure body at each callsite. THEORY.md §VI.1 — generation
2873 /// over composition; a future classification-axis peer
2874 /// (`has_substrate`, `has_calm`, …) lands as ONE inherent method
2875 /// that delegates through the resolver's `has_<axis>(kind)` call
2876 /// on the sibling [`Classification`] closed-set primitive with no
2877 /// per-axis restatement of the fill-through logic.
2878 #[must_use]
2879 pub fn resolved_classification(&self) -> Cow<'_, Classification> {
2880 match &self.classification {
2881 Some(c) => Cow::Borrowed(c),
2882 None => Cow::Owned(default_ephemeral_class()),
2883 }
2884 }
2885
2886 /// Overlay a single [`ClassificationAxis`] variant onto this
2887 /// ephemeral spec's authored [`Self::classification`] slot, filling
2888 /// `None` through [`Classification::gate_compute`] before the
2889 /// overlay so the resulting slot carries `Some(_)` regardless of
2890 /// the pre-call state. Fluent chaining primitive: the peer of
2891 /// [`ProcessSpec::gate_compute_with_axis`] (fresh-spec × axis
2892 /// overlay) and [`Classification::with_axis`] (arbitrary-base ×
2893 /// axis overlay) on the ephemeral sugar surface.
2894 ///
2895 /// # Substrate ergonomics
2896 ///
2897 /// Pre-lift the four-line shape `let mut classification =
2898 /// Classification::gate_compute(); classification.<axis> =
2899 /// populated; let spec = EphemeralSpec { classification:
2900 /// Some(classification), ..ephemeral_fixture() };` (and its newer
2901 /// three-line peer `let classification =
2902 /// Classification::gate_compute_with_axis(populated); let spec =
2903 /// EphemeralSpec { classification: Some(classification),
2904 /// ..ephemeral_fixture() };`) recurred at THIRTY-SIX hand-authored
2905 /// callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger
2906 /// inside `tatara-reconciler::bin::tatara-check`'s
2907 /// `evaluate_ephemeral_require_tag_*` classifier-facing test
2908 /// module. Post-lift each callsite reads
2909 /// `let spec = ephemeral_fixture().with_classification_axis(populated);`
2910 /// — one line, one immutable binding, and every per-axis loop
2911 /// dispatches its per-iteration axis mutation through the SAME
2912 /// [`ClassificationAxis::overlay`] trait rather than by directly
2913 /// poking a `classification.<axis>` field or restating the
2914 /// `Some(_)` wrap.
2915 ///
2916 /// # Fluent chaining semantics
2917 ///
2918 /// * `EphemeralSpec { classification: None, .. }
2919 /// .with_classification_axis(axis)` produces
2920 /// `EphemeralSpec { classification:
2921 /// Some(Classification::gate_compute_with_axis(axis)), .. }` —
2922 /// the `None`-arm short-circuit fills through
2923 /// [`Classification::gate_compute`] identically to the sibling
2924 /// [`Self::resolved_classification`] resolver on the read side.
2925 /// * `EphemeralSpec { classification: Some(prior), .. }
2926 /// .with_classification_axis(axis)` produces
2927 /// `EphemeralSpec { classification: Some(prior.with_axis(axis)),
2928 /// .. }` — the axis overlay composes onto the existing carrier
2929 /// via [`ClassificationAxis::overlay`], preserving every other
2930 /// axis slot on `prior`. Chained calls
2931 /// `.with_classification_axis(a).with_classification_axis(b)`
2932 /// compose arbitrary N-axis conjunctions on the ephemeral
2933 /// sugar surface with the same order-independence guarantee
2934 /// [`Classification::with_axis`] carries on distinct-slot axes.
2935 ///
2936 /// # Sibling to [`ProcessSpec::gate_compute_with_axis`]
2937 ///
2938 /// Same (spec-carrier × axis) shape, one refinement lower on
2939 /// the composition-depth axis: `ProcessSpec::gate_compute_with_axis`
2940 /// owns the (fresh-`gate_compute_defaults`-spec × axis-overlay)
2941 /// construction on the point-surface carrier;
2942 /// [`Self::with_classification_axis`] owns the
2943 /// (arbitrary-`EphemeralSpec` × axis-overlay-onto-authored-classification)
2944 /// construction on the ephemeral sugar-surface carrier. Both
2945 /// primitives compose through the SAME
2946 /// [`ClassificationAxis::overlay`] trait so a regression on any
2947 /// axis's overlay surfaces at both composer owners' pin sets
2948 /// simultaneously.
2949 ///
2950 /// # Compounding
2951 ///
2952 /// A future SIXTH classification axis lands as ONE peer
2953 /// `impl ClassificationAxis` — every ephemeral-surface fixture
2954 /// that binds through this primitive picks up the sixth axis
2955 /// mechanically without a `classification.<new-axis> = value;`
2956 /// restatement per site. A future audit dispatcher walking the
2957 /// (ephemeral-surface × axis-loop) shape (per-axis matrix
2958 /// generator, closed-set-sweep sagas, per-axis-XOR-partition-
2959 /// witness synthesis on the ephemeral side) binds through the
2960 /// SAME composer regardless of which axis it targets. Directly
2961 /// benefits the P1 caixa-tatara renderer target
2962 /// (`(defaplicacao …)` → `Process` mechanical lowering test
2963 /// fixtures that construct authored classifications through the
2964 /// ephemeral sugar surface) and future ephemeral-surface XOR-
2965 /// partition landmark tests peer to the point-surface pins in
2966 /// `tatara-check.rs`.
2967 ///
2968 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2969 /// preserves proofs; the [`ClassificationAxis::overlay`] trait
2970 /// owns the axis-dispatch proof at ONE site and this primitive
2971 /// extends the ONE-site guarantee to the (ephemeral-spec ×
2972 /// authored-classification × axis-overlay) construction shape.
2973 /// THEORY.md §VI.1 — generation over composition; the 3-to-4-line
2974 /// hand-authored classification-then-wrap shape recurred at ≥ 36
2975 /// hand-authored callsites past the ★★ PRIME-DIRECTIVE ≥ 2
2976 /// duplication threshold and is lifted onto ONE substrate owner
2977 /// here.
2978 #[must_use]
2979 pub fn with_classification_axis<A: ClassificationAxis>(mut self, axis: A) -> Self {
2980 let mut c = self
2981 .classification
2982 .take()
2983 .unwrap_or_else(Classification::gate_compute);
2984 axis.overlay(&mut c);
2985 self.classification = Some(c);
2986 self
2987 }
2988
2989 /// True iff the resolved [`Classification`] carries the given
2990 /// [`ConvergencePointType`] on its `point_type` slot — byte-for-
2991 /// byte peer of [`Classification::has_point_type`] wrapped through
2992 /// the [`Self::resolved_classification`] resolver so an
2993 /// operator-omitted `:classification` slot reads as the
2994 /// [`default_ephemeral_class`] baseline the sibling
2995 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2996 ///
2997 /// # Two-surface parity contract
2998 ///
2999 /// A given [`EphemeralSpec`] classifies identically through this
3000 /// primitive AND through
3001 /// `<eph.clone().into::<ProcessSpec>>().classification.has_point_type(kind)`
3002 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3003 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3004 /// the lowering side both dereference the same
3005 /// `default_ephemeral_class()` value on `None` and the same
3006 /// authored value on `Some(_)`. This means the ephemeral-surface
3007 /// `point-type-<kind>` `:requires` family in
3008 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3009 /// truth on the SAME authored spec as the point-surface family
3010 /// on the mechanically-lowered `ProcessSpec`.
3011 ///
3012 /// # Sibling to the seven other classification axes
3013 ///
3014 /// FIRST classification-axis peer on the [`EphemeralSpec`]
3015 /// surface. Six future sibling axes on the SAME `Cow`-resolver
3016 /// carrier ([`Self::has_substrate`] opened the SECOND,
3017 /// [`Self::has_calm`] the THIRD,
3018 /// [`Self::has_data_classification`] the FOURTH,
3019 /// [`Self::has_horizon_kind`] the FIFTH,
3020 /// [`Self::has_optimization_direction`] the SIXTH; then
3021 /// `has_input_arity`, `has_output_arity`) land as one-line
3022 /// wrappers around the SAME resolver + the sibling
3023 /// [`Classification`] closed-set primitive, so a future variant
3024 /// added to [`ConvergencePointType`] (or any of the seven other
3025 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3026 /// families through the SAME closed-set walk with no per-caller
3027 /// edit.
3028 ///
3029 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3030 /// preserves proofs; the classification-axis presence-probe body
3031 /// composes ONE resolver primitive
3032 /// ([`Self::resolved_classification`]) with ONE closed-set
3033 /// primitive ([`Classification::has_point_type`]) so every
3034 /// downstream (`point-type-<kind>` require-tag families on both
3035 /// surfaces in tatara-check, closed-set audit dispatchers, future
3036 /// variant additions on [`ConvergencePointType`]) binds through
3037 /// the SAME `has(kind)` shape rather than restating either the
3038 /// resolver walk or the closed-set equality at the callsite.
3039 #[must_use]
3040 pub fn has_point_type(&self, kind: ConvergencePointType) -> bool {
3041 self.resolved_classification().has_point_type(kind)
3042 }
3043
3044 /// True iff the resolved [`Classification`] carries the given
3045 /// [`SubstrateType`] on its `substrate` slot — byte-for-byte peer
3046 /// of [`Classification::has_substrate`] wrapped through the
3047 /// [`Self::resolved_classification`] resolver so an operator-
3048 /// omitted `:classification` slot reads as the
3049 /// [`default_ephemeral_class`] baseline the sibling
3050 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3051 ///
3052 /// # Two-surface parity contract
3053 ///
3054 /// A given [`EphemeralSpec`] classifies identically through this
3055 /// primitive AND through
3056 /// `<eph.clone().into::<ProcessSpec>>().classification.has_substrate(kind)`
3057 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3058 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3059 /// the lowering side both dereference the same
3060 /// `default_ephemeral_class()` value on `None` and the same
3061 /// authored value on `Some(_)`. This means the ephemeral-surface
3062 /// `substrate-<kind>` `:requires` family in
3063 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3064 /// truth on the SAME authored spec as the point-surface family
3065 /// on the mechanically-lowered `ProcessSpec`.
3066 ///
3067 /// # SECOND classification-axis peer on the ephemeral surface
3068 ///
3069 /// Peer of [`Self::has_point_type`] — both route through the SAME
3070 /// [`Self::resolved_classification`] resolver, so the operator-
3071 /// omitted `:classification` slot's fill-through logic lives at
3072 /// ONE substrate primitive rather than being restated in each
3073 /// per-axis probe body. Five future sibling axes on the SAME
3074 /// `Cow`-resolver carrier ([`Self::has_calm`] opened the THIRD,
3075 /// [`Self::has_data_classification`] the FOURTH,
3076 /// [`Self::has_horizon_kind`] the FIFTH,
3077 /// [`Self::has_optimization_direction`] the SIXTH; then
3078 /// `has_input_arity`, `has_output_arity`) land as one-line
3079 /// wrappers around the SAME resolver + the sibling
3080 /// [`Classification`] closed-set primitive, so a future variant
3081 /// added to [`SubstrateType`] (or any of the six other closed
3082 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
3083 /// through the SAME closed-set walk with no per-caller edit.
3084 ///
3085 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3086 /// preserves proofs; the classification-axis presence-probe body
3087 /// composes ONE resolver primitive
3088 /// ([`Self::resolved_classification`]) with ONE closed-set
3089 /// primitive ([`Classification::has_substrate`]) so every
3090 /// downstream (`substrate-<kind>` require-tag families on both
3091 /// surfaces in tatara-check, closed-set audit dispatchers, future
3092 /// variant additions on [`SubstrateType`]) binds through the
3093 /// SAME `has(kind)` shape rather than restating either the
3094 /// resolver walk or the closed-set equality at the callsite.
3095 #[must_use]
3096 pub fn has_substrate(&self, kind: SubstrateType) -> bool {
3097 self.resolved_classification().has_substrate(kind)
3098 }
3099
3100 /// True iff the resolved [`Classification`] carries the given
3101 /// [`CalmClassification`] on its `calm` slot — byte-for-byte peer
3102 /// of [`Classification::has_calm`] wrapped through the
3103 /// [`Self::resolved_classification`] resolver so an operator-
3104 /// omitted `:classification` slot reads as the
3105 /// [`default_ephemeral_class`] baseline the sibling
3106 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3107 ///
3108 /// # Two-surface parity contract
3109 ///
3110 /// A given [`EphemeralSpec`] classifies identically through this
3111 /// primitive AND through
3112 /// `<eph.clone().into::<ProcessSpec>>().classification.has_calm(kind)`
3113 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3114 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3115 /// the lowering side both dereference the same
3116 /// `default_ephemeral_class()` value on `None` and the same
3117 /// authored value on `Some(_)`. This means the ephemeral-surface
3118 /// `calm-<kind>` `:requires` family in
3119 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3120 /// truth on the SAME authored spec as the point-surface family
3121 /// on the mechanically-lowered `ProcessSpec`.
3122 ///
3123 /// # THIRD classification-axis peer on the ephemeral surface
3124 ///
3125 /// Peer of [`Self::has_point_type`] and [`Self::has_substrate`] —
3126 /// all three route through the SAME
3127 /// [`Self::resolved_classification`] resolver, so the operator-
3128 /// omitted `:classification` slot's fill-through logic lives at
3129 /// ONE substrate primitive rather than being restated in each
3130 /// per-axis probe body. FIRST occupant on the (Option-parent ×
3131 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
3132 /// of the ephemeral-surface presence-probe algebra — distinct
3133 /// from the (Option-parent × NON-DEFAULT-scalar-child) corner
3134 /// the first two classification-axis peers opened, since
3135 /// [`CalmClassification`] carries `#[default] = Monotone` on the
3136 /// closed set. The default-arm short-circuit on the absent-
3137 /// classification arm reads `true` on the [`CalmClassification`]
3138 /// child's `#[default]` variant precisely because BOTH the parent
3139 /// Option's fill-through baseline (`default_ephemeral_class`) AND
3140 /// the child's own `#[default]` land on the SAME variant
3141 /// ([`CalmClassification::Monotone`]) — a two-defaults
3142 /// composition property distinct from the NON-DEFAULT-scalar
3143 /// peers, whose absent-classification arm defaults through a
3144 /// specific chosen baseline (`ConvergencePointType::Gate`,
3145 /// `SubstrateType::Compute`) rather than through the child's own
3146 /// `#[default]`. Four future sibling axes on the SAME
3147 /// `Cow`-resolver carrier ([`Self::has_data_classification`]
3148 /// opened the FOURTH, [`Self::has_horizon_kind`] the FIFTH,
3149 /// [`Self::has_optimization_direction`] the SIXTH; then
3150 /// `has_input_arity`, `has_output_arity`) land as one-line
3151 /// wrappers around the SAME resolver + the sibling
3152 /// [`Classification`] closed-set primitive, so a future variant
3153 /// added to [`CalmClassification`] (or any of the five other
3154 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3155 /// families through the SAME closed-set walk with no per-caller
3156 /// edit.
3157 ///
3158 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3159 /// preserves proofs; the classification-axis presence-probe body
3160 /// composes ONE resolver primitive
3161 /// ([`Self::resolved_classification`]) with ONE closed-set
3162 /// primitive ([`Classification::has_calm`]) so every downstream
3163 /// (`calm-<kind>` require-tag families on both surfaces in
3164 /// tatara-check, closed-set audit dispatchers, future variant
3165 /// additions on [`CalmClassification`]) binds through the SAME
3166 /// `has(kind)` shape rather than restating either the resolver
3167 /// walk or the closed-set equality at the callsite.
3168 #[must_use]
3169 pub fn has_calm(&self, kind: CalmClassification) -> bool {
3170 self.resolved_classification().has_calm(kind)
3171 }
3172
3173 /// True iff the resolved [`Classification`] carries the given
3174 /// [`DataClassification`] on its `data_classification` slot —
3175 /// byte-for-byte peer of [`Classification::has_data_classification`]
3176 /// wrapped through the [`Self::resolved_classification`] resolver
3177 /// so an operator-omitted `:classification` slot reads as the
3178 /// [`default_ephemeral_class`] baseline the sibling
3179 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3180 ///
3181 /// # Two-surface parity contract
3182 ///
3183 /// A given [`EphemeralSpec`] classifies identically through this
3184 /// primitive AND through
3185 /// `<eph.clone().into::<ProcessSpec>>().classification.has_data_classification(kind)`
3186 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3187 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3188 /// the lowering side both dereference the same
3189 /// `default_ephemeral_class()` value on `None` and the same
3190 /// authored value on `Some(_)`. This means the ephemeral-surface
3191 /// `data-classification-<kind>` `:requires` family in
3192 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3193 /// truth on the SAME authored spec as the point-surface family
3194 /// on the mechanically-lowered `ProcessSpec`.
3195 ///
3196 /// # FOURTH classification-axis peer on the ephemeral surface
3197 ///
3198 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`], and
3199 /// [`Self::has_calm`] — all four route through the SAME
3200 /// [`Self::resolved_classification`] resolver, so the operator-
3201 /// omitted `:classification` slot's fill-through logic lives at
3202 /// ONE substrate primitive rather than being restated in each
3203 /// per-axis probe body. SECOND occupant on the (Option-parent ×
3204 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
3205 /// of the ephemeral-surface presence-probe algebra alongside
3206 /// [`Self::has_calm`] — both probe REQUIRED [`Classification`]
3207 /// sub-slots whose child closed set carries its own `#[default]`
3208 /// ([`DataClassification::Internal`] here,
3209 /// [`CalmClassification::Monotone`] on the peer), so the
3210 /// default-arm short-circuit on the absent-classification arm
3211 /// reads `true` on the [`DataClassification`] child's
3212 /// `#[default]` variant precisely because BOTH the parent
3213 /// Option's fill-through baseline (`default_ephemeral_class`)
3214 /// AND the child's own `#[default]` land on the SAME variant
3215 /// ([`DataClassification::Internal`]). The two-defaults
3216 /// composition property now walks TWO independent defaulted-
3217 /// scalar-child slots on the SAME ephemeral resolver — a
3218 /// regression that promoted a different [`DataClassification`]
3219 /// variant to `#[default]` (or wired the arm to a fixed variant
3220 /// answer) fails HERE at ONE narrow substrate site before
3221 /// drifting through every unadorned ephemeral spec's baseline
3222 /// data-classification answer. Distinct from the FIRST + SECOND
3223 /// peers on the (Option-parent × NON-DEFAULT-scalar-child)
3224 /// corner, whose absent-classification arm defaults through a
3225 /// specific chosen baseline (`ConvergencePointType::Gate`,
3226 /// `SubstrateType::Compute`) rather than through the child's own
3227 /// `#[default]`. Four future sibling axes on the SAME
3228 /// `Cow`-resolver carrier ([`Self::has_horizon_kind`] opened the
3229 /// FIFTH, [`Self::has_optimization_direction`] the SIXTH; then
3230 /// `has_input_arity`, `has_output_arity`) land as one-line
3231 /// wrappers around the SAME resolver + the sibling
3232 /// [`Classification`] closed-set primitive, so a future variant
3233 /// added to [`DataClassification`] (or any of the four other
3234 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3235 /// families through the SAME closed-set walk with no per-caller
3236 /// edit.
3237 ///
3238 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3239 /// preserves proofs; the classification-axis presence-probe body
3240 /// composes ONE resolver primitive
3241 /// ([`Self::resolved_classification`]) with ONE closed-set
3242 /// primitive ([`Classification::has_data_classification`]) so
3243 /// every downstream (`data-classification-<kind>` require-tag
3244 /// families on both surfaces in tatara-check, closed-set audit
3245 /// dispatchers, future variant additions on
3246 /// [`DataClassification`]) binds through the SAME `has(kind)`
3247 /// shape rather than restating either the resolver walk or the
3248 /// closed-set equality at the callsite.
3249 #[must_use]
3250 pub fn has_data_classification(&self, kind: DataClassification) -> bool {
3251 self.resolved_classification().has_data_classification(kind)
3252 }
3253
3254 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
3255 /// carries the given [`HorizonKind`] discriminator on its
3256 /// `horizon.kind` slot — byte-for-byte peer of
3257 /// [`Classification::has_horizon_kind`] wrapped through the
3258 /// [`Self::resolved_classification`] resolver so an operator-
3259 /// omitted `:classification` slot reads as the
3260 /// [`default_ephemeral_class`] baseline the sibling
3261 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3262 ///
3263 /// # Two-surface parity contract
3264 ///
3265 /// A given [`EphemeralSpec`] classifies identically through this
3266 /// primitive AND through
3267 /// `<eph.clone().into::<ProcessSpec>>().classification.has_horizon_kind(kind)`
3268 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3269 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3270 /// the lowering side both dereference the same
3271 /// `default_ephemeral_class()` value on `None` and the same
3272 /// authored value on `Some(_)`. This means the ephemeral-surface
3273 /// `horizon-<kind>` `:requires` family in
3274 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3275 /// truth on the SAME authored spec as the point-surface family
3276 /// on the mechanically-lowered `ProcessSpec`.
3277 ///
3278 /// # FIFTH classification-axis peer on the ephemeral surface
3279 ///
3280 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3281 /// [`Self::has_calm`], and [`Self::has_data_classification`] — all
3282 /// five route through the SAME [`Self::resolved_classification`]
3283 /// resolver, so the operator-omitted `:classification` slot's
3284 /// fill-through logic lives at ONE substrate primitive rather
3285 /// than being restated in each per-axis probe body. OPENS a fresh
3286 /// (Option-parent × NESTED-STRUCT-scalar-child ×
3287 /// operator-resolvable-baseline) corner on the ephemeral-surface
3288 /// presence-probe algebra — the four prior peers on this surface
3289 /// all read the closed-set discriminator DIRECTLY off a scalar
3290 /// [`Classification`] slot (`point_type`, `substrate`, `calm`,
3291 /// `data_classification`); this probe instead threads through a
3292 /// NESTED-STRUCT intermediary ([`Horizon`], the defaulted nested
3293 /// struct owning the `horizon` axis) to reach a scalar
3294 /// [`HorizonKind`] discriminator on `horizon.kind`. The
3295 /// default-arm short-circuit on the absent-classification arm
3296 /// reads `true` on the [`HorizonKind`] child's `#[default]`
3297 /// variant precisely because BOTH the parent Option's fill-
3298 /// through baseline ([`default_ephemeral_class`], which fills
3299 /// `horizon: Horizon::default()`) AND the child's own `#[default]`
3300 /// land on the SAME variant ([`HorizonKind::Bounded`]). A
3301 /// regression that dropped `#[default]` on [`HorizonKind`], or
3302 /// promoted `Asymptotic` to `#[default]`, or wired the arm to a
3303 /// fixed variant answer, or crossed the wires through the wrong
3304 /// nested struct fails HERE at ONE narrow substrate site before
3305 /// drifting through every unadorned ephemeral spec's baseline
3306 /// horizon answer. Distinct from the FIRST + SECOND peers on the
3307 /// (Option-parent × NON-DEFAULT-scalar-child) corner
3308 /// (`has_point_type`, `has_substrate`) whose absent-classification
3309 /// arm defaults through a specific chosen baseline
3310 /// (`ConvergencePointType::Gate`, `SubstrateType::Compute`), AND
3311 /// distinct from the THIRD + FOURTH peers on the (Option-parent ×
3312 /// DEFAULTED-scalar-child) corner (`has_calm`,
3313 /// `has_data_classification`) which reach a defaulted scalar
3314 /// DIRECTLY off the parent without a nested-struct hop. Three
3315 /// future sibling axes on the SAME `Cow`-resolver carrier
3316 /// ([`Self::has_optimization_direction`] opened the SIXTH; then
3317 /// `has_input_arity`, `has_output_arity`) land as one-line
3318 /// wrappers around the SAME resolver + the sibling
3319 /// [`Classification`] closed-set primitive, so a future variant
3320 /// added to [`HorizonKind`] (or any of the three other closed
3321 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
3322 /// through the SAME closed-set walk with no per-caller edit.
3323 ///
3324 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3325 /// preserves proofs; the classification-axis presence-probe body
3326 /// composes ONE resolver primitive
3327 /// ([`Self::resolved_classification`]) with ONE closed-set
3328 /// primitive ([`Classification::has_horizon_kind`]) so every
3329 /// downstream (`horizon-<kind>` require-tag families on both
3330 /// surfaces in tatara-check, closed-set audit dispatchers, future
3331 /// variant additions on [`HorizonKind`]) binds through the SAME
3332 /// `has(kind)` shape rather than restating either the resolver
3333 /// walk or the closed-set equality at the callsite.
3334 #[must_use]
3335 pub fn has_horizon_kind(&self, kind: HorizonKind) -> bool {
3336 self.resolved_classification().has_horizon_kind(kind)
3337 }
3338
3339 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
3340 /// carries the given [`OptimizationDirection`] discriminator on its
3341 /// `horizon.direction` slot (with the substrate
3342 /// `Option::unwrap_or_default` treating `None` as the closed set's
3343 /// `#[default] Minimize`) — byte-for-byte peer of
3344 /// [`Classification::has_optimization_direction`] wrapped through
3345 /// the [`Self::resolved_classification`] resolver so an operator-
3346 /// omitted `:classification` slot reads as the
3347 /// [`default_ephemeral_class`] baseline the sibling
3348 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3349 ///
3350 /// # Two-surface parity contract
3351 ///
3352 /// A given [`EphemeralSpec`] classifies identically through this
3353 /// primitive AND through
3354 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
3355 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3356 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3357 /// the lowering side both dereference the same
3358 /// `default_ephemeral_class()` value on `None` and the same
3359 /// authored value on `Some(_)`, and the sibling
3360 /// [`Classification::has_optimization_direction`] applies the same
3361 /// `Option::unwrap_or_default` collapse on the inner
3362 /// `horizon.direction` slot on both sides. This means the
3363 /// ephemeral-surface `optimization-direction-<kind>` `:requires`
3364 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3365 /// SAME truth on the SAME authored spec as the point-surface
3366 /// family on the mechanically-lowered `ProcessSpec`.
3367 ///
3368 /// # SIXTH classification-axis peer on the ephemeral surface
3369 ///
3370 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3371 /// [`Self::has_calm`], [`Self::has_data_classification`], and
3372 /// [`Self::has_horizon_kind`] — all six route through the SAME
3373 /// [`Self::resolved_classification`] resolver, so the operator-
3374 /// omitted `:classification` slot's fill-through logic lives at
3375 /// ONE substrate primitive rather than being restated in each per-
3376 /// axis probe body. SECOND occupant on the (Option-parent ×
3377 /// NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
3378 /// corner alongside [`Self::has_horizon_kind`] — both probes thread
3379 /// through the SAME nested [`Horizon`] intermediary to reach a
3380 /// scalar discriminator on the six-axis classification lattice, but
3381 /// this method additionally traverses an `Option`-slot with
3382 /// `unwrap_or_default` so a Process filled through
3383 /// [`crate::classification::Horizon::default`] (leaves `direction:
3384 /// None`) still reads `true` on the closed set's default arm
3385 /// ([`OptimizationDirection::Minimize`]). The corner therefore
3386 /// admits BOTH direct nested-scalar shapes ([`Self::has_horizon_kind`]
3387 /// walks `horizon.kind: HorizonKind` directly) AND Option-nested-
3388 /// scalar shapes (this method walks `horizon.direction:
3389 /// Option<OptimizationDirection>` through `unwrap_or_default`),
3390 /// pinning the corner as a proven-repeatable primitive shape on the
3391 /// ephemeral surface rather than a single-example curiosity. The
3392 /// two-defaults composition property (parent Option's fill-through
3393 /// baseline via `default_ephemeral_class` AND child's closed-set
3394 /// `#[default]` land on the SAME variant) reaches through TWO
3395 /// hops here: the parent Option's `.unwrap_or_else(default_…)`
3396 /// AND the inner Option's `.unwrap_or_default()` both dereference
3397 /// to the same [`OptimizationDirection::Minimize`] baseline the
3398 /// closed set publishes. A regression that flipped
3399 /// [`OptimizationDirection`]'s `#[default]` off `Minimize` (which
3400 /// would silently invert every unadorned `Asymptotic` Process's
3401 /// rate-window evaluator polarity), or that dropped the resolver
3402 /// hop, or that wired the arm to a fixed variant answer, fails
3403 /// HERE at ONE narrow substrate site before drifting through every
3404 /// unadorned ephemeral spec's baseline direction answer. Two future
3405 /// sibling axes on the SAME `Cow`-resolver carrier
3406 /// (`has_input_arity`, `has_output_arity`) land as one-line
3407 /// wrappers around the SAME resolver + the sibling
3408 /// [`Classification`] closed-set primitive, so a future variant
3409 /// added to [`OptimizationDirection`] (or any of the two other
3410 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3411 /// families through the SAME closed-set walk with no per-caller
3412 /// edit.
3413 ///
3414 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3415 /// preserves proofs; the classification-axis presence-probe body
3416 /// composes ONE resolver primitive
3417 /// ([`Self::resolved_classification`]) with ONE closed-set
3418 /// primitive ([`Classification::has_optimization_direction`]) so
3419 /// every downstream (`optimization-direction-<kind>` require-tag
3420 /// families on both surfaces in tatara-check, closed-set audit
3421 /// dispatchers, future variant additions on
3422 /// [`OptimizationDirection`]) binds through the SAME `has(kind)`
3423 /// shape rather than restating either the resolver walk or the
3424 /// closed-set equality plus the nested-struct-Option-hop at the
3425 /// callsite.
3426 #[must_use]
3427 pub fn has_optimization_direction(&self, kind: OptimizationDirection) -> bool {
3428 self.resolved_classification()
3429 .has_optimization_direction(kind)
3430 }
3431
3432 /// True iff the resolved [`Classification`]'s nested
3433 /// [`ConvergencePointType`] projects (via the many-to-one
3434 /// [`ConvergencePointType::input_arity`] typed projection) to the
3435 /// given [`Arity`] discriminator — byte-for-byte peer of
3436 /// [`Classification::has_input_arity`] wrapped through the
3437 /// [`Self::resolved_classification`] resolver so an operator-omitted
3438 /// `:classification` slot reads as the [`default_ephemeral_class`]
3439 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
3440 /// lowering fills.
3441 ///
3442 /// # Two-surface parity contract
3443 ///
3444 /// A given [`EphemeralSpec`] classifies identically through this
3445 /// primitive AND through
3446 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
3447 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3448 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
3449 /// lowering side both dereference the same
3450 /// `default_ephemeral_class()` value on `None` and the same
3451 /// authored value on `Some(_)`, and the sibling
3452 /// [`Classification::has_input_arity`] applies the same
3453 /// `point_type.input_arity()` typed projection on both sides. This
3454 /// means the ephemeral-surface `input-arity-<kind>` `:requires`
3455 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3456 /// SAME truth on the SAME authored spec as the point-surface family
3457 /// on the mechanically-lowered `ProcessSpec`.
3458 ///
3459 /// # SEVENTH classification-axis peer on the ephemeral surface — first via a derived-typed-projection
3460 ///
3461 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3462 /// [`Self::has_calm`], [`Self::has_data_classification`],
3463 /// [`Self::has_horizon_kind`], and
3464 /// [`Self::has_optimization_direction`] — all seven route through
3465 /// the SAME [`Self::resolved_classification`] resolver, so the
3466 /// operator-omitted `:classification` slot's fill-through logic
3467 /// lives at ONE substrate primitive rather than being restated in
3468 /// each per-axis probe body. FIRST occupant on the (Option-parent ×
3469 /// NESTED-STRUCT-scalar-child × derived-typed-projection) corner on
3470 /// the ephemeral surface — byte-for-byte symmetric with the
3471 /// derived-typed-projection precedent set by
3472 /// [`Classification::has_input_arity`] on the point surface: THAT
3473 /// peer routes through [`ConvergencePointType::input_arity`] on a
3474 /// required [`Classification`] carrier; THIS peer routes through the
3475 /// SAME projection on the `Cow`-resolver carrier so the resolver
3476 /// walk composes with the projection at ONE substrate site rather
3477 /// than being restated per surface. Distinct from the SIXTH peer
3478 /// [`Self::has_optimization_direction`] (which walks
3479 /// `horizon.direction` through an `Option::unwrap_or_default`
3480 /// collapse to reach a defaulted scalar child) and the FIFTH peer
3481 /// [`Self::has_horizon_kind`] (which walks `horizon.kind` DIRECTLY
3482 /// as a scalar without any typed-projection hop) on ONE dimension:
3483 /// this probe threads through the many-to-one closed-set typed
3484 /// projection [`ConvergencePointType::input_arity`] (`Transform |
3485 /// Fork | Broadcast | Observe → One`, `Join | Gate | Select |
3486 /// Reduce → Many`) so the child's closed set ([`Arity`]) is REACHED
3487 /// THROUGH a projection layer, not read raw off a scalar. The
3488 /// corner therefore admits three ephemeral-surface traversal
3489 /// shapes through the SAME `resolved_classification().<field>`
3490 /// walk: direct-nested-scalar
3491 /// ([`Self::has_horizon_kind`] reads `horizon.kind: HorizonKind`
3492 /// directly), Option-nested-scalar
3493 /// ([`Self::has_optimization_direction`] reads `horizon.direction:
3494 /// Option<OptimizationDirection>` through `unwrap_or_default`), and
3495 /// derived-typed-projection (this method reads
3496 /// `point_type.input_arity(): Arity` through a many-to-one
3497 /// projection). The co-tenant derived-typed-projection axis on the
3498 /// SAME `Cow`-resolver carrier ([`Self::has_output_arity`]) lands as
3499 /// a one-line wrapper around the SAME resolver + the sibling
3500 /// [`Classification`] closed-set primitive, so a future variant
3501 /// added to [`Arity`] or to [`ConvergencePointType`] reaches BOTH
3502 /// surfaces' `<axis>-<kind>` prefix families through the SAME
3503 /// closed-set walk with no per-caller edit.
3504 ///
3505 /// # Semantics — VARIANT match on the projected image
3506 ///
3507 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
3508 /// `#[default]`), so exactly ONE of the two arms answers `true` per
3509 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
3510 /// shortcut. The absent-`:classification` baseline
3511 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
3512 /// [`ConvergencePointType::input_arity`] projects `Gate → Many`, so
3513 /// the ephemeral sugar surface's `input-arity-Many` require-tag
3514 /// reads `true` on every operator-authored spec that omits the
3515 /// `:classification` slot — pinning the workspace's convergent-by-
3516 /// default point posture on the input side. The many-to-one
3517 /// projection shape means the answer is invariant under intra-
3518 /// bucket point-type swaps (`Transform ↔ Fork ↔ Broadcast ↔
3519 /// Observe` all keep `input-arity-One = true`) and flips at bucket
3520 /// boundaries (`Transform ↔ Join` flips `input-arity-One` from
3521 /// `true` to `false`). A regression that dropped the resolver hop,
3522 /// probed [`ConvergencePointType`] directly (dropping the
3523 /// `.input_arity()` call), inverted the projection (`One ↔ Many`),
3524 /// or crossed the wires with the sibling
3525 /// [`ConvergencePointType::output_arity`] projection fails HERE at
3526 /// ONE narrow substrate site before drifting through every
3527 /// unadorned ephemeral spec's baseline input-arity answer.
3528 ///
3529 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3530 /// preserves proofs; the classification-axis presence-probe body
3531 /// composes ONE resolver primitive
3532 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
3533 /// ([`Classification::has_input_arity`]) so every downstream
3534 /// (`input-arity-<kind>` require-tag families on both surfaces in
3535 /// tatara-check, closed-set audit dispatchers, future variant
3536 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
3537 /// through the SAME `has(kind)` shape rather than restating either
3538 /// the resolver walk or the closed-set equality plus the typed-
3539 /// projection hop at the callsite.
3540 #[must_use]
3541 pub fn has_input_arity(&self, kind: Arity) -> bool {
3542 self.resolved_classification().has_input_arity(kind)
3543 }
3544
3545 /// True iff the resolved [`Classification`]'s nested
3546 /// [`ConvergencePointType`] projects (via the many-to-one
3547 /// [`ConvergencePointType::output_arity`] typed projection) to the
3548 /// given [`Arity`] discriminator — byte-for-byte peer of
3549 /// [`Classification::has_output_arity`] wrapped through the
3550 /// [`Self::resolved_classification`] resolver so an operator-omitted
3551 /// `:classification` slot reads as the [`default_ephemeral_class`]
3552 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
3553 /// lowering fills.
3554 ///
3555 /// # Two-surface parity contract
3556 ///
3557 /// A given [`EphemeralSpec`] classifies identically through this
3558 /// primitive AND through
3559 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
3560 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3561 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
3562 /// lowering side both dereference the same
3563 /// `default_ephemeral_class()` value on `None` and the same
3564 /// authored value on `Some(_)`, and the sibling
3565 /// [`Classification::has_output_arity`] applies the same
3566 /// `point_type.output_arity()` typed projection on both sides. This
3567 /// means the ephemeral-surface `output-arity-<kind>` `:requires`
3568 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3569 /// SAME truth on the SAME authored spec as the point-surface family
3570 /// on the mechanically-lowered `ProcessSpec`.
3571 ///
3572 /// # EIGHTH classification-axis peer — closes the ephemeral-side DAG-composition arity pair
3573 ///
3574 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3575 /// [`Self::has_calm`], [`Self::has_data_classification`],
3576 /// [`Self::has_horizon_kind`], [`Self::has_optimization_direction`],
3577 /// and [`Self::has_input_arity`] — all eight route through the SAME
3578 /// [`Self::resolved_classification`] resolver, so the operator-
3579 /// omitted `:classification` slot's fill-through logic lives at ONE
3580 /// substrate primitive rather than being restated in each per-axis
3581 /// probe body. SECOND occupant on the (Option-parent × NESTED-
3582 /// STRUCT-scalar-child × derived-typed-projection) corner on the
3583 /// ephemeral surface — co-tenant with [`Self::has_input_arity`] on
3584 /// the SAME `point_type` scalar carrier through the SAME [`Arity`]
3585 /// closed set but through the sibling many-to-one typed projection
3586 /// [`ConvergencePointType::output_arity`] (`Transform | Join | Gate
3587 /// | Select | Reduce | Observe → One`, `Fork | Broadcast → Many`).
3588 /// Closes the DAG-composition arity pair on the ephemeral side —
3589 /// the two projections DISAGREE on the diffusive arms `Fork |
3590 /// Broadcast` (input `One` vs. output `Many`) and on the convergent
3591 /// arms `Join | Gate | Select | Reduce` (input `Many` vs. output
3592 /// `One`), and AGREE on the endomorphic arms `Transform | Observe`
3593 /// (both `One`). Byte-for-byte symmetric with the DAG-composition
3594 /// arity pair on the point surface ([`Classification::has_input_arity`] +
3595 /// [`Classification::has_output_arity`]) — THAT pair walks a required
3596 /// [`Classification`] carrier; THIS pair walks the SAME projection
3597 /// pair on the `Cow`-resolver carrier so the resolver walk composes
3598 /// with the projection at ONE substrate site rather than being
3599 /// restated per surface.
3600 ///
3601 /// # Semantics — VARIANT match on the projected image
3602 ///
3603 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
3604 /// `#[default]`), so exactly ONE of the two arms answers `true` per
3605 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
3606 /// shortcut. The absent-`:classification` baseline
3607 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
3608 /// [`ConvergencePointType::output_arity`] projects `Gate → One`, so
3609 /// the ephemeral sugar surface's `output-arity-One` require-tag
3610 /// reads `true` on every operator-authored spec that omits the
3611 /// `:classification` slot — pinning the workspace's convergent-by-
3612 /// default point posture on the output side. The many-to-one
3613 /// projection shape means the answer is invariant under intra-
3614 /// bucket point-type swaps (`Fork ↔ Broadcast` both keep
3615 /// `output-arity-Many = true`; `Transform ↔ Join ↔ Gate ↔ Select ↔
3616 /// Reduce ↔ Observe` all keep `output-arity-One = true`) and flips
3617 /// at bucket boundaries (`Fork ↔ Transform` flips `output-arity-
3618 /// Many` from `true` to `false`). A regression that dropped the
3619 /// resolver hop, probed [`ConvergencePointType`] directly (dropping
3620 /// the `.output_arity()` call), inverted the projection (`One ↔
3621 /// Many`), or crossed the wires with the sibling
3622 /// [`ConvergencePointType::input_arity`] projection fails HERE at
3623 /// ONE narrow substrate site before drifting through every
3624 /// unadorned ephemeral spec's baseline output-arity answer.
3625 ///
3626 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3627 /// preserves proofs; the classification-axis presence-probe body
3628 /// composes ONE resolver primitive
3629 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
3630 /// ([`Classification::has_output_arity`]) so every downstream
3631 /// (`output-arity-<kind>` require-tag families on both surfaces in
3632 /// tatara-check, closed-set audit dispatchers, future variant
3633 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
3634 /// through the SAME `has(kind)` shape rather than restating either
3635 /// the resolver walk or the closed-set equality plus the typed-
3636 /// projection hop at the callsite.
3637 #[must_use]
3638 pub fn has_output_arity(&self, kind: Arity) -> bool {
3639 self.resolved_classification().has_output_arity(kind)
3640 }
3641
3642 /// Derived-boolean predicate — does this ephemeral spec's
3643 /// resolved [`Classification`]'s [`Horizon`] project to `true`
3644 /// under [`crate::classification::HorizonKind::terminates`]?
3645 /// Byte-for-byte peer of
3646 /// [`Classification::horizon_terminates`] wrapped through the
3647 /// [`Self::resolved_classification`] resolver so an operator-
3648 /// omitted `:classification` slot on `(defephemeral …)` still
3649 /// answers via the substrate default. The ONE ephemeral-surface
3650 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3651 /// derived-nullary-boolean walk on the classification-horizon
3652 /// axis.
3653 ///
3654 /// # Two-surface parity — resolver hop + Classification primitive
3655 ///
3656 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3657 /// [`Self::has_calm`], [`Self::has_data_classification`],
3658 /// [`Self::has_horizon_kind`],
3659 /// [`Self::has_optimization_direction`],
3660 /// [`Self::has_input_arity`], and [`Self::has_output_arity`] on
3661 /// the (resolver-hop × [`Classification`] presence primitive)
3662 /// axis: all nine methods route through the SAME
3663 /// [`Self::resolved_classification`] resolver, and each composes
3664 /// against ONE [`Classification`] primitive. This method
3665 /// distinguishes itself by targeting the [`Classification`]
3666 /// primitive [`Classification::horizon_terminates`] which is the
3667 /// FIRST derived-nullary-boolean (no closed-set argument)
3668 /// primitive on the [`Classification`] surface — every prior
3669 /// peer probe on [`Classification`] admits a closed-set `kind`
3670 /// argument and answers a variant-equality question, while this
3671 /// probe collapses [`HorizonKind::ALL`] onto a single boolean
3672 /// via the closed set's own [`HorizonKind::terminates`]
3673 /// predicate.
3674 ///
3675 /// # Semantics — resolver hop + derived-nullary-boolean
3676 ///
3677 /// `horizon_terminates()` returns `true` iff
3678 /// `self.resolved_classification().horizon_terminates()`. The
3679 /// resolver returns the authored [`Classification`] when
3680 /// present and the substrate default
3681 /// [`Classification::gate_compute`] on absence. Because
3682 /// [`Classification::gate_compute`] uses [`Horizon::default`]
3683 /// (whose `kind` field defaults to [`HorizonKind::Bounded`] via
3684 /// `#[default]`), a bare ephemeral spec with no `:classification`
3685 /// slot answers `true` — the default-arm short-circuit
3686 /// propagates through THREE layers of `Default`
3687 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
3688 /// [`HorizonKind::default`]) to this predicate's answer, matching
3689 /// the default-arm shortcut every prior defaulted-child probe
3690 /// on this surface publishes. A regression that dropped the
3691 /// resolver hop, probed [`Classification::has_horizon_kind`]
3692 /// directly (dropping the `.terminates()` projection), or
3693 /// crossed the wires with the antisymmetric partner
3694 /// [`HorizonKind::requires_metric_axes`] fails HERE at ONE
3695 /// narrow substrate site before drifting through every
3696 /// unadorned ephemeral spec's baseline horizon-terminates
3697 /// answer.
3698 ///
3699 /// # Compounding
3700 ///
3701 /// The ephemeral require-tag classifier composes this primitive
3702 /// as a fixed tag `terminating-horizon` on
3703 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3704 /// surface's `terminating-horizon` fixed tag on
3705 /// `POINT_FIXED_TAG_ARMS` via [`Classification::horizon_terminates`]
3706 /// directly. The two-surface parity contract holds by
3707 /// construction: both surfaces route through the SAME
3708 /// [`Classification::horizon_terminates`] primitive after the
3709 /// ephemeral surface pays ONE resolver hop — a future
3710 /// [`HorizonKind`] variant or a future normalization at the
3711 /// substrate primitive lands at ONE site and both surfaces'
3712 /// `terminating-horizon` fixed tags inherit the shift
3713 /// mechanically. A future co-tenant peer on this surface (a
3714 /// hypothetical `horizon_requires_metric_axes` composing the
3715 /// antisymmetric partner [`HorizonKind::requires_metric_axes`]
3716 /// through the SAME resolver hop) lands as ONE peer inherent
3717 /// method with the same nullary-derived body.
3718 ///
3719 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3720 /// preserves proofs; the classification-axis derived-nullary-
3721 /// boolean probe body composes ONE resolver primitive
3722 /// ([`Self::resolved_classification`]) with ONE
3723 /// [`Classification`] primitive
3724 /// ([`Classification::horizon_terminates`]) so every downstream
3725 /// (`terminating-horizon` fixed tags on both surfaces in
3726 /// tatara-check, future scheduler / termination-shape
3727 /// validators, future variant additions on [`HorizonKind`])
3728 /// binds through the SAME `horizon_terminates()` shape rather
3729 /// than restating either the resolver walk or the closed-set
3730 /// projection composition at the callsite. THEORY.md §VI.1 —
3731 /// generation over composition; a future [`HorizonKind`]
3732 /// variant lands at ONE `ALL` entry + ONE `terminates` arm on
3733 /// the closed set and both surfaces pick it up mechanically.
3734 #[must_use]
3735 pub fn horizon_terminates(&self) -> bool {
3736 self.resolved_classification().horizon_terminates()
3737 }
3738
3739 /// Derived-boolean predicate — does this ephemeral spec's
3740 /// resolved [`Classification`]'s [`Horizon`] project to `true`
3741 /// under [`crate::classification::HorizonKind::requires_metric_axes`]?
3742 /// Byte-for-byte peer of
3743 /// [`Classification::horizon_requires_metric_axes`] wrapped
3744 /// through the [`Self::resolved_classification`] resolver so an
3745 /// operator-omitted `:classification` slot on `(defephemeral …)`
3746 /// still answers via the substrate default. The ONE ephemeral-
3747 /// surface substrate primitive that owns the
3748 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on
3749 /// the metric-axes-required question over the classification-
3750 /// horizon axis.
3751 ///
3752 /// # Antisymmetric peer of [`Self::horizon_terminates`]
3753 ///
3754 /// Byte-for-byte antisymmetric peer of [`Self::horizon_terminates`]
3755 /// via the SAME [`Self::resolved_classification`] resolver hop
3756 /// and the SAME closed set [`crate::classification::HorizonKind`]:
3757 /// [`Self::horizon_terminates`] composes
3758 /// [`Classification::horizon_terminates`] (walking
3759 /// [`crate::classification::HorizonKind::terminates`]); this
3760 /// method composes the ANTISYMMETRIC partner
3761 /// [`Classification::horizon_requires_metric_axes`] (walking
3762 /// [`crate::classification::HorizonKind::requires_metric_axes`]).
3763 /// The closed set pins the XOR contract
3764 /// `terminates() ^ requires_metric_axes()` on every variant, so
3765 /// exactly ONE of these two ephemeral-surface derived-nullary
3766 /// probes answers `true` per resolved [`Classification`] and the
3767 /// two probes together partition the resolver's output space into
3768 /// two disjoint buckets on every ephemeral spec — authored or
3769 /// defaulted.
3770 ///
3771 /// # Semantics — resolver hop + derived-nullary-boolean
3772 ///
3773 /// `horizon_requires_metric_axes()` returns `true` iff
3774 /// `self.resolved_classification().horizon_requires_metric_axes()`.
3775 /// The resolver returns the authored [`Classification`] when
3776 /// present and the substrate default
3777 /// [`Classification::gate_compute`] on absence. Because
3778 /// [`Classification::gate_compute`] uses [`Horizon::default`]
3779 /// (whose `kind` field defaults to
3780 /// [`crate::classification::HorizonKind::Bounded`] via
3781 /// `#[default]`), a bare ephemeral spec with no `:classification`
3782 /// slot answers `false` — the default-arm short-circuit
3783 /// propagates through THREE layers of `Default`
3784 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
3785 /// [`crate::classification::HorizonKind::default`]) to this
3786 /// predicate's answer, the mirror image of
3787 /// [`Self::horizon_terminates`]'s default-arm `true` answer. A
3788 /// regression that dropped the resolver hop, probed
3789 /// [`Classification::has_horizon_kind`] directly (dropping the
3790 /// `.requires_metric_axes()` projection), or crossed the wires
3791 /// with the antisymmetric partner
3792 /// [`crate::classification::HorizonKind::terminates`] fails HERE
3793 /// at ONE narrow substrate site before drifting through every
3794 /// unadorned ephemeral spec's baseline metric-provisioning
3795 /// answer.
3796 ///
3797 /// # Compounding
3798 ///
3799 /// The ephemeral require-tag classifier composes this primitive
3800 /// as a fixed tag `metric-axes-required` on
3801 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3802 /// surface's `metric-axes-required` fixed tag on
3803 /// `POINT_FIXED_TAG_ARMS` via
3804 /// [`Classification::horizon_requires_metric_axes`] directly. The
3805 /// two-surface parity contract holds by construction: both
3806 /// surfaces route through the SAME
3807 /// [`Classification::horizon_requires_metric_axes`] primitive
3808 /// after the ephemeral surface pays ONE resolver hop — a future
3809 /// [`crate::classification::HorizonKind`] variant or a future
3810 /// normalization at the substrate primitive lands at ONE site and
3811 /// both surfaces' `metric-axes-required` fixed tags inherit the
3812 /// shift mechanically.
3813 ///
3814 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3815 /// preserves proofs; the classification-axis derived-nullary-
3816 /// boolean probe body composes ONE resolver primitive
3817 /// ([`Self::resolved_classification`]) with ONE
3818 /// [`Classification`] primitive
3819 /// ([`Classification::horizon_requires_metric_axes`]) so every
3820 /// downstream (`metric-axes-required` fixed tags on both
3821 /// surfaces in tatara-check, future scheduler / metric-
3822 /// provisioning validators, future variant additions on
3823 /// [`crate::classification::HorizonKind`]) binds through the
3824 /// SAME `horizon_requires_metric_axes()` shape rather than
3825 /// restating either the resolver walk or the closed-set
3826 /// projection composition at the callsite. THEORY.md §VI.1 —
3827 /// generation over composition; a future
3828 /// [`crate::classification::HorizonKind`] variant lands at ONE
3829 /// `ALL` entry + ONE `requires_metric_axes` arm on the closed
3830 /// set and both surfaces pick it up mechanically.
3831 #[must_use]
3832 pub fn horizon_requires_metric_axes(&self) -> bool {
3833 self.resolved_classification()
3834 .horizon_requires_metric_axes()
3835 }
3836
3837 /// Derived-boolean predicate — does this ephemeral spec's
3838 /// resolved [`Classification`]'s [`crate::classification::CalmClassification`]
3839 /// project to `true` under
3840 /// [`crate::classification::CalmClassification::requires_coordination`]?
3841 /// Byte-for-byte peer of
3842 /// [`Classification::calm_requires_coordination`] wrapped through
3843 /// the [`Self::resolved_classification`] resolver so an operator-
3844 /// omitted `:classification` slot on `(defephemeral …)` still
3845 /// answers via the substrate default. The ONE ephemeral-surface
3846 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3847 /// derived-nullary-boolean walk on the coordination-required
3848 /// question over the classification-calm axis.
3849 ///
3850 /// # Third derived-nullary-boolean peer on the ephemeral surface
3851 ///
3852 /// Peer of [`Self::horizon_terminates`] and
3853 /// [`Self::horizon_requires_metric_axes`] on the ephemeral
3854 /// surface's (resolver-hop × derived-nullary-bool) shape — the
3855 /// FIRST peer threading the classification-calm axis rather than
3856 /// the classification-horizon axis. Distinct from both prior
3857 /// derived-nullary peers by ONE structural degree at the underlying
3858 /// [`Classification`] primitive: [`Self::horizon_terminates`] +
3859 /// [`Self::horizon_requires_metric_axes`] both walk the nested
3860 /// `.horizon.kind` sub-slot's derived projection, while this probe
3861 /// walks the direct scalar `.calm` field's derived projection.
3862 /// The resolver-hop shape is byte-identical.
3863 ///
3864 /// # Semantics — resolver hop + derived-nullary-boolean
3865 ///
3866 /// `calm_requires_coordination()` returns `true` iff
3867 /// `self.resolved_classification().calm_requires_coordination()`.
3868 /// The resolver returns the authored [`Classification`] when
3869 /// present and the substrate default
3870 /// [`Classification::gate_compute`] on absence. Because
3871 /// [`Classification::gate_compute`] carries
3872 /// [`crate::classification::CalmClassification::default = Monotone`],
3873 /// a bare ephemeral spec with no `:classification` slot answers
3874 /// `false` — the default-arm short-circuit propagates through TWO
3875 /// layers of `Default` ([`Classification::gate_compute`] →
3876 /// [`crate::classification::CalmClassification::default`]) to this
3877 /// predicate's answer. Distinct from the two `horizon_*` peers on
3878 /// this surface, which short-circuit through THREE layers of
3879 /// `Default` ([`Classification::gate_compute`] → [`Horizon::default`]
3880 /// → [`HorizonKind::default`]) because the horizon axis has a
3881 /// nested-struct wrapper between the classification field and the
3882 /// closed-set discriminator. A regression that dropped the
3883 /// resolver hop, probed [`Classification::has_calm`] directly
3884 /// (dropping the `.requires_coordination()` projection), or
3885 /// inverted the projection (silently promoting the Monotone
3886 /// baseline to "requires coordination") fails HERE at ONE narrow
3887 /// substrate site before drifting through every unadorned
3888 /// ephemeral spec's baseline coordination-mode answer.
3889 ///
3890 /// # Compounding
3891 ///
3892 /// The ephemeral require-tag classifier composes this primitive
3893 /// as a fixed tag `coordination-required` on
3894 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3895 /// surface's `coordination-required` fixed tag on
3896 /// `POINT_FIXED_TAG_ARMS` via
3897 /// [`Classification::calm_requires_coordination`] directly. The
3898 /// two-surface parity contract holds by construction: both
3899 /// surfaces route through the SAME
3900 /// [`Classification::calm_requires_coordination`] primitive after
3901 /// the ephemeral surface pays ONE resolver hop — a future
3902 /// [`crate::classification::CalmClassification`] variant or a
3903 /// future normalization at the substrate primitive lands at ONE
3904 /// site and both surfaces' `coordination-required` fixed tags
3905 /// inherit the shift mechanically.
3906 ///
3907 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3908 /// preserves proofs; the classification-axis derived-nullary-
3909 /// boolean probe body composes ONE resolver primitive
3910 /// ([`Self::resolved_classification`]) with ONE
3911 /// [`Classification`] primitive
3912 /// ([`Classification::calm_requires_coordination`]) so every
3913 /// downstream (`coordination-required` fixed tags on both
3914 /// surfaces in tatara-check, future scheduler / coordination-mode
3915 /// validators, future variant additions on
3916 /// [`crate::classification::CalmClassification`]) binds through
3917 /// the SAME `calm_requires_coordination()` shape rather than
3918 /// restating either the resolver walk or the closed-set
3919 /// projection composition at the callsite. THEORY.md §VI.1 —
3920 /// generation over composition; a future
3921 /// [`crate::classification::CalmClassification`] variant lands at
3922 /// ONE `ALL` entry + ONE `requires_coordination` arm on the
3923 /// closed set and both surfaces pick it up mechanically.
3924 #[must_use]
3925 pub fn calm_requires_coordination(&self) -> bool {
3926 self.resolved_classification().calm_requires_coordination()
3927 }
3928
3929 /// Derived-boolean predicate — does this ephemeral spec's
3930 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
3931 /// project to `true` under
3932 /// [`crate::classification::DataClassification::is_regulated`]?
3933 /// Byte-for-byte peer of
3934 /// [`Classification::data_is_regulated`] wrapped through the
3935 /// [`Self::resolved_classification`] resolver so an operator-
3936 /// omitted `:classification` slot on `(defephemeral …)` still
3937 /// answers via the substrate default. The ONE ephemeral-surface
3938 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3939 /// derived-nullary-boolean walk on the regulated-data question
3940 /// over the classification-data axis.
3941 ///
3942 /// # Fourth derived-nullary-boolean peer on the ephemeral surface
3943 ///
3944 /// Peer of [`Self::horizon_terminates`],
3945 /// [`Self::horizon_requires_metric_axes`], and
3946 /// [`Self::calm_requires_coordination`] on the ephemeral surface's
3947 /// (resolver-hop × derived-nullary-bool) shape — the FIRST peer
3948 /// threading the classification-data axis rather than the horizon
3949 /// or calm axes. Structural byte-for-byte peer of
3950 /// [`Self::calm_requires_coordination`]: both walk a DIRECT scalar
3951 /// closed-set field's derived projection on the resolved
3952 /// [`Classification`] (`.calm.requires_coordination()` /
3953 /// `.data_classification.is_regulated()`) — TWO layers of
3954 /// `Default` short-circuit ([`Classification::gate_compute`] →
3955 /// the direct scalar child's `#[default]`) — distinct from the
3956 /// two `horizon_*` peers which walk a NESTED-STRUCT projection
3957 /// (`.horizon.kind`) with THREE layers of `Default`. The resolver-
3958 /// hop shape is byte-identical across all four peers.
3959 ///
3960 /// # Semantics — resolver hop + derived-nullary-boolean
3961 ///
3962 /// `data_is_regulated()` returns `true` iff
3963 /// `self.resolved_classification().data_is_regulated()`. The
3964 /// resolver returns the authored [`Classification`] when present
3965 /// and the substrate default [`Classification::gate_compute`] on
3966 /// absence. Because [`Classification::gate_compute`] carries
3967 /// [`crate::classification::DataClassification::default = Internal`],
3968 /// a bare ephemeral spec with no `:classification` slot answers
3969 /// `false` — the default-arm short-circuit propagates through TWO
3970 /// layers of `Default` ([`Classification::gate_compute`] →
3971 /// [`crate::classification::DataClassification::default`]) to
3972 /// this predicate's answer, mirror-image of
3973 /// [`Self::calm_requires_coordination`]'s Monotone-default
3974 /// short-circuit through the same structural depth. Distinct
3975 /// from the two `horizon_*` peers on this surface which short-
3976 /// circuit through THREE layers of `Default` because the horizon
3977 /// axis has a nested-struct wrapper. A regression that dropped
3978 /// the resolver hop, probed [`Classification::has_data_classification`]
3979 /// directly (dropping the `.is_regulated()` projection), or
3980 /// inverted the projection (silently promoting the Internal
3981 /// baseline to "regulated") fails HERE at ONE narrow substrate
3982 /// site before drifting through every unadorned ephemeral spec's
3983 /// baseline regulatory-regime answer.
3984 ///
3985 /// # Compounding
3986 ///
3987 /// The ephemeral require-tag classifier composes this primitive
3988 /// as a fixed tag `data-regulated` on `EPHEMERAL_FIXED_TAG_ARMS`
3989 /// — byte-for-byte peer of the point surface's `data-regulated`
3990 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3991 /// [`Classification::data_is_regulated`] directly. The two-
3992 /// surface parity contract holds by construction: both surfaces
3993 /// route through the SAME
3994 /// [`Classification::data_is_regulated`] primitive after the
3995 /// ephemeral surface pays ONE resolver hop — a future
3996 /// [`crate::classification::DataClassification`] variant or a
3997 /// future normalization at the substrate primitive lands at ONE
3998 /// site and both surfaces' `data-regulated` fixed tags inherit
3999 /// the shift mechanically.
4000 ///
4001 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4002 /// preserves proofs; the classification-data-axis derived-nullary-
4003 /// boolean probe body composes ONE resolver primitive
4004 /// ([`Self::resolved_classification`]) with ONE
4005 /// [`Classification`] primitive
4006 /// ([`Classification::data_is_regulated`]) so every downstream
4007 /// (`data-regulated` fixed tags on both surfaces in tatara-check,
4008 /// future compliance-baseline / regulatory-regime validators,
4009 /// future variant additions on
4010 /// [`crate::classification::DataClassification`]) binds through
4011 /// the SAME `data_is_regulated()` shape rather than restating
4012 /// either the resolver walk or the closed-set projection
4013 /// composition at the callsite. THEORY.md §VI.1 — generation
4014 /// over composition; a future
4015 /// [`crate::classification::DataClassification`] variant lands
4016 /// at ONE `ALL` entry + ONE `is_regulated` arm on the closed set
4017 /// and both surfaces pick it up mechanically.
4018 #[must_use]
4019 pub fn data_is_regulated(&self) -> bool {
4020 self.resolved_classification().data_is_regulated()
4021 }
4022
4023 /// Derived-boolean predicate — does this ephemeral spec's
4024 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
4025 /// project to `true` under
4026 /// [`crate::classification::DataClassification::is_restricted`]?
4027 /// Byte-for-byte peer of
4028 /// [`Classification::data_is_restricted`] wrapped through the
4029 /// [`Self::resolved_classification`] resolver so an operator-
4030 /// omitted `:classification` slot on `(defephemeral …)` still
4031 /// answers via the substrate default. The ONE ephemeral-surface
4032 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4033 /// derived-nullary-boolean walk on the restricted-data question
4034 /// over the classification-data axis.
4035 ///
4036 /// # Fifth derived-nullary-boolean peer on the ephemeral surface
4037 ///
4038 /// Peer of [`Self::horizon_terminates`],
4039 /// [`Self::horizon_requires_metric_axes`],
4040 /// [`Self::calm_requires_coordination`], and
4041 /// [`Self::data_is_regulated`] on the ephemeral surface's
4042 /// (resolver-hop × derived-nullary-bool) shape — the SECOND peer
4043 /// threading the classification-data axis after
4044 /// [`Self::data_is_regulated`] opened it, pinning the data axis
4045 /// as a proven-repeatable structural sub-corner across TWO sibling
4046 /// closed-set projections (`is_regulated` / `is_restricted`).
4047 /// Structural byte-for-byte peer of
4048 /// [`Self::data_is_regulated`]: both walk the SAME DIRECT scalar
4049 /// closed-set field's derived projection on the resolved
4050 /// [`Classification`] (`.data_classification.is_regulated()` /
4051 /// `.is_restricted()`) — TWO layers of `Default` short-circuit
4052 /// ([`Classification::gate_compute`] → [`crate::classification::DataClassification::default = Internal`])
4053 /// — distinct from the two `horizon_*` peers which walk a NESTED-
4054 /// STRUCT projection (`.horizon.kind`) with THREE layers of
4055 /// `Default`. The resolver-hop shape is byte-identical across all
4056 /// five peers.
4057 ///
4058 /// # Semantics — resolver hop + derived-nullary-boolean
4059 ///
4060 /// `data_is_restricted()` returns `true` iff
4061 /// `self.resolved_classification().data_is_restricted()`. The
4062 /// resolver returns the authored [`Classification`] when present
4063 /// and the substrate default [`Classification::gate_compute`] on
4064 /// absence. Because [`Classification::gate_compute`] carries
4065 /// [`crate::classification::DataClassification::default = Internal`],
4066 /// a bare ephemeral spec with no `:classification` slot answers
4067 /// `true` — the default-arm short-circuit propagates through TWO
4068 /// layers of `Default` ([`Classification::gate_compute`] →
4069 /// [`crate::classification::DataClassification::default`]) to
4070 /// this predicate's answer. FIRST direct-scalar ephemeral-surface
4071 /// peer whose absent-classification default answers `true`, not
4072 /// `false` (`data_is_regulated` and `calm_requires_coordination`
4073 /// both project `false` on the same absent classification),
4074 /// mirror-image of [`Self::horizon_terminates`]'s `Bounded`-default
4075 /// `true` baseline on the nested-struct sub-corner. A regression
4076 /// that dropped the resolver hop, probed
4077 /// [`Classification::has_data_classification`] directly (dropping
4078 /// the `.is_restricted()` projection), or inverted the projection
4079 /// (silently demoting the Internal baseline to "unrestricted")
4080 /// fails HERE at ONE narrow substrate site before drifting
4081 /// through every unadorned ephemeral spec's baseline access-
4082 /// control-mandatory answer.
4083 ///
4084 /// # Compounding
4085 ///
4086 /// The ephemeral require-tag classifier composes this primitive
4087 /// as a fixed tag `data-restricted` on `EPHEMERAL_FIXED_TAG_ARMS`
4088 /// — byte-for-byte peer of the point surface's `data-restricted`
4089 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4090 /// [`Classification::data_is_restricted`] directly. The two-
4091 /// surface parity contract holds by construction: both surfaces
4092 /// route through the SAME
4093 /// [`Classification::data_is_restricted`] primitive after the
4094 /// ephemeral surface pays ONE resolver hop — a future
4095 /// [`crate::classification::DataClassification`] variant or a
4096 /// future normalization at the substrate primitive lands at ONE
4097 /// site and both surfaces' `data-restricted` fixed tags inherit
4098 /// the shift mechanically. The closed-set-internal implication
4099 /// `is_regulated() ⇒ is_restricted()` composes through the
4100 /// resolver hop to
4101 /// `data_is_regulated() ⇒ data_is_restricted()` at this surface
4102 /// too.
4103 ///
4104 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4105 /// preserves proofs; the classification-data-axis derived-nullary-
4106 /// boolean probe body composes ONE resolver primitive
4107 /// ([`Self::resolved_classification`]) with ONE
4108 /// [`Classification`] primitive
4109 /// ([`Classification::data_is_restricted`]) so every downstream
4110 /// (`data-restricted` fixed tags on both surfaces in tatara-check,
4111 /// future compliance-baseline / access-control-mandatory
4112 /// validators, future variant additions on
4113 /// [`crate::classification::DataClassification`]) binds through
4114 /// the SAME `data_is_restricted()` shape rather than restating
4115 /// either the resolver walk or the closed-set projection
4116 /// composition at the callsite. THEORY.md §VI.1 — generation
4117 /// over composition; a future
4118 /// [`crate::classification::DataClassification`] variant lands
4119 /// at ONE `ALL` entry + ONE `is_restricted` arm on the closed set
4120 /// and both surfaces pick it up mechanically.
4121 #[must_use]
4122 pub fn data_is_restricted(&self) -> bool {
4123 self.resolved_classification().data_is_restricted()
4124 }
4125
4126 /// Derived-boolean predicate — does this ephemeral spec's
4127 /// resolved [`Classification`]'s
4128 /// [`crate::classification::ConvergencePointType`] project to
4129 /// `true` under
4130 /// [`crate::classification::ConvergencePointType::is_endomorphic`]?
4131 /// Byte-for-byte peer of
4132 /// [`Classification::point_is_endomorphic`] wrapped through the
4133 /// [`Self::resolved_classification`] resolver so an operator-
4134 /// omitted `:classification` slot on `(defephemeral …)` still
4135 /// answers via the substrate default. The ONE ephemeral-surface
4136 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4137 /// derived-nullary-boolean walk on the 1→1 topology-bucket
4138 /// question over the classification-`point_type` axis.
4139 ///
4140 /// # Sixth derived-nullary-boolean peer on the ephemeral surface
4141 ///
4142 /// Peer of [`Self::horizon_terminates`],
4143 /// [`Self::horizon_requires_metric_axes`],
4144 /// [`Self::calm_requires_coordination`],
4145 /// [`Self::data_is_regulated`], and [`Self::data_is_restricted`]
4146 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
4147 /// shape — the FIRST peer threading the classification-`point_type`
4148 /// axis after the two `horizon_*`, one `calm_*`, and two `data_*`
4149 /// peers populated the horizon, calm, and data axes. Direct-scalar
4150 /// peer of the sibling `data_*` and `calm_*` arms but distinct by
4151 /// ONE structural degree at the underlying [`Classification`]
4152 /// primitive: [`crate::classification::ConvergencePointType`] has
4153 /// NO [`Default`] impl, so the absent-`:classification` baseline
4154 /// answers `false` via the resolver's substrate default
4155 /// [`Classification::gate_compute`] carrying its chosen
4156 /// `point_type: Gate` field (not via a `#[default]` short-circuit
4157 /// on the point-type axis itself). The resolver-hop shape is
4158 /// byte-identical across all six peers.
4159 ///
4160 /// # Semantics — resolver hop + derived-nullary-boolean
4161 ///
4162 /// `point_is_endomorphic()` returns `true` iff
4163 /// `self.resolved_classification().point_is_endomorphic()`. The
4164 /// resolver returns the authored [`Classification`] when present
4165 /// and the substrate default [`Classification::gate_compute`] on
4166 /// absence. Because [`Classification::gate_compute`] carries
4167 /// [`crate::classification::ConvergencePointType::Gate`] (a
4168 /// convergent barrier point, not a 1→1 endomorphism), a bare
4169 /// ephemeral spec with no `:classification` slot answers `false`.
4170 /// A regression that dropped the resolver hop, probed the wrong
4171 /// closed-set arm, or inverted the projection fails HERE at ONE
4172 /// narrow substrate site before drifting through every unadorned
4173 /// ephemeral spec's DAG-composition answer.
4174 ///
4175 /// # Compounding
4176 ///
4177 /// The ephemeral require-tag classifier composes this primitive
4178 /// as a fixed tag `endomorphic-point` on
4179 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4180 /// surface's `endomorphic-point` fixed tag on
4181 /// `POINT_FIXED_TAG_ARMS` via
4182 /// [`Classification::point_is_endomorphic`] directly. The two-
4183 /// surface parity contract holds by construction: both surfaces
4184 /// route through the SAME
4185 /// [`Classification::point_is_endomorphic`] primitive after the
4186 /// ephemeral surface pays ONE resolver hop — a future
4187 /// [`crate::classification::ConvergencePointType`] variant or a
4188 /// future normalization at the substrate primitive lands at ONE
4189 /// site and both surfaces' `endomorphic-point` fixed tags inherit
4190 /// the shift mechanically. Sibling projections
4191 /// [`crate::classification::ConvergencePointType::is_diffusive`]
4192 /// and [`crate::classification::ConvergencePointType::is_convergent`]
4193 /// compose byte-identically as future seventh + eighth ephemeral-
4194 /// surface peers; when all three land the three-way partition
4195 /// contract sealed on the closed set by
4196 /// `convergence_point_type_buckets_cover_every_variant` composes
4197 /// through the resolver-hop layer as a substrate-wide theorem.
4198 ///
4199 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4200 /// preserves proofs; the classification-`point_type`-axis derived-
4201 /// nullary-boolean probe body composes ONE resolver primitive
4202 /// ([`Self::resolved_classification`]) with ONE
4203 /// [`Classification`] primitive
4204 /// ([`Classification::point_is_endomorphic`]) so every downstream
4205 /// (`endomorphic-point` fixed tags on both surfaces in tatara-check,
4206 /// future DAG composition / edge-cardinality validators, future
4207 /// variant additions on
4208 /// [`crate::classification::ConvergencePointType`]) binds through
4209 /// the SAME `point_is_endomorphic()` shape rather than restating
4210 /// either the resolver walk or the closed-set projection
4211 /// composition at the callsite. THEORY.md §VI.1 — generation over
4212 /// composition; a future
4213 /// [`crate::classification::ConvergencePointType`] variant lands
4214 /// at ONE `ALL` entry + ONE `is_endomorphic` arm on the closed
4215 /// set and both surfaces pick it up mechanically.
4216 #[must_use]
4217 pub fn point_is_endomorphic(&self) -> bool {
4218 self.resolved_classification().point_is_endomorphic()
4219 }
4220
4221 /// Derived-boolean predicate — does this ephemeral spec's
4222 /// resolved [`Classification`]'s
4223 /// [`crate::classification::ConvergencePointType`] project to
4224 /// `true` under
4225 /// [`crate::classification::ConvergencePointType::is_diffusive`]?
4226 /// Byte-for-byte peer of
4227 /// [`Classification::point_is_diffusive`] wrapped through the
4228 /// [`Self::resolved_classification`] resolver so an operator-
4229 /// omitted `:classification` slot on `(defephemeral …)` still
4230 /// answers via the substrate default. The ONE ephemeral-surface
4231 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4232 /// derived-nullary-boolean walk on the 1→N fan-out topology-bucket
4233 /// question over the classification-`point_type` axis.
4234 ///
4235 /// # Seventh derived-nullary-boolean peer on the ephemeral surface
4236 ///
4237 /// Peer of [`Self::horizon_terminates`],
4238 /// [`Self::horizon_requires_metric_axes`],
4239 /// [`Self::calm_requires_coordination`],
4240 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`], and
4241 /// [`Self::point_is_endomorphic`] on the ephemeral surface's
4242 /// (resolver-hop × derived-nullary-bool) shape — the SEVENTH peer
4243 /// overall and the SECOND peer threading the classification-
4244 /// `point_type` axis. Direct-scalar peer of
4245 /// [`Self::point_is_endomorphic`]: both compose the SAME resolver
4246 /// hop and the SAME closed-set carrier through the SAME chosen-
4247 /// field baseline discipline (`Gate.is_diffusive() = false`,
4248 /// mirror-image of `Gate.is_endomorphic() = false`). The
4249 /// resolver-hop shape is byte-identical across all seven peers.
4250 ///
4251 /// # Semantics — resolver hop + derived-nullary-boolean
4252 ///
4253 /// `point_is_diffusive()` returns `true` iff
4254 /// `self.resolved_classification().point_is_diffusive()`. The
4255 /// resolver returns the authored [`Classification`] when present
4256 /// and the substrate default [`Classification::gate_compute`] on
4257 /// absence. Because [`Classification::gate_compute`] carries
4258 /// [`crate::classification::ConvergencePointType::Gate`] (a
4259 /// convergent barrier, not a fan-out), a bare ephemeral spec with
4260 /// no `:classification` slot answers `false`. A regression that
4261 /// dropped the resolver hop, probed the wrong closed-set arm, or
4262 /// inverted the projection fails HERE at ONE narrow substrate
4263 /// site before drifting through every unadorned ephemeral spec's
4264 /// DAG-composition answer.
4265 ///
4266 /// # Compounding — first ephemeral-surface corner-peer mutex on the `point_type` axis
4267 ///
4268 /// The ephemeral require-tag classifier composes this primitive
4269 /// as a fixed tag `diffusive-point` on `EPHEMERAL_FIXED_TAG_ARMS`
4270 /// — byte-for-byte peer of the point surface's `diffusive-point`
4271 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4272 /// [`Classification::point_is_diffusive`] directly. The two-
4273 /// surface parity contract holds by construction: both surfaces
4274 /// route through the SAME
4275 /// [`Classification::point_is_diffusive`] primitive after the
4276 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
4277 /// surface corner-peer pair on the `point_type` axis (with
4278 /// [`Self::point_is_endomorphic`]) whose two projections carry a
4279 /// non-trivial closed-set-internal MUTEX relationship
4280 /// (`point_is_endomorphic ⇒ ¬point_is_diffusive`), distinct from
4281 /// the sibling `data`-axis ephemeral corner-peer pair whose two
4282 /// projections carry a non-trivial IMPLICATION relationship. When
4283 /// the third sibling [`Self::point_is_convergent`] lands, the
4284 /// mutex closes into the full three-way XOR partition composed
4285 /// through the resolver-hop layer as a substrate-wide theorem.
4286 ///
4287 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4288 /// preserves proofs; the classification-`point_type`-axis derived-
4289 /// nullary-boolean probe body composes ONE resolver primitive
4290 /// ([`Self::resolved_classification`]) with ONE
4291 /// [`Classification`] primitive
4292 /// ([`Classification::point_is_diffusive`]) so every downstream
4293 /// (`diffusive-point` fixed tags on both surfaces in tatara-check,
4294 /// future DAG composition / edge-cardinality validators, future
4295 /// variant additions on
4296 /// [`crate::classification::ConvergencePointType`]) binds through
4297 /// the SAME `point_is_diffusive()` shape rather than restating
4298 /// either the resolver walk or the closed-set projection
4299 /// composition at the callsite. THEORY.md §VI.1 — generation over
4300 /// composition; a future
4301 /// [`crate::classification::ConvergencePointType`] variant lands
4302 /// at ONE `ALL` entry + ONE `is_diffusive` arm on the closed set
4303 /// and both surfaces pick it up mechanically.
4304 #[must_use]
4305 pub fn point_is_diffusive(&self) -> bool {
4306 self.resolved_classification().point_is_diffusive()
4307 }
4308
4309 /// Derived-boolean predicate — does this ephemeral spec's
4310 /// resolved [`Classification`]'s
4311 /// [`crate::classification::ConvergencePointType`] project to
4312 /// `true` under
4313 /// [`crate::classification::ConvergencePointType::is_convergent`]?
4314 /// Byte-for-byte peer of
4315 /// [`Classification::point_is_convergent`] wrapped through the
4316 /// [`Self::resolved_classification`] resolver so an operator-
4317 /// omitted `:classification` slot on `(defephemeral …)` still
4318 /// answers via the substrate default. The ONE ephemeral-surface
4319 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4320 /// derived-nullary-boolean walk on the N→1 fan-in topology-bucket
4321 /// question over the classification-`point_type` axis.
4322 ///
4323 /// # Eighth derived-nullary-boolean peer on the ephemeral surface
4324 ///
4325 /// Peer of [`Self::horizon_terminates`],
4326 /// [`Self::horizon_requires_metric_axes`],
4327 /// [`Self::calm_requires_coordination`],
4328 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4329 /// [`Self::point_is_endomorphic`], and [`Self::point_is_diffusive`]
4330 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4331 /// bool) shape — the EIGHTH peer overall and the THIRD peer
4332 /// threading the classification-`point_type` axis. Direct-scalar
4333 /// peer of [`Self::point_is_endomorphic`] and
4334 /// [`Self::point_is_diffusive`]: the three compose the SAME
4335 /// resolver hop and the SAME closed-set carrier through the SAME
4336 /// chosen-field baseline discipline, but the answer flips on the
4337 /// baseline — `Gate.is_convergent() = true`, so an ephemeral spec
4338 /// with no `:classification` slot answers `true` HERE (mirror-
4339 /// inverted from the two sibling probes which answer `false`).
4340 /// The resolver-hop shape is byte-identical across all eight
4341 /// peers.
4342 ///
4343 /// # Semantics — resolver hop + derived-nullary-boolean
4344 ///
4345 /// `point_is_convergent()` returns `true` iff
4346 /// `self.resolved_classification().point_is_convergent()`. The
4347 /// resolver returns the authored [`Classification`] when present
4348 /// and the substrate default [`Classification::gate_compute`] on
4349 /// absence. Because [`Classification::gate_compute`] carries
4350 /// [`crate::classification::ConvergencePointType::Gate`] (the
4351 /// canonical convergent barrier), a bare ephemeral spec with no
4352 /// `:classification` slot answers `true` — a regression that
4353 /// dropped the resolver hop, probed the wrong closed-set arm, or
4354 /// inverted the projection fails HERE at ONE narrow substrate
4355 /// site before drifting through every unadorned ephemeral spec's
4356 /// DAG-composition answer.
4357 ///
4358 /// # Compounding — closes the three-way XOR partition on the ephemeral surface
4359 ///
4360 /// The ephemeral require-tag classifier composes this primitive
4361 /// as a fixed tag `convergent-point` on `EPHEMERAL_FIXED_TAG_ARMS`
4362 /// — byte-for-byte peer of the point surface's `convergent-point`
4363 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4364 /// [`Classification::point_is_convergent`] directly. The two-
4365 /// surface parity contract holds by construction: both surfaces
4366 /// route through the SAME
4367 /// [`Classification::point_is_convergent`] primitive after the
4368 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
4369 /// surface peer on the `point_type` axis closing the mutex pair
4370 /// [`Self::point_is_endomorphic`] / [`Self::point_is_diffusive`]
4371 /// into the FULL three-way XOR partition contract composed
4372 /// through the resolver-hop layer as a substrate-wide theorem.
4373 ///
4374 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4375 /// preserves proofs; the classification-`point_type`-axis derived-
4376 /// nullary-boolean probe body composes ONE resolver primitive
4377 /// ([`Self::resolved_classification`]) with ONE
4378 /// [`Classification`] primitive
4379 /// ([`Classification::point_is_convergent`]) so every downstream
4380 /// (`convergent-point` fixed tags on both surfaces in tatara-check,
4381 /// future DAG composition / edge-cardinality validators, future
4382 /// variant additions on
4383 /// [`crate::classification::ConvergencePointType`]) binds through
4384 /// the SAME `point_is_convergent()` shape rather than restating
4385 /// either the resolver walk or the closed-set projection
4386 /// composition at the callsite. THEORY.md §VI.1 — generation over
4387 /// composition; a future
4388 /// [`crate::classification::ConvergencePointType`] variant lands
4389 /// at ONE `ALL` entry + ONE `is_convergent` arm on the closed set
4390 /// and both surfaces pick it up mechanically.
4391 #[must_use]
4392 pub fn point_is_convergent(&self) -> bool {
4393 self.resolved_classification().point_is_convergent()
4394 }
4395
4396 /// Derived-boolean predicate — does this ephemeral spec's
4397 /// resolved [`Classification`]'s
4398 /// [`crate::classification::SubstrateType`] project to `true`
4399 /// under [`crate::classification::SubstrateType::is_resource`]?
4400 /// Byte-for-byte peer of
4401 /// [`Classification::substrate_is_resource`] wrapped through the
4402 /// [`Self::resolved_classification`] resolver so an operator-
4403 /// omitted `:classification` slot on `(defephemeral …)` still
4404 /// answers via the substrate default. The ONE ephemeral-surface
4405 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4406 /// derived-nullary-boolean walk on the resource-plane bucket
4407 /// question over the classification-`substrate` axis.
4408 ///
4409 /// # Ninth derived-nullary-boolean peer on the ephemeral surface
4410 ///
4411 /// Peer of [`Self::horizon_terminates`],
4412 /// [`Self::horizon_requires_metric_axes`],
4413 /// [`Self::calm_requires_coordination`],
4414 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4415 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4416 /// and [`Self::point_is_convergent`] on the ephemeral surface's
4417 /// (resolver-hop × derived-nullary-bool) shape — the NINTH peer
4418 /// overall and the FIRST peer threading the classification-
4419 /// `substrate` axis (the fourth of six classification axes
4420 /// participating on this corner, after `horizon`, `calm`,
4421 /// `data_classification`, and `point_type`). The resolver-hop
4422 /// shape is byte-identical across all nine peers.
4423 ///
4424 /// # Semantics — resolver hop + derived-nullary-boolean
4425 ///
4426 /// `substrate_is_resource()` returns `true` iff
4427 /// `self.resolved_classification().substrate_is_resource()`. The
4428 /// resolver returns the authored [`Classification`] when present
4429 /// and the substrate default [`Classification::gate_compute`] on
4430 /// absence. Because [`Classification::gate_compute`] carries
4431 /// [`crate::classification::SubstrateType::Compute`] (the
4432 /// canonical resource-plane substrate), a bare ephemeral spec
4433 /// with no `:classification` slot answers `true` — a regression
4434 /// that dropped the resolver hop, probed the wrong closed-set
4435 /// arm, or inverted the projection fails HERE at ONE narrow
4436 /// substrate site before drifting through every unadorned
4437 /// ephemeral spec's plane-baseline answer.
4438 ///
4439 /// # Compounding — opens the substrate axis on the ephemeral surface
4440 ///
4441 /// The ephemeral require-tag classifier composes this primitive
4442 /// as a fixed tag `resource-substrate` on
4443 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4444 /// surface's `resource-substrate` fixed tag on
4445 /// `POINT_FIXED_TAG_ARMS` via
4446 /// [`Classification::substrate_is_resource`] directly. The two-
4447 /// surface parity contract holds by construction: both surfaces
4448 /// route through the SAME
4449 /// [`Classification::substrate_is_resource`] primitive after the
4450 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
4451 /// surface peer on the `substrate` axis — future sibling
4452 /// projections [`crate::classification::SubstrateType::is_policy`]
4453 /// and [`crate::classification::SubstrateType::is_telemetry`]
4454 /// compose byte-identically as future tenth + eleventh peers,
4455 /// closing the axis into a proven-repeatable three-peer sub-
4456 /// corner exactly as the `point_type` axis was closed on this
4457 /// surface by
4458 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4459 ///
4460 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4461 /// preserves proofs; the classification-`substrate`-axis derived-
4462 /// nullary-boolean probe body composes ONE resolver primitive
4463 /// ([`Self::resolved_classification`]) with ONE
4464 /// [`Classification`] primitive
4465 /// ([`Classification::substrate_is_resource`]) so every
4466 /// downstream (`resource-substrate` fixed tags on both surfaces
4467 /// in tatara-check, future plane-baseline / compliance-baseline
4468 /// selectors, future variant additions on
4469 /// [`crate::classification::SubstrateType`]) binds through the
4470 /// SAME `substrate_is_resource()` shape rather than restating
4471 /// either the resolver walk or the closed-set projection
4472 /// composition at the callsite. THEORY.md §VI.1 — generation
4473 /// over composition; a future
4474 /// [`crate::classification::SubstrateType`] variant lands at ONE
4475 /// `ALL` entry + ONE `is_resource` arm on the closed set and
4476 /// both surfaces pick it up mechanically.
4477 #[must_use]
4478 pub fn substrate_is_resource(&self) -> bool {
4479 self.resolved_classification().substrate_is_resource()
4480 }
4481
4482 /// Derived-boolean predicate — does this ephemeral spec's
4483 /// resolved [`Classification`]'s
4484 /// [`crate::classification::SubstrateType`] project to `true`
4485 /// under [`crate::classification::SubstrateType::is_policy`]?
4486 /// Byte-for-byte peer of
4487 /// [`Classification::substrate_is_policy`] wrapped through the
4488 /// [`Self::resolved_classification`] resolver so an operator-
4489 /// omitted `:classification` slot on `(defephemeral …)` still
4490 /// answers via the substrate default. The ONE ephemeral-surface
4491 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4492 /// derived-nullary-boolean walk on the policy-plane bucket
4493 /// question over the classification-`substrate` axis.
4494 ///
4495 /// # Tenth derived-nullary-boolean peer on the ephemeral surface
4496 ///
4497 /// Peer of [`Self::horizon_terminates`],
4498 /// [`Self::horizon_requires_metric_axes`],
4499 /// [`Self::calm_requires_coordination`],
4500 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4501 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4502 /// [`Self::point_is_convergent`], and
4503 /// [`Self::substrate_is_resource`] on the ephemeral surface's
4504 /// (resolver-hop × derived-nullary-bool) shape — the TENTH peer
4505 /// overall and the SECOND peer threading the classification-
4506 /// `substrate` axis, promoting that axis on this surface from a
4507 /// proven-repeatable one-off to a proven-repeatable pair.
4508 /// FIRST ephemeral-surface substrate-axis corner-peer pair
4509 /// carrying a non-trivial closed-set-internal MUTEX relationship
4510 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`), structural
4511 /// twin of the sibling `point_type`-axis MUTEX pair sealed on
4512 /// this surface by
4513 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
4514 /// The resolver-hop shape is byte-identical across all ten peers.
4515 ///
4516 /// # Semantics — resolver hop + derived-nullary-boolean
4517 ///
4518 /// `substrate_is_policy()` returns `true` iff
4519 /// `self.resolved_classification().substrate_is_policy()`. The
4520 /// resolver returns the authored [`Classification`] when present
4521 /// and the substrate default [`Classification::gate_compute`] on
4522 /// absence. Because [`Classification::gate_compute`] carries
4523 /// [`crate::classification::SubstrateType::Compute`] (the
4524 /// canonical resource-plane substrate, NOT a policy plane), a
4525 /// bare ephemeral spec with no `:classification` slot answers
4526 /// `false` — a regression that dropped the resolver hop, probed
4527 /// the wrong closed-set arm, or inverted the projection fails
4528 /// HERE at ONE narrow substrate site before drifting through
4529 /// every unadorned ephemeral spec's plane-baseline answer.
4530 ///
4531 /// # Compounding — second substrate-axis peer on the ephemeral surface
4532 ///
4533 /// The ephemeral require-tag classifier composes this primitive
4534 /// as a fixed tag `policy-substrate` on
4535 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4536 /// surface's `policy-substrate` fixed tag on
4537 /// `POINT_FIXED_TAG_ARMS` via
4538 /// [`Classification::substrate_is_policy`] directly. The two-
4539 /// surface parity contract holds by construction: both surfaces
4540 /// route through the SAME
4541 /// [`Classification::substrate_is_policy`] primitive after the
4542 /// ephemeral surface pays ONE resolver hop. SECOND ephemeral-
4543 /// surface peer on the `substrate` axis — sibling projection
4544 /// [`crate::classification::SubstrateType::is_telemetry`]
4545 /// composes byte-identically as a future eleventh peer, closing
4546 /// the axis into a proven-repeatable three-peer sub-corner
4547 /// exactly as the `point_type` axis was closed on this surface
4548 /// by
4549 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4550 ///
4551 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4552 /// preserves proofs; the classification-`substrate`-axis derived-
4553 /// nullary-boolean probe body composes ONE resolver primitive
4554 /// ([`Self::resolved_classification`]) with ONE
4555 /// [`Classification`] primitive
4556 /// ([`Classification::substrate_is_policy`]) so every
4557 /// downstream (`policy-substrate` fixed tags on both surfaces
4558 /// in tatara-check, future plane-baseline / compliance-baseline
4559 /// selectors, future variant additions on
4560 /// [`crate::classification::SubstrateType`]) binds through the
4561 /// SAME `substrate_is_policy()` shape rather than restating
4562 /// either the resolver walk or the closed-set projection
4563 /// composition at the callsite. THEORY.md §VI.1 — generation
4564 /// over composition; a future
4565 /// [`crate::classification::SubstrateType`] variant lands at ONE
4566 /// `ALL` entry + ONE `is_policy` arm on the closed set and
4567 /// both surfaces pick it up mechanically.
4568 #[must_use]
4569 pub fn substrate_is_policy(&self) -> bool {
4570 self.resolved_classification().substrate_is_policy()
4571 }
4572
4573 /// Derived-boolean predicate — does this ephemeral spec's
4574 /// resolved [`Classification`]'s
4575 /// [`crate::classification::SubstrateType`] project to `true`
4576 /// under [`crate::classification::SubstrateType::is_telemetry`]?
4577 /// Byte-for-byte peer of
4578 /// [`Classification::substrate_is_telemetry`] wrapped through
4579 /// the [`Self::resolved_classification`] resolver so an operator-
4580 /// omitted `:classification` slot on `(defephemeral …)` still
4581 /// answers via the substrate default. The ONE ephemeral-surface
4582 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4583 /// derived-nullary-boolean walk on the telemetry-plane bucket
4584 /// question over the classification-`substrate` axis.
4585 ///
4586 /// # Eleventh derived-nullary-boolean peer on the ephemeral surface — CLOSES the substrate axis
4587 ///
4588 /// Peer of [`Self::horizon_terminates`],
4589 /// [`Self::horizon_requires_metric_axes`],
4590 /// [`Self::calm_requires_coordination`],
4591 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4592 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4593 /// [`Self::point_is_convergent`], [`Self::substrate_is_resource`],
4594 /// and [`Self::substrate_is_policy`] on the ephemeral surface's
4595 /// (resolver-hop × derived-nullary-bool) shape — the ELEVENTH
4596 /// peer overall and the THIRD peer threading the classification-
4597 /// `substrate` axis. This peer CLOSES the substrate axis on the
4598 /// ephemeral surface into the FULL three-way XOR partition
4599 /// contract `substrate_is_resource ⊕ substrate_is_policy ⊕
4600 /// substrate_is_telemetry` — sealed on this surface by
4601 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
4602 /// the resolver-hop peer of the parent-composed
4603 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`.
4604 /// Structural twin of the sibling `point_type`-axis ternary lift
4605 /// sealed on this surface by
4606 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4607 /// The resolver-hop shape is byte-identical across all eleven
4608 /// peers.
4609 ///
4610 /// # Semantics — resolver hop + derived-nullary-boolean
4611 ///
4612 /// `substrate_is_telemetry()` returns `true` iff
4613 /// `self.resolved_classification().substrate_is_telemetry()`.
4614 /// The resolver returns the authored [`Classification`] when
4615 /// present and the substrate default [`Classification::gate_compute`]
4616 /// on absence. Because [`Classification::gate_compute`] carries
4617 /// [`crate::classification::SubstrateType::Compute`] (the
4618 /// canonical resource-plane substrate, NOT a telemetry plane),
4619 /// a bare ephemeral spec with no `:classification` slot answers
4620 /// `false` — a regression that dropped the resolver hop, probed
4621 /// the wrong closed-set arm, or inverted the projection fails
4622 /// HERE at ONE narrow substrate site before drifting through
4623 /// every unadorned ephemeral spec's plane-baseline answer.
4624 ///
4625 /// # Compounding — CLOSES the substrate axis on the ephemeral surface
4626 ///
4627 /// The ephemeral require-tag classifier composes this primitive
4628 /// as a fixed tag `telemetry-substrate` on
4629 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4630 /// surface's `telemetry-substrate` fixed tag on
4631 /// `POINT_FIXED_TAG_ARMS` via
4632 /// [`Classification::substrate_is_telemetry`] directly. The two-
4633 /// surface parity contract holds by construction: both surfaces
4634 /// route through the SAME
4635 /// [`Classification::substrate_is_telemetry`] primitive after the
4636 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
4637 /// surface peer on the `substrate` axis — closes the axis into a
4638 /// proven-repeatable three-peer sub-corner exactly as the
4639 /// `point_type` axis was closed on this surface by
4640 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4641 ///
4642 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4643 /// preserves proofs; the classification-`substrate`-axis derived-
4644 /// nullary-boolean probe body composes ONE resolver primitive
4645 /// ([`Self::resolved_classification`]) with ONE
4646 /// [`Classification`] primitive
4647 /// ([`Classification::substrate_is_telemetry`]) so every
4648 /// downstream (`telemetry-substrate` fixed tags on both surfaces
4649 /// in tatara-check, future plane-baseline / compliance-baseline
4650 /// selectors, future variant additions on
4651 /// [`crate::classification::SubstrateType`]) binds through the
4652 /// SAME `substrate_is_telemetry()` shape rather than restating
4653 /// either the resolver walk or the closed-set projection
4654 /// composition at the callsite. THEORY.md §VI.1 — generation
4655 /// over composition; a future
4656 /// [`crate::classification::SubstrateType`] variant lands at ONE
4657 /// `ALL` entry + ONE `is_telemetry` arm on the closed set and
4658 /// both surfaces pick it up mechanically.
4659 #[must_use]
4660 pub fn substrate_is_telemetry(&self) -> bool {
4661 self.resolved_classification().substrate_is_telemetry()
4662 }
4663
4664 /// Derived-boolean predicate — does this ephemeral spec's
4665 /// resolved [`Classification`]'s
4666 /// [`crate::classification::CalmClassification`] project to `true`
4667 /// under [`crate::classification::CalmClassification::is_monotone`]?
4668 /// Byte-for-byte peer of [`Classification::calm_is_monotone`]
4669 /// wrapped through the [`Self::resolved_classification`] resolver
4670 /// so an operator-omitted `:classification` slot on
4671 /// `(defephemeral …)` still answers via the substrate default.
4672 /// The ONE ephemeral-surface substrate primitive that owns the
4673 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4674 /// CALM-monotone-plane question — the positive framing peer of
4675 /// [`Self::calm_requires_coordination`].
4676 ///
4677 /// # Twelfth derived-nullary-boolean peer on the ephemeral surface — CLOSES the calm axis
4678 ///
4679 /// Peer of [`Self::horizon_terminates`],
4680 /// [`Self::horizon_requires_metric_axes`],
4681 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4682 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4683 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4684 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4685 /// and [`Self::substrate_is_telemetry`] on the ephemeral
4686 /// surface's (resolver-hop × derived-nullary-bool) shape — the
4687 /// TWELFTH peer overall and the SECOND peer threading the
4688 /// classification-`calm` axis. This peer CLOSES the calm axis
4689 /// on the ephemeral surface into the FULL binary XOR partition
4690 /// contract `calm_is_monotone ⊕ calm_requires_coordination` —
4691 /// sealed on this surface by
4692 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
4693 /// the resolver-hop peer of the parent-composed
4694 /// `classification_calm_probes_form_binary_xor_partition_over_all`.
4695 /// Structural twin of the sibling horizon-axis binary XOR
4696 /// sealed on the closed set by
4697 /// `horizon_kind_terminate_xor_requires_metric_axes`, lifted
4698 /// through the resolver hop to the ephemeral surface. The
4699 /// resolver-hop shape is byte-identical across all twelve peers.
4700 ///
4701 /// # Semantics — resolver hop + derived-nullary-boolean
4702 ///
4703 /// `calm_is_monotone()` returns `true` iff
4704 /// `self.resolved_classification().calm_is_monotone()`. The
4705 /// resolver returns the authored [`Classification`] when present
4706 /// and the substrate default [`Classification::gate_compute`] on
4707 /// absence. Because [`Classification::gate_compute`] carries
4708 /// [`crate::classification::CalmClassification::default =
4709 /// Monotone`] via `#[default]`, a bare ephemeral spec with no
4710 /// `:classification` slot answers `true` — every unadorned
4711 /// `(defephemeral …)` reads as gossip-eligible under the
4712 /// positive CALM framing, safe under Hellerstein's theorem
4713 /// (monotone operations distribute without coordination). A
4714 /// regression that dropped the resolver hop, probed the wrong
4715 /// closed-set arm, or inverted the projection fails HERE at ONE
4716 /// narrow substrate site before drifting through every
4717 /// unadorned ephemeral spec's positive-CALM-framing answer.
4718 /// Mirror-inverted from the sibling
4719 /// `calm_requires_coordination_probes_false_on_absent_classification`
4720 /// (both walk the SAME defaulted `calm` field, so
4721 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
4722 /// closed set's disjoint XOR partition).
4723 ///
4724 /// # Compounding — CLOSES the calm axis on the ephemeral surface
4725 ///
4726 /// The ephemeral require-tag classifier composes this primitive
4727 /// as a fixed tag `monotone-calm` on `EPHEMERAL_FIXED_TAG_ARMS`
4728 /// — byte-for-byte peer of the point surface's `monotone-calm`
4729 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4730 /// [`Classification::calm_is_monotone`] directly. The two-
4731 /// surface parity contract holds by construction: both surfaces
4732 /// route through the SAME [`Classification::calm_is_monotone`]
4733 /// primitive after the ephemeral surface pays ONE resolver hop.
4734 /// SECOND ephemeral-surface peer on the `calm` axis — CLOSES the
4735 /// axis into a proven-repeatable two-peer sub-corner exactly as
4736 /// the `horizon` axis is closed on the closed-set layer by
4737 /// `horizon_kind_terminate_xor_requires_metric_axes`.
4738 ///
4739 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4740 /// preserves proofs; the classification-`calm`-axis derived-
4741 /// nullary-boolean probe body composes ONE resolver primitive
4742 /// ([`Self::resolved_classification`]) with ONE
4743 /// [`Classification`] primitive
4744 /// ([`Classification::calm_is_monotone`]) so every downstream
4745 /// (`monotone-calm` fixed tags on both surfaces in tatara-check,
4746 /// future scheduler / gossip-eligibility validators reading the
4747 /// positive CALM framing, future variant additions on
4748 /// [`crate::classification::CalmClassification`]) binds through
4749 /// the SAME `calm_is_monotone()` shape rather than restating
4750 /// either the resolver walk or the closed-set projection
4751 /// composition at the callsite. THEORY.md §VI.1 — generation
4752 /// over composition; a future
4753 /// [`crate::classification::CalmClassification`] variant lands
4754 /// at ONE `ALL` entry + ONE `is_monotone` arm on the closed set
4755 /// and both surfaces pick it up mechanically.
4756 #[must_use]
4757 pub fn calm_is_monotone(&self) -> bool {
4758 self.resolved_classification().calm_is_monotone()
4759 }
4760
4761 /// Derived-boolean predicate — does this ephemeral spec's
4762 /// resolved [`Classification`]'s
4763 /// [`crate::classification::DataClassification`] project to `true`
4764 /// under [`crate::classification::DataClassification::is_public`]?
4765 /// Byte-for-byte peer of [`Classification::data_is_public`]
4766 /// wrapped through the [`Self::resolved_classification`] resolver
4767 /// so an operator-omitted `:classification` slot on
4768 /// `(defephemeral …)` still answers via the substrate default.
4769 /// The ONE ephemeral-surface substrate primitive that owns the
4770 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4771 /// freely-distributable-data question — the positive framing peer
4772 /// of [`Self::data_is_restricted`].
4773 ///
4774 /// # Thirteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the data axis
4775 ///
4776 /// Peer of [`Self::horizon_terminates`],
4777 /// [`Self::horizon_requires_metric_axes`],
4778 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4779 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4780 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4781 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4782 /// [`Self::substrate_is_telemetry`], and [`Self::calm_is_monotone`]
4783 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
4784 /// shape — the THIRTEENTH peer overall and the THIRD peer
4785 /// threading the classification-`data_classification` axis. This
4786 /// peer CLOSES the data axis on the ephemeral surface into the
4787 /// FULL binary XOR partition contract
4788 /// `data_is_public ⊕ data_is_restricted` — sealed on this surface
4789 /// by `ephemeral_data_probes_form_binary_xor_partition_over_all`,
4790 /// the resolver-hop peer of the parent-composed
4791 /// `classification_data_probes_form_binary_xor_partition_over_all`.
4792 /// Structural twin of the sibling calm-axis binary XOR sealed on
4793 /// this surface by
4794 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
4795 /// lifted through the resolver hop from the six-variant data-axis
4796 /// closed set to the ephemeral surface. The resolver-hop shape is
4797 /// byte-identical across all thirteen peers.
4798 ///
4799 /// # Semantics — resolver hop + derived-nullary-boolean
4800 ///
4801 /// `data_is_public()` returns `true` iff
4802 /// `self.resolved_classification().data_is_public()`. The
4803 /// resolver returns the authored [`Classification`] when present
4804 /// and the substrate default [`Classification::gate_compute`] on
4805 /// absence. Because [`Classification::gate_compute`] carries
4806 /// [`crate::classification::DataClassification::default =
4807 /// Internal`] via `#[default]`, a bare ephemeral spec with no
4808 /// `:classification` slot answers `false` — every unadorned
4809 /// `(defephemeral …)` reads as access-controlled by default (safe
4810 /// under compliance baseline: an operator must deliberately opt
4811 /// the dataset into public distribution rather than the substrate
4812 /// silently promoting an unadorned Process onto the freely-
4813 /// distributable path). A regression that dropped the resolver
4814 /// hop, probed the wrong closed-set arm, or inverted the
4815 /// projection fails HERE at ONE narrow substrate site before
4816 /// drifting through every unadorned ephemeral spec's positive-
4817 /// distribution-framing answer. Mirror-inverted from the sibling
4818 /// `data_is_restricted_probes_true_on_absent_classification`
4819 /// (both walk the SAME defaulted `data_classification` field, so
4820 /// `is_restricted = true` ⇒ `is_public = false` on the closed
4821 /// set's disjoint XOR partition).
4822 ///
4823 /// # Compounding — CLOSES the data axis on the ephemeral surface
4824 ///
4825 /// The ephemeral require-tag classifier composes this primitive
4826 /// as a fixed tag `public-data` on `EPHEMERAL_FIXED_TAG_ARMS`
4827 /// — byte-for-byte peer of the point surface's `public-data`
4828 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4829 /// [`Classification::data_is_public`] directly. The two-
4830 /// surface parity contract holds by construction: both surfaces
4831 /// route through the SAME [`Classification::data_is_public`]
4832 /// primitive after the ephemeral surface pays ONE resolver hop.
4833 /// THIRD ephemeral-surface peer on the `data_classification` axis
4834 /// — CLOSES the axis into a proven-repeatable three-peer sub-
4835 /// corner (data_is_regulated, data_is_restricted, data_is_public)
4836 /// whose complementary XOR partition seals on the closed set by
4837 /// `data_classification_public_xor_restricted` and composes
4838 /// through the resolver hop as a substrate-wide theorem.
4839 ///
4840 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4841 /// preserves proofs; the classification-`data_classification`-axis
4842 /// derived-nullary-boolean probe body composes ONE resolver
4843 /// primitive ([`Self::resolved_classification`]) with ONE
4844 /// [`Classification`] primitive
4845 /// ([`Classification::data_is_public`]) so every downstream
4846 /// (`public-data` fixed tags on both surfaces in tatara-check,
4847 /// future compliance-baseline / audit-log-optional validators
4848 /// reading the positive distribution framing, future variant
4849 /// additions on
4850 /// [`crate::classification::DataClassification`]) binds through
4851 /// the SAME `data_is_public()` shape rather than restating either
4852 /// the resolver walk or the closed-set projection composition at
4853 /// the callsite. THEORY.md §VI.1 — generation over composition; a
4854 /// future [`crate::classification::DataClassification`] variant
4855 /// lands at ONE `ALL` entry + ONE `is_public` arm on the closed
4856 /// set and both surfaces pick it up mechanically.
4857 #[must_use]
4858 pub fn data_is_public(&self) -> bool {
4859 self.resolved_classification().data_is_public()
4860 }
4861
4862 /// Derived-boolean predicate — does this ephemeral spec's resolved
4863 /// [`Classification`]'s
4864 /// [`crate::classification::Horizon::direction`] slot (defaulted
4865 /// through [`crate::classification::OptimizationDirection::default =
4866 /// Minimize`] on absence) project to `true` under
4867 /// [`crate::classification::OptimizationDirection::prefers_lower`]?
4868 /// Byte-for-byte peer of
4869 /// [`crate::classification::Classification::direction_prefers_lower`]
4870 /// wrapped through the [`Self::resolved_classification`] resolver so
4871 /// an operator-omitted `:classification` slot on
4872 /// `(defephemeral …)` still answers via the substrate default. The
4873 /// ONE ephemeral-surface substrate primitive that owns the
4874 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4875 /// lower-is-better optimization-polarity question.
4876 ///
4877 /// # Fourteenth derived-nullary-boolean peer on the ephemeral surface — opens the optimization-direction axis
4878 ///
4879 /// Peer of the thirteen prior nullary-boolean substrate primitives
4880 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4881 /// [`Self::horizon_requires_metric_axes`],
4882 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4883 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4884 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4885 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4886 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4887 /// [`Self::data_is_public`]) on the ephemeral surface's
4888 /// (resolver-hop × derived-nullary-bool) shape — the FOURTEENTH
4889 /// peer overall and the FIRST peer threading the classification-
4890 /// `horizon.direction` axis on this surface. Opens the SIXTH
4891 /// classification axis into the ephemeral fixed-tag algebra after
4892 /// the horizon, calm, data, point, and substrate axes. The
4893 /// resolver-hop shape is byte-identical across all fourteen peers.
4894 ///
4895 /// # Semantics — resolver hop + derived-nullary-boolean
4896 ///
4897 /// `direction_prefers_lower()` returns `true` iff
4898 /// `self.resolved_classification().direction_prefers_lower()`. The
4899 /// resolver returns the authored [`Classification`] when present
4900 /// and the substrate default [`Classification::gate_compute`] on
4901 /// absence. Because [`Classification::gate_compute`] carries
4902 /// `horizon: Horizon::default()` whose `direction` field is `None`,
4903 /// and [`crate::classification::OptimizationDirection::default =
4904 /// Minimize`] projects `prefers_lower = true`, a bare ephemeral
4905 /// spec with no `:classification` slot answers `true` — every
4906 /// unadorned `(defephemeral …)` reads as lower-is-better under the
4907 /// substrate polarity default (safe under the asymptotic-health
4908 /// rate-window evaluator's convention: an operator must
4909 /// deliberately opt into Maximize polarity rather than the
4910 /// substrate silently flipping every unadorned Process onto the
4911 /// higher-is-better path). A regression that dropped the resolver
4912 /// hop, probed the wrong closed-set arm, or inverted the projection
4913 /// fails HERE at ONE narrow substrate site before drifting through
4914 /// every unadorned ephemeral spec's rate-window evaluator polarity.
4915 ///
4916 /// # Compounding — opens the optimization-direction axis on the ephemeral surface
4917 ///
4918 /// The ephemeral require-tag classifier composes this primitive as
4919 /// a fixed tag `prefers-lower-direction` on
4920 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4921 /// surface's `prefers-lower-direction` fixed tag on
4922 /// `POINT_FIXED_TAG_ARMS` via
4923 /// [`Classification::direction_prefers_lower`] directly. The
4924 /// two-surface parity contract holds by construction: both surfaces
4925 /// route through the SAME [`Classification::direction_prefers_lower`]
4926 /// primitive after the ephemeral surface pays ONE resolver hop.
4927 /// A future antisymmetric peer (`direction_prefers_higher`) closes
4928 /// the binary XOR partition on this axis — mirror of the calm-axis
4929 /// (`monotone-calm ⊕ coordination-required`) and data-axis
4930 /// (`public-data ⊕ data-restricted`) closures on this surface.
4931 ///
4932 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4933 /// preserves proofs; the classification-`horizon.direction`-axis
4934 /// derived-nullary-boolean probe body composes ONE resolver
4935 /// primitive ([`Self::resolved_classification`]) with ONE
4936 /// [`Classification`] primitive
4937 /// ([`Classification::direction_prefers_lower`]) so every
4938 /// downstream (the `prefers-lower-direction` fixed tags on both
4939 /// surfaces in tatara-check, future asymptotic-health rate-window
4940 /// / regression-detector evaluators, future variant additions on
4941 /// [`crate::classification::OptimizationDirection`]) binds through
4942 /// the SAME `direction_prefers_lower()` shape rather than restating
4943 /// either the resolver walk or the closed-set projection
4944 /// composition at the callsite. THEORY.md §VI.1 — generation over
4945 /// composition; a future
4946 /// [`crate::classification::OptimizationDirection`] variant lands
4947 /// at ONE `ALL` entry + ONE `prefers_lower` arm on the closed set
4948 /// and both surfaces pick it up mechanically.
4949 #[must_use]
4950 pub fn direction_prefers_lower(&self) -> bool {
4951 self.resolved_classification().direction_prefers_lower()
4952 }
4953
4954 /// POSITIVE-FRAMING PEER of [`Self::direction_prefers_lower`] —
4955 /// does this ephemeral spec's resolved [`Classification`]'s
4956 /// [`crate::classification::Horizon::direction`] slot (defaulted
4957 /// through [`crate::classification::OptimizationDirection::default =
4958 /// Minimize`] on absence) project to `true` under
4959 /// [`crate::classification::OptimizationDirection::prefers_higher`]?
4960 /// Byte-for-byte peer of
4961 /// [`crate::classification::Classification::direction_prefers_higher`]
4962 /// wrapped through the [`Self::resolved_classification`] resolver
4963 /// so an operator-omitted `:classification` slot on
4964 /// `(defephemeral …)` still answers via the substrate default. The
4965 /// ONE ephemeral-surface substrate primitive that owns the
4966 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4967 /// higher-is-better optimization-polarity question.
4968 ///
4969 /// # Fifteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the optimization-direction axis
4970 ///
4971 /// Peer of the fourteen prior nullary-boolean substrate primitives
4972 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4973 /// [`Self::horizon_requires_metric_axes`],
4974 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4975 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4976 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4977 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4978 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4979 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`]) on
4980 /// the ephemeral surface's (resolver-hop × derived-nullary-bool)
4981 /// shape — the FIFTEENTH peer overall and the SECOND peer
4982 /// threading the classification-`horizon.direction` axis on this
4983 /// surface. CLOSES the SIXTH classification axis into a binary XOR
4984 /// partition on the ephemeral surface after the horizon, calm,
4985 /// data, point, and substrate axes — completing the axis-coverage
4986 /// milestone on this surface: ALL SIX classification axes now
4987 /// have their partitions closed at the ephemeral-surface derived-
4988 /// nullary corner. The resolver-hop shape is byte-identical across
4989 /// all fifteen peers.
4990 ///
4991 /// # Semantics — resolver hop + derived-nullary-boolean
4992 ///
4993 /// `direction_prefers_higher()` returns `true` iff
4994 /// `self.resolved_classification().direction_prefers_higher()`.
4995 /// The resolver returns the authored [`Classification`] when
4996 /// present and the substrate default
4997 /// [`Classification::gate_compute`] on absence. Because
4998 /// [`Classification::gate_compute`] carries `horizon:
4999 /// Horizon::default()` whose `direction` field is `None`, and
5000 /// [`crate::classification::OptimizationDirection::default =
5001 /// Minimize`] projects `prefers_higher = false`, a bare ephemeral
5002 /// spec with no `:classification` slot answers `false` — every
5003 /// unadorned `(defephemeral …)` reads as lower-is-better under the
5004 /// substrate polarity default (safe under the asymptotic-health
5005 /// rate-window evaluator's convention: an operator must
5006 /// deliberately opt into Maximize polarity rather than the
5007 /// substrate silently flipping every unadorned Process onto the
5008 /// higher-is-better path). A regression that dropped the resolver
5009 /// hop, probed the wrong closed-set arm, or inverted the
5010 /// projection fails HERE at ONE narrow substrate site before
5011 /// drifting through every unadorned ephemeral spec's rate-window
5012 /// evaluator polarity.
5013 ///
5014 /// # Compounding — CLOSES the optimization-direction axis on the ephemeral surface
5015 ///
5016 /// The ephemeral require-tag classifier composes this primitive as
5017 /// a fixed tag `prefers-higher-direction` on
5018 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5019 /// surface's `prefers-higher-direction` fixed tag on
5020 /// `POINT_FIXED_TAG_ARMS` via
5021 /// [`Classification::direction_prefers_higher`] directly. The
5022 /// two-surface parity contract holds by construction: both
5023 /// surfaces route through the SAME
5024 /// [`Classification::direction_prefers_higher`] primitive after
5025 /// the ephemeral surface pays ONE resolver hop. SECOND
5026 /// optimization-direction-axis peer CLOSES the axis into the FULL
5027 /// binary XOR partition contract on this surface — the resolver-
5028 /// hop peer of the parent-composed
5029 /// `classification_direction_probes_form_binary_xor_partition_over_all`,
5030 /// mirror of the calm-axis (`monotone-calm ⊕ coordination-required`)
5031 /// and data-axis (`public-data ⊕ data-restricted`) closures on
5032 /// this surface.
5033 ///
5034 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5035 /// preserves proofs; the classification-`horizon.direction`-axis
5036 /// derived-nullary-boolean probe body composes ONE resolver
5037 /// primitive ([`Self::resolved_classification`]) with ONE
5038 /// [`Classification`] primitive
5039 /// ([`Classification::direction_prefers_higher`]) so every
5040 /// downstream (the `prefers-higher-direction` fixed tags on both
5041 /// surfaces in tatara-check, future asymptotic-health rate-window
5042 /// / regression-detector evaluators, future variant additions on
5043 /// [`crate::classification::OptimizationDirection`]) binds through
5044 /// the SAME `direction_prefers_higher()` shape rather than
5045 /// restating either the resolver walk or the closed-set projection
5046 /// composition at the callsite. THEORY.md §VI.1 — generation over
5047 /// composition; a future
5048 /// [`crate::classification::OptimizationDirection`] variant lands
5049 /// at ONE `ALL` entry + ONE `prefers_higher` arm on the closed set
5050 /// and both surfaces pick it up mechanically.
5051 #[must_use]
5052 pub fn direction_prefers_higher(&self) -> bool {
5053 self.resolved_classification().direction_prefers_higher()
5054 }
5055
5056 /// Derived-boolean predicate — does this ephemeral spec's resolved
5057 /// [`Classification`]'s `point_type` slot project to `Arity::One`
5058 /// under
5059 /// [`crate::classification::ConvergencePointType::input_arity`]?
5060 /// Byte-for-byte peer of
5061 /// [`crate::classification::Classification::input_arity_is_one`]
5062 /// wrapped through the [`Self::resolved_classification`] resolver
5063 /// so an operator-omitted `:classification` slot on
5064 /// `(defephemeral …)` still answers via the substrate default. The
5065 /// ONE ephemeral-surface substrate primitive that owns the
5066 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5067 /// single-input side of the DAG-composition input-arity projection.
5068 ///
5069 /// # Sixteenth derived-nullary-boolean peer on the ephemeral surface — opens the input-arity axis
5070 ///
5071 /// Peer of the fifteen prior nullary-boolean substrate primitives
5072 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5073 /// [`Self::horizon_requires_metric_axes`],
5074 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5075 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5076 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5077 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5078 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5079 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5080 /// [`Self::direction_prefers_higher`]) on the ephemeral surface's
5081 /// (resolver-hop × derived-nullary-bool) shape — the SIXTEENTH
5082 /// peer overall and the FIRST peer threading the classification-
5083 /// `point_type`-derived input-arity axis on this surface. Opens
5084 /// the SEVENTH classification axis into the ephemeral fixed-tag
5085 /// algebra after the horizon, calm, data, point-type, substrate,
5086 /// and optimization-direction axes. First peer on the derived-
5087 /// typed-projection stratum of the ephemeral surface — composes
5088 /// an extra closed-set-level projection hop
5089 /// ([`crate::classification::ConvergencePointType::input_arity`])
5090 /// compared to the sibling `point_is_*` triple that walks the raw
5091 /// `point_type` slot through the resolver. The resolver-hop shape
5092 /// is byte-identical across all sixteen peers.
5093 ///
5094 /// # Semantics — resolver hop + derived-nullary-boolean
5095 ///
5096 /// `input_arity_is_one()` returns `true` iff
5097 /// `self.resolved_classification().input_arity_is_one()`. The
5098 /// resolver returns the authored [`Classification`] when present
5099 /// and the substrate default [`Classification::gate_compute`] on
5100 /// absence. Because [`Classification::gate_compute`] carries
5101 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
5102 /// ephemeral spec with no `:classification` slot answers `false` —
5103 /// every unadorned `(defephemeral …)` lands in the multi-input
5104 /// bucket under the substrate default (`Gate` gates a
5105 /// many-to-one bucket dispatch, so the single-input bucket only
5106 /// applies to operator-authored specs on the `Transform | Fork |
5107 /// Broadcast | Observe` arms). A regression that dropped the
5108 /// resolver hop, probed the wrong closed-set arm, or crossed the
5109 /// wires with the sibling
5110 /// [`crate::classification::ConvergencePointType::output_arity`]
5111 /// projection (which disagrees on six of the eight variants) fails
5112 /// HERE at ONE narrow substrate site before drifting through
5113 /// every unadorned ephemeral spec's DAG-composition input-arity
5114 /// audit.
5115 ///
5116 /// # Compounding — opens the input-arity axis on the ephemeral surface
5117 ///
5118 /// The ephemeral require-tag classifier will compose this
5119 /// primitive as a fixed tag `single-input-arity` on
5120 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5121 /// surface's `single-input-arity` fixed tag on
5122 /// `POINT_FIXED_TAG_ARMS` via
5123 /// [`Classification::input_arity_is_one`] directly. The
5124 /// two-surface parity contract holds by construction: both
5125 /// surfaces route through the SAME
5126 /// [`Classification::input_arity_is_one`] primitive after the
5127 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
5128 /// peer ([`Self::input_arity_is_many`]) closes the binary XOR
5129 /// partition on this axis — mirror of the calm-axis
5130 /// (`monotone-calm ⊕ coordination-required`), data-axis
5131 /// (`public-data ⊕ data-restricted`), and optimization-direction-
5132 /// axis (`prefers-lower-direction ⊕ prefers-higher-direction`)
5133 /// closures on this surface.
5134 ///
5135 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5136 /// preserves proofs; the classification-`point_type`-derived
5137 /// input-arity-axis derived-nullary-boolean probe body composes
5138 /// ONE resolver primitive ([`Self::resolved_classification`])
5139 /// with ONE [`Classification`] primitive
5140 /// ([`Classification::input_arity_is_one`]) so every downstream
5141 /// (the future `single-input-arity` fixed tag on the ephemeral
5142 /// surface in tatara-check, future DAG-composition input-arity
5143 /// validators keying on the single-input framing, future variant
5144 /// additions on
5145 /// [`crate::classification::ConvergencePointType`]) binds through
5146 /// the SAME `input_arity_is_one()` shape rather than restating
5147 /// either the resolver walk or the two-hop closed-set projection
5148 /// composition at the callsite. THEORY.md §VI.1 — generation over
5149 /// composition; a future
5150 /// [`crate::classification::ConvergencePointType`] variant lands
5151 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
5152 /// and both surfaces pick it up mechanically.
5153 #[must_use]
5154 pub fn input_arity_is_one(&self) -> bool {
5155 self.resolved_classification().input_arity_is_one()
5156 }
5157
5158 /// ANTISYMMETRIC PEER of [`Self::input_arity_is_one`] — does
5159 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
5160 /// slot project to `Arity::Many` under
5161 /// [`crate::classification::ConvergencePointType::input_arity`]?
5162 /// Byte-for-byte peer of
5163 /// [`crate::classification::Classification::input_arity_is_many`]
5164 /// wrapped through the [`Self::resolved_classification`] resolver
5165 /// so an operator-omitted `:classification` slot on
5166 /// `(defephemeral …)` still answers via the substrate default. The
5167 /// ONE ephemeral-surface substrate primitive that owns the
5168 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5169 /// multi-input side of the DAG-composition input-arity projection.
5170 ///
5171 /// # Seventeenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the input-arity axis
5172 ///
5173 /// Peer of the sixteen prior nullary-boolean substrate primitives
5174 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5175 /// [`Self::horizon_requires_metric_axes`],
5176 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5177 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5178 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5179 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5180 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5181 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5182 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`])
5183 /// on the ephemeral surface's (resolver-hop × derived-nullary-
5184 /// bool) shape — the SEVENTEENTH peer overall and the SECOND peer
5185 /// threading the classification-`point_type`-derived input-arity
5186 /// axis on this surface. CLOSES the SEVENTH classification axis
5187 /// into the FULL binary XOR partition contract
5188 /// `input_arity_is_one ⊕ input_arity_is_many` on the ephemeral
5189 /// surface — the resolver-hop peer of the parent-composed
5190 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`.
5191 /// The resolver-hop shape is byte-identical across all seventeen
5192 /// peers.
5193 ///
5194 /// # Semantics — resolver hop + derived-nullary-boolean
5195 ///
5196 /// `input_arity_is_many()` returns `true` iff
5197 /// `self.resolved_classification().input_arity_is_many()`. The
5198 /// resolver returns the authored [`Classification`] when present
5199 /// and the substrate default [`Classification::gate_compute`] on
5200 /// absence. Because [`Classification::gate_compute`] carries
5201 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
5202 /// ephemeral spec with no `:classification` slot answers `true` —
5203 /// every unadorned `(defephemeral …)` lands in the multi-input
5204 /// bucket under the substrate default. Direct antisymmetric
5205 /// mirror of [`Self::input_arity_is_one`] on the SAME resolver
5206 /// walk + SAME projection through the SAME closed set.
5207 ///
5208 /// # Compounding — CLOSES the input-arity axis on the ephemeral surface
5209 ///
5210 /// The ephemeral require-tag classifier will compose this
5211 /// primitive as a fixed tag `multi-input-arity` on
5212 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5213 /// surface's `multi-input-arity` fixed tag on
5214 /// `POINT_FIXED_TAG_ARMS` via
5215 /// [`Classification::input_arity_is_many`] directly. The
5216 /// two-surface parity contract holds by construction: both
5217 /// surfaces route through the SAME
5218 /// [`Classification::input_arity_is_many`] primitive after the
5219 /// ephemeral surface pays ONE resolver hop. SECOND input-arity-
5220 /// axis peer CLOSES the axis into the FULL binary XOR partition
5221 /// contract on this surface — the resolver-hop peer of the
5222 /// parent-composed
5223 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`,
5224 /// mirror of the calm-axis (`monotone-calm ⊕
5225 /// coordination-required`), data-axis (`public-data ⊕
5226 /// data-restricted`), and optimization-direction-axis
5227 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
5228 /// closures on this surface — the SEVENTH classification axis to
5229 /// reach the closed XOR partition landmark on the ephemeral
5230 /// resolver-hop surface, opening the derived-typed-projection
5231 /// stratum on this surface for the first time.
5232 ///
5233 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5234 /// preserves proofs; the classification-`point_type`-derived
5235 /// input-arity-axis derived-nullary-boolean probe body composes
5236 /// ONE resolver primitive ([`Self::resolved_classification`])
5237 /// with ONE [`Classification`] primitive
5238 /// ([`Classification::input_arity_is_many`]) so every downstream
5239 /// (the future `multi-input-arity` fixed tag on the ephemeral
5240 /// surface in tatara-check, future DAG-composition input-arity
5241 /// validators keying on the multi-input framing, future variant
5242 /// additions on
5243 /// [`crate::classification::ConvergencePointType`]) binds through
5244 /// the SAME `input_arity_is_many()` shape rather than restating
5245 /// either `!self.input_arity_is_one()` or the two-hop
5246 /// `self.resolved_classification().point_type.input_arity().is_many()`
5247 /// chain at each callsite. THEORY.md §VI.1 — generation over
5248 /// composition; a future
5249 /// [`crate::classification::ConvergencePointType`] variant lands
5250 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
5251 /// and both surfaces pick it up mechanically.
5252 #[must_use]
5253 pub fn input_arity_is_many(&self) -> bool {
5254 self.resolved_classification().input_arity_is_many()
5255 }
5256
5257 /// Derived-boolean predicate — does this ephemeral spec's resolved
5258 /// [`Classification`]'s `point_type` slot project to `Arity::One`
5259 /// under
5260 /// [`crate::classification::ConvergencePointType::output_arity`]?
5261 /// Byte-for-byte peer of
5262 /// [`crate::classification::Classification::output_arity_is_one`]
5263 /// wrapped through the [`Self::resolved_classification`] resolver
5264 /// so an operator-omitted `:classification` slot on
5265 /// `(defephemeral …)` still answers via the substrate default. The
5266 /// ONE ephemeral-surface substrate primitive that owns the
5267 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5268 /// single-output side of the DAG-composition output-arity projection.
5269 ///
5270 /// # Eighteenth derived-nullary-boolean peer on the ephemeral surface — opens the output-arity axis
5271 ///
5272 /// Peer of the seventeen prior nullary-boolean substrate primitives
5273 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5274 /// [`Self::horizon_requires_metric_axes`],
5275 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5276 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5277 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5278 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5279 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5280 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5281 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
5282 /// [`Self::input_arity_is_many`]) on the ephemeral surface's
5283 /// (resolver-hop × derived-nullary-bool) shape — the EIGHTEENTH
5284 /// peer overall and the FIRST peer threading the classification-
5285 /// `point_type`-derived OUTPUT-arity axis on this surface. Opens
5286 /// the EIGHTH classification axis into the ephemeral fixed-tag
5287 /// algebra after the horizon, calm, data, point-type, substrate,
5288 /// optimization-direction, and input-arity axes. SECOND peer on
5289 /// the derived-typed-projection stratum of the ephemeral surface
5290 /// (after [`Self::input_arity_is_one`]) — composes an extra
5291 /// closed-set-level projection hop
5292 /// ([`crate::classification::ConvergencePointType::output_arity`])
5293 /// compared to the sibling `point_is_*` triple that walks the raw
5294 /// `point_type` slot through the resolver. The resolver-hop shape
5295 /// is byte-identical across all eighteen peers.
5296 ///
5297 /// # Distinctness from the input-arity axis
5298 ///
5299 /// The input-arity and output-arity axes carve the eight-variant
5300 /// [`crate::classification::ConvergencePointType`] closed set into
5301 /// DISTINCT partitions — six of the eight variants (`Fork |
5302 /// Broadcast | Join | Gate | Select | Reduce`) DISAGREE between the
5303 /// two projections, and only the two endomorphic variants
5304 /// (`Transform | Observe` — both `(One, One)`) agree. The ephemeral
5305 /// resolver-hop surface inherits this distinctness verbatim: the
5306 /// absent-classification baseline (`gate_compute` → `point_type:
5307 /// Gate`) FLIPS between the two axes — `input_arity_is_one` is
5308 /// `false` on the baseline but `output_arity_is_one` is `true`.
5309 /// So `output_arity_is_one` is NOT a redundant restatement of
5310 /// `input_arity_is_one` even after both wrap through the SAME
5311 /// resolver.
5312 ///
5313 /// # Semantics — resolver hop + derived-nullary-boolean
5314 ///
5315 /// `output_arity_is_one()` returns `true` iff
5316 /// `self.resolved_classification().output_arity_is_one()`. The
5317 /// resolver returns the authored [`Classification`] when present
5318 /// and the substrate default [`Classification::gate_compute`] on
5319 /// absence. Because [`Classification::gate_compute`] carries
5320 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5321 /// ephemeral spec with no `:classification` slot answers `true` —
5322 /// every unadorned `(defephemeral …)` lands in the single-output
5323 /// bucket under the substrate default (`Gate` gates a many-to-one
5324 /// bucket dispatch, so the multi-output bucket only applies to
5325 /// operator-authored specs on the `Fork | Broadcast` arms). A
5326 /// regression that dropped the resolver hop, probed the wrong
5327 /// closed-set arm, or crossed the wires with the sibling
5328 /// [`crate::classification::ConvergencePointType::input_arity`]
5329 /// projection (which disagrees on six of the eight variants) fails
5330 /// HERE at ONE narrow substrate site before drifting through every
5331 /// unadorned ephemeral spec's DAG-composition output-arity audit.
5332 ///
5333 /// # Compounding — opens the output-arity axis on the ephemeral surface
5334 ///
5335 /// The ephemeral require-tag classifier will compose this
5336 /// primitive as a fixed tag `single-output-arity` on
5337 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5338 /// surface's `single-output-arity` fixed tag on
5339 /// `POINT_FIXED_TAG_ARMS` via
5340 /// [`Classification::output_arity_is_one`] directly. The
5341 /// two-surface parity contract holds by construction: both
5342 /// surfaces route through the SAME
5343 /// [`Classification::output_arity_is_one`] primitive after the
5344 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
5345 /// peer ([`Self::output_arity_is_many`]) closes the binary XOR
5346 /// partition on this axis — mirror of the input-arity-axis
5347 /// (`input_arity_is_one ⊕ input_arity_is_many`), the calm-axis
5348 /// (`monotone-calm ⊕ coordination-required`), the data-axis
5349 /// (`public-data ⊕ data-restricted`), and the optimization-
5350 /// direction-axis (`prefers-lower-direction ⊕
5351 /// prefers-higher-direction`) closures on this surface,
5352 /// completing the DAG-composition arity PAIR on the ephemeral
5353 /// derived-typed-projection stratum.
5354 ///
5355 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5356 /// preserves proofs; the classification-`point_type`-derived
5357 /// output-arity-axis derived-nullary-boolean probe body composes
5358 /// ONE resolver primitive ([`Self::resolved_classification`])
5359 /// with ONE [`Classification`] primitive
5360 /// ([`Classification::output_arity_is_one`]) so every downstream
5361 /// (the future `single-output-arity` fixed tag on the ephemeral
5362 /// surface in tatara-check, future DAG-composition output-arity
5363 /// validators keying on the single-output framing, future variant
5364 /// additions on
5365 /// [`crate::classification::ConvergencePointType`]) binds through
5366 /// the SAME `output_arity_is_one()` shape rather than restating
5367 /// either the resolver walk or the two-hop closed-set projection
5368 /// composition at the callsite. THEORY.md §VI.1 — generation over
5369 /// composition; a future
5370 /// [`crate::classification::ConvergencePointType`] variant lands
5371 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
5372 /// and both surfaces pick it up mechanically.
5373 #[must_use]
5374 pub fn output_arity_is_one(&self) -> bool {
5375 self.resolved_classification().output_arity_is_one()
5376 }
5377
5378 /// ANTISYMMETRIC PEER of [`Self::output_arity_is_one`] — does
5379 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
5380 /// slot project to `Arity::Many` under
5381 /// [`crate::classification::ConvergencePointType::output_arity`]?
5382 /// Byte-for-byte peer of
5383 /// [`crate::classification::Classification::output_arity_is_many`]
5384 /// wrapped through the [`Self::resolved_classification`] resolver
5385 /// so an operator-omitted `:classification` slot on
5386 /// `(defephemeral …)` still answers via the substrate default. The
5387 /// ONE ephemeral-surface substrate primitive that owns the
5388 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5389 /// multi-output side of the DAG-composition output-arity projection.
5390 ///
5391 /// # Nineteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the output-arity axis
5392 ///
5393 /// Peer of the eighteen prior nullary-boolean substrate primitives
5394 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5395 /// [`Self::horizon_requires_metric_axes`],
5396 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5397 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5398 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5399 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5400 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5401 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5402 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
5403 /// [`Self::input_arity_is_many`], [`Self::output_arity_is_one`])
5404 /// on the ephemeral surface's (resolver-hop × derived-nullary-
5405 /// bool) shape — the NINETEENTH peer overall and the SECOND peer
5406 /// threading the classification-`point_type`-derived OUTPUT-arity
5407 /// axis on this surface. CLOSES the EIGHTH classification axis
5408 /// into the FULL binary XOR partition contract
5409 /// `output_arity_is_one ⊕ output_arity_is_many` on the ephemeral
5410 /// surface — the resolver-hop peer of the parent-composed
5411 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`.
5412 /// The resolver-hop shape is byte-identical across all nineteen
5413 /// peers. Completes the DAG-composition arity PAIR on the
5414 /// ephemeral derived-typed-projection stratum
5415 /// (`input_arity_is_{one,many}` + `output_arity_is_{one,many}` on
5416 /// the SAME resolver walk through the SAME closed set).
5417 ///
5418 /// # Semantics — resolver hop + derived-nullary-boolean
5419 ///
5420 /// `output_arity_is_many()` returns `true` iff
5421 /// `self.resolved_classification().output_arity_is_many()`. The
5422 /// resolver returns the authored [`Classification`] when present
5423 /// and the substrate default [`Classification::gate_compute`] on
5424 /// absence. Because [`Classification::gate_compute`] carries
5425 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5426 /// ephemeral spec with no `:classification` slot answers `false` —
5427 /// every unadorned `(defephemeral …)` lands in the single-output
5428 /// bucket under the substrate default. Direct antisymmetric
5429 /// mirror of [`Self::output_arity_is_one`] on the SAME resolver
5430 /// walk + SAME projection through the SAME closed set.
5431 ///
5432 /// # Compounding — CLOSES the output-arity axis on the ephemeral surface
5433 ///
5434 /// The ephemeral require-tag classifier will compose this
5435 /// primitive as a fixed tag `multi-output-arity` on
5436 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5437 /// surface's `multi-output-arity` fixed tag on
5438 /// `POINT_FIXED_TAG_ARMS` via
5439 /// [`Classification::output_arity_is_many`] directly. The
5440 /// two-surface parity contract holds by construction: both
5441 /// surfaces route through the SAME
5442 /// [`Classification::output_arity_is_many`] primitive after the
5443 /// ephemeral surface pays ONE resolver hop. SECOND output-arity-
5444 /// axis peer CLOSES the axis into the FULL binary XOR partition
5445 /// contract on this surface — the resolver-hop peer of the
5446 /// parent-composed
5447 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`,
5448 /// mirror of the input-arity-axis (`input_arity_is_one ⊕
5449 /// input_arity_is_many`), the calm-axis (`monotone-calm ⊕
5450 /// coordination-required`), the data-axis (`public-data ⊕
5451 /// data-restricted`), and the optimization-direction-axis
5452 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
5453 /// closures on this surface — the EIGHTH classification axis to
5454 /// reach the closed XOR partition landmark on the ephemeral
5455 /// resolver-hop surface, completing the DAG-composition arity
5456 /// PAIR on the derived-typed-projection stratum of this surface.
5457 ///
5458 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5459 /// preserves proofs; the classification-`point_type`-derived
5460 /// output-arity-axis derived-nullary-boolean probe body composes
5461 /// ONE resolver primitive ([`Self::resolved_classification`])
5462 /// with ONE [`Classification`] primitive
5463 /// ([`Classification::output_arity_is_many`]) so every downstream
5464 /// (the future `multi-output-arity` fixed tag on the ephemeral
5465 /// surface in tatara-check, future DAG-composition output-arity
5466 /// validators keying on the multi-output framing, future variant
5467 /// additions on
5468 /// [`crate::classification::ConvergencePointType`]) binds through
5469 /// the SAME `output_arity_is_many()` shape rather than restating
5470 /// either `!self.output_arity_is_one()` or the two-hop
5471 /// `self.resolved_classification().point_type.output_arity().is_many()`
5472 /// chain at each callsite. THEORY.md §VI.1 — generation over
5473 /// composition; a future
5474 /// [`crate::classification::ConvergencePointType`] variant lands
5475 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
5476 /// and both surfaces pick it up mechanically.
5477 #[must_use]
5478 pub fn output_arity_is_many(&self) -> bool {
5479 self.resolved_classification().output_arity_is_many()
5480 }
5481
5482 /// True iff this ephemeral spec's [`Self::routing`] slot is
5483 /// populated AND the inner [`RoutingSpec`]'s derived
5484 /// [`RoutingForm`] equals `kind` — the substrate primitive that
5485 /// owns the (`&EphemeralSpec`, [`RoutingForm`]) → `bool` presence-
5486 /// probe shape on the sugar-surface type.
5487 ///
5488 /// # Peer to [`crate::routing::RoutingSpec::has_form`]
5489 ///
5490 /// [`RoutingSpec::has_form`] carries the same `(&self, RoutingForm)
5491 /// -> bool` signature on the inner routing carrier reached through
5492 /// the Option gate; this peer composes byte-identical semantics on
5493 /// [`EphemeralSpec`]'s direct `routing: Option<RoutingSpec>` slot,
5494 /// so both surfaces' `routing-form-<kind>` require-tag families
5495 /// route through the SAME `RoutingSpec::has_form` primitive. A
5496 /// future normalization at the probe shape (a widened return
5497 /// carrying the derived [`RoutingForm`] variant, a debug-build
5498 /// assertion on operator-set vs defaulted overrides on the
5499 /// `stable_name_claim` bool, a fleet-wide warn on `Stable`
5500 /// combined with content-hashed hostnames) lands at ONE site per
5501 /// surface and every downstream `routing-form-<kind>` require-tag
5502 /// family + closed-set audit dispatcher picks it up mechanically.
5503 ///
5504 /// # Semantics — Option-gated derived-scalar match
5505 ///
5506 /// [`EphemeralSpec::routing`] is an `Option<RoutingSpec>`: `None`
5507 /// on an in-cluster-only ephemeral env (no per-instance edges
5508 /// declared), `Some(_)` when the operator authored the
5509 /// `:routing (…)` slot. `has_routing_form(kind)` returns `true`
5510 /// iff the slot is `Some(spec)` AND `spec.has_form(kind)` — the
5511 /// Option-parent gate short-circuits `false` on `None` regardless
5512 /// of `kind`, and the reachable arm reads the DERIVED
5513 /// [`RoutingForm`] through the ONE substrate composer
5514 /// [`RoutingForm::from_is_stable`] over the child
5515 /// `stable_name_claim` bool (a `false` default projects to
5516 /// [`RoutingForm::Instance`], a `true` operator override projects
5517 /// to [`RoutingForm::Stable`]).
5518 ///
5519 /// # Corner — (Option-parent × derived-scalar-child)
5520 ///
5521 /// SAME corner as the point surface's `routing-form-<kind>`
5522 /// family (via [`crate::routing::RoutingSpec::has_form`] reached
5523 /// through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`)
5524 /// — both surfaces' Option-parent hop threads through the SAME
5525 /// `Option<RoutingSpec>` field name on their respective sugar
5526 /// structs. The [`From<EphemeralSpec>`] lowering copies
5527 /// `e.routing → ProcessSpec::routing` byte-for-byte at the
5528 /// [`From`] impl in this module (see the `routing: e.routing`
5529 /// line), so the SAME `Option<RoutingSpec>` reaches both
5530 /// surfaces' `routing-form-<kind>` families through the SAME
5531 /// [`RoutingSpec::has_form`] walk. Distinct from
5532 /// [`Self::has_teardown_policy`] on this same surface, which
5533 /// walks a required-scalar-child through no Option-parent hop.
5534 ///
5535 /// # Compounding
5536 ///
5537 /// The ephemeral require-tag classifier composes this primitive
5538 /// with the closed-set `FromStr` autoderived on [`RoutingForm`]
5539 /// through the `strip_and_classify_prefixed_kind` substrate to
5540 /// publish a `routing-form-<kind>` prefix family byte-for-byte
5541 /// symmetrical with the point surface's family via
5542 /// [`crate::routing::RoutingSpec::has_form`]. A future third
5543 /// [`RoutingForm`] variant added to `ALL` (a hypothetical
5544 /// `Anchored` for "hold the claim only for a specific
5545 /// generation") reaches BOTH surfaces' `routing-form-<kind>`
5546 /// prefix families through the SAME closed-set walk with no
5547 /// per-caller edit — the two-surface symmetry means adding a
5548 /// variant on the closed set publishes it in lockstep across
5549 /// every downstream consumer.
5550 ///
5551 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
5552 /// preserves proofs — the Option-gated derived-scalar-carrier
5553 /// presence-probe body lives at ONE substrate site per surface
5554 /// so every downstream (`routing-form-<kind>` require-tag families
5555 /// on both surfaces in tatara-check, closed-set audit dispatchers,
5556 /// future variant additions on [`RoutingForm`]) binds through the
5557 /// SAME `has(kind)` shape rather than restating the
5558 /// `spec.routing.as_ref().is_some_and(|r| r.has_form(kind))`
5559 /// closure body at each call site). THEORY.md §VI.1 (generation
5560 /// over composition — a future variant lands at ONE `ALL` entry +
5561 /// one `as_str` arm on the closed set and the probe picks it up
5562 /// mechanically without further per-consumer edits).
5563 #[must_use]
5564 pub fn has_routing_form(&self, kind: RoutingForm) -> bool {
5565 self.routing.as_ref().is_some_and(|r| r.has_form(kind))
5566 }
5567
5568 /// True iff at least one declared export in `self.exports` would
5569 /// fire on the given terminal-reached [`ProcessPhase`] — the peer
5570 /// of [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5571 /// on the [`EphemeralSpec`] surface.
5572 ///
5573 /// # Semantics — byte-identical to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5574 ///
5575 /// Both surfaces walk the SAME slice-level substrate primitive
5576 /// [`ExportSpecSliceExt::has_applicable_at`] on their respective
5577 /// `Vec<ExportSpec>` slot: [`EphemeralSpec`]'s `exports` field is
5578 /// copied byte-for-byte into `EphemeralLifetime::exports` at the
5579 /// `From<EphemeralSpec>` lowering, so a `has_applicable_exports_at`
5580 /// query on the authored ephemeral spec answers identically to a
5581 /// `has_applicable_exports` query on the lowered `EphemeralLifetime`.
5582 /// A regression at the compound `(when, phase) → fires_on(phase)`
5583 /// walk fails at [`ExportSpecSliceExt::has_applicable_at`]'s tests
5584 /// rather than as silent drift at either surface's inherent method.
5585 ///
5586 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5587 ///
5588 /// Same shape, same axis, same body — the point-domain surface
5589 /// composes through `spec.lifetime.resolved_ephemeral().is_some_and(
5590 /// |e| e.exports.has_applicable_at(phase))`; the ephemeral sugar
5591 /// surface reads `self.exports.has_applicable_at(phase)` directly
5592 /// because `EphemeralSpec` stores `exports: Vec<ExportSpec>` as a
5593 /// top-level field. Both routes bind through THIS ONE slice-level
5594 /// primitive so a future normalization (widening the trigger from
5595 /// a stored discriminator to a computed predicate, adding a phase
5596 /// that composes across multiple trigger arms, threading a
5597 /// per-export justification back for editor tooltips) lands at ONE
5598 /// site and every downstream inherits the shift by construction.
5599 ///
5600 /// # Compounding
5601 ///
5602 /// The ephemeral require-tag classifier composes this primitive
5603 /// with the closed-set [`ProcessPhase`]'s autoderived `FromStr`
5604 /// through the `strip_and_classify_prefixed_kind` substrate to
5605 /// publish an `exports-fire-on-<phase>` closed-set prefix family
5606 /// byte-for-byte symmetrical with the point surface's family via
5607 /// `spec.lifetime.resolved_ephemeral().is_some_and(|e|
5608 /// e.exports.has_applicable_at(phase))`. A future twelfth
5609 /// [`ProcessPhase`] variant reaches BOTH surfaces' prefix families
5610 /// through the ONE [`crate::export::ExportTrigger::fires_on`]
5611 /// exhaustive match — either the new phase inherits a per-trigger
5612 /// fire rule at that single substrate site or it collapses to
5613 /// `false` for every trigger (the current non-terminal tail),
5614 /// without a per-caller edit anywhere else.
5615 ///
5616 /// A future normalization at the compound `(when, phase) →
5617 /// fires_on(phase)` walk (a widening that returns the applicable
5618 /// exports themselves rather than a bool, a debug-build assertion
5619 /// on redundant `Always`-triggered exports coexisting with an
5620 /// `OnAttested` peer, a fleet-wide warn on empty-export ephemerals
5621 /// declaring `OnAttested` postconditions) lands at the ONE
5622 /// slice-level substrate primitive [`ExportSpecSliceExt::has_applicable_at`]
5623 /// both this method and [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5624 /// compose against — so the two struct-level union methods stay
5625 /// symmetric by construction.
5626 ///
5627 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
5628 /// proofs — the walk composes the SAME slice-level substrate
5629 /// primitive on both this ephemeral surface and the
5630 /// [`crate::lifetime::EphemeralLifetime`] surface, so a regression
5631 /// at the compound `(when, phase) → fires_on(phase)` chain fails
5632 /// at ONE site rather than as silent drift between the two peers).
5633 /// THEORY.md §VI.1 (generation over composition — a future
5634 /// [`ProcessPhase`] variant or a future [`crate::export::ExportTrigger`]
5635 /// variant reaches both `exports-fire-on-<phase>` require-tag
5636 /// surfaces mechanically through the SAME closed-set walk).
5637 #[must_use]
5638 pub fn has_applicable_exports_at(&self, phase: ProcessPhase) -> bool {
5639 self.exports.has_applicable_at(phase)
5640 }
5641}
5642
5643impl From<EphemeralSpec> for ProcessSpec {
5644 fn from(e: EphemeralSpec) -> Self {
5645 let classification = e.classification.unwrap_or_else(default_ephemeral_class);
5646 let mut spec = Self {
5647 identity: crate::spec::IdentitySpec {
5648 parent: e.parent,
5649 name_override: None,
5650 },
5651 classification,
5652 intent: Intent {
5653 aplicacao: Some(e.aplicacao),
5654 ..Intent::default()
5655 },
5656 boundary: Boundary {
5657 preconditions: e.preconditions,
5658 postconditions: e.postconditions,
5659 timeout: e.verify_timeout,
5660 },
5661 compliance: Default::default(),
5662 depends_on: vec![],
5663 signals: Default::default(),
5664 // Routes through the ONE substrate composer
5665 // [`Lifetime::ephemeral`] — pre-lift this was one of
5666 // ELEVEN+ hand-authored `Lifetime { ephemeral: Some(<e>),
5667 // .. }` sites past the ★★ PRIME-DIRECTIVE ≥ 2 threshold.
5668 // See the composer's doc-comment for the full migration
5669 // rationale.
5670 lifetime: Lifetime::ephemeral(EphemeralLifetime {
5671 ttl: e.ttl,
5672 teardown_policy: e.teardown,
5673 max_concurrent: e.max_concurrent,
5674 exports: e.exports,
5675 }),
5676 // R5 — propagate routing template (None = no edges).
5677 routing: e.routing,
5678 // EncapsulatesSpec isn't exposed via EphemeralSpec sugar;
5679 // operators wanting Adopt/Observe author the full
5680 // (defpoint …) form. Sugar path stays greenfield-Manage.
5681 encapsulates: None,
5682 suspended: false,
5683 };
5684 // Belt-and-suspenders: make sure exactly-one Intent invariant holds.
5685 spec.intent.nix = None;
5686 spec.intent.flux = None;
5687 spec.intent.lisp = None;
5688 spec.intent.container = None;
5689 spec.intent.guest = None;
5690 spec
5691 }
5692}
5693
5694fn default_ephemeral_class() -> Classification {
5695 // Delegates through the substrate `(Gate, Compute)` baseline owner
5696 // so the shape lives at ONE workspace-wide site — see
5697 // [`Classification::gate_compute`] for the pre-lift ten-callsite
5698 // duplication history and the sibling-default correspondence
5699 // pinned there.
5700 Classification::gate_compute()
5701}
5702
5703/// Compile a `(defephemeral …)` Lisp source into named `EphemeralSpec` values.
5704pub fn compile_ephemeral_source(
5705 src: &str,
5706) -> tatara_lisp::Result<Vec<tatara_lisp::NamedDefinition<EphemeralSpec>>> {
5707 tatara_lisp::compile_named::<EphemeralSpec>(src)
5708}
5709
5710#[cfg(test)]
5711mod tests {
5712 use super::*;
5713 use crate::boundary::{assert_slice_refinement_composition_laws, ConditionKind};
5714 use crate::classification::{
5715 Arity, CalmClassification, ConvergencePointType, DataClassification, Horizon, HorizonKind,
5716 OptimizationDirection, SubstrateType,
5717 };
5718 use crate::intent::IntentVariant;
5719 use crate::lifetime::LifetimeVariant;
5720
5721 /// LANDMARK PIN — the (ephemeral-surface test-fixture ×
5722 /// [`Classification::gate_compute_with_axis`] on horizon-nested
5723 /// axes) sweep equivalence. Nine ephemeral-surface probe-sweep
5724 /// tests in this module (`has_horizon_kind_*`,
5725 /// `has_optimization_direction_*`, `horizon_terminates_*`,
5726 /// `horizon_requires_metric_axes_*`, `horizon_terminates_xor_*`)
5727 /// pre-sweep restated the SAME `let mut c =
5728 /// Classification::gate_compute(); c.horizon = Horizon { <slot>:
5729 /// populated, ..Horizon::default() }` five-line fixture at each
5730 /// callsite, mutating exactly ONE horizon-nested slot to
5731 /// `populated`; post-sweep each callsite reads
5732 /// [`Classification::gate_compute_with_axis(populated)`] — one
5733 /// line — and the four-baseline-slot restatement lives at ONE
5734 /// substrate primitive. This pin asserts byte-parity between the
5735 /// pre-sweep hand-authored `Horizon` struct-literal shape (both
5736 /// the [`HorizonKind::kind`] mutation shape AND the
5737 /// [`OptimizationDirection`]-into-`Some(_)` mutation shape) and
5738 /// the post-sweep composer output on every variant of each closed
5739 /// set, so a regression that either (a) changed
5740 /// [`ClassificationAxis for HorizonKind`] to stomp a non-`kind`
5741 /// sub-slot, (b) changed [`ClassificationAxis for OptimizationDirection`]
5742 /// to drop the `Some(...)` wrap, or (c) reintroduced a whole-
5743 /// `Horizon`-reset shape that dropped a sibling sub-slot would
5744 /// fail HERE at ONE landmark site before landing at the peer
5745 /// probe-sweep pins that use the composer.
5746 ///
5747 /// Byte-for-byte peer of the sibling landmark
5748 /// `with_axis_optimization_direction_overlay_wraps_variant_in_some`
5749 /// on the point-surface classification-module tests — this pin
5750 /// carries the same substrate contract through to the ephemeral-
5751 /// surface tests that consume the composer.
5752 #[test]
5753 fn gate_compute_with_axis_on_horizon_nested_axes_matches_hand_authored_shape() {
5754 for kind in HorizonKind::ALL {
5755 let via_composer = Classification::gate_compute_with_axis(kind);
5756 let mut via_hand_authored = Classification::gate_compute();
5757 via_hand_authored.horizon = Horizon {
5758 kind,
5759 ..Horizon::default()
5760 };
5761 assert_eq!(
5762 via_composer, via_hand_authored,
5763 "HorizonKind::{kind:?}: composer vs pre-sweep hand-authored struct-literal drift",
5764 );
5765 }
5766 for direction in OptimizationDirection::ALL {
5767 let via_composer = Classification::gate_compute_with_axis(direction);
5768 let mut via_hand_authored = Classification::gate_compute();
5769 via_hand_authored.horizon = Horizon {
5770 direction: Some(direction),
5771 ..Horizon::default()
5772 };
5773 assert_eq!(
5774 via_composer, via_hand_authored,
5775 "OptimizationDirection::{direction:?}: composer vs pre-sweep hand-authored struct-literal drift",
5776 );
5777 }
5778 }
5779
5780 /// Primitive-owner pin — `EphemeralSpec::with_classification_axis`
5781 /// on a `classification: None` carrier produces an ephemeral spec
5782 /// whose `classification` slot is
5783 /// `Some(Classification::gate_compute_with_axis(axis))` byte-for-
5784 /// byte on every axis-variant, and preserves every non-
5785 /// classification slot at its pre-call value. A regression that
5786 /// (a) failed to wrap the composed [`Classification`] in `Some(_)`
5787 /// on the `None`-arm, (b) mutated a sibling slot on `EphemeralSpec`
5788 /// through the axis overlay, or (c) picked a different `None`-arm
5789 /// fill-through than the sibling
5790 /// [`Self::resolved_classification`] resolver would fail HERE.
5791 #[test]
5792 fn with_classification_axis_on_none_arm_fills_through_gate_compute() {
5793 fn baseline() -> EphemeralSpec {
5794 EphemeralSpec {
5795 aplicacao: demo_overlay(),
5796 ttl: "2h".into(),
5797 teardown: TeardownPolicy::OnAttested,
5798 max_concurrent: 3,
5799 postconditions: vec![],
5800 preconditions: vec![],
5801 verify_timeout: Some("30m".into()),
5802 classification: None,
5803 parent: Some("seph.1".into()),
5804 exports: vec![],
5805 routing: None,
5806 }
5807 }
5808 // Direct-scalar axes: composer output matches
5809 // `Classification::gate_compute_with_axis(axis)` byte-for-byte,
5810 // wrapped in `Some(_)`.
5811 for kind in ConvergencePointType::ALL {
5812 let via_composer = baseline().with_classification_axis(kind);
5813 assert_eq!(
5814 via_composer.classification,
5815 Some(Classification::gate_compute_with_axis(kind)),
5816 "ConvergencePointType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5817 );
5818 }
5819 for kind in SubstrateType::ALL {
5820 let via_composer = baseline().with_classification_axis(kind);
5821 assert_eq!(
5822 via_composer.classification,
5823 Some(Classification::gate_compute_with_axis(kind)),
5824 "SubstrateType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5825 );
5826 }
5827 for kind in CalmClassification::ALL {
5828 let via_composer = baseline().with_classification_axis(kind);
5829 assert_eq!(
5830 via_composer.classification,
5831 Some(Classification::gate_compute_with_axis(kind)),
5832 "CalmClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5833 );
5834 }
5835 for kind in DataClassification::ALL {
5836 let via_composer = baseline().with_classification_axis(kind);
5837 assert_eq!(
5838 via_composer.classification,
5839 Some(Classification::gate_compute_with_axis(kind)),
5840 "DataClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5841 );
5842 }
5843 // Horizon-nested axes: same shape through the trait's
5844 // sub-slot overlay.
5845 for kind in HorizonKind::ALL {
5846 let via_composer = baseline().with_classification_axis(kind);
5847 assert_eq!(
5848 via_composer.classification,
5849 Some(Classification::gate_compute_with_axis(kind)),
5850 "HorizonKind::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5851 );
5852 }
5853 for direction in OptimizationDirection::ALL {
5854 let via_composer = baseline().with_classification_axis(direction);
5855 assert_eq!(
5856 via_composer.classification,
5857 Some(Classification::gate_compute_with_axis(direction)),
5858 "OptimizationDirection::{direction:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5859 );
5860 }
5861 // Non-classification slots: every one preserved byte-for-byte
5862 // across the overlay on every axis. Compare through JSON
5863 // round-trip since `AplicacaoIntent` / `ExportSpec` /
5864 // `RoutingSpec` do not carry `PartialEq`.
5865 for kind in ConvergencePointType::ALL {
5866 let via_composer = baseline().with_classification_axis(kind);
5867 let baseline_ref = baseline();
5868 assert_eq!(
5869 serde_json::to_string(&via_composer.aplicacao).unwrap(),
5870 serde_json::to_string(&baseline_ref.aplicacao).unwrap(),
5871 "aplicacao slot drifted under axis overlay for kind={kind:?}",
5872 );
5873 assert_eq!(via_composer.ttl, baseline_ref.ttl);
5874 assert_eq!(via_composer.teardown, baseline_ref.teardown);
5875 assert_eq!(via_composer.max_concurrent, baseline_ref.max_concurrent);
5876 assert_eq!(
5877 via_composer.postconditions.len(),
5878 baseline_ref.postconditions.len()
5879 );
5880 assert_eq!(
5881 via_composer.preconditions.len(),
5882 baseline_ref.preconditions.len()
5883 );
5884 assert_eq!(via_composer.verify_timeout, baseline_ref.verify_timeout);
5885 assert_eq!(via_composer.parent, baseline_ref.parent);
5886 assert_eq!(via_composer.exports.len(), baseline_ref.exports.len());
5887 assert!(via_composer.routing.is_none());
5888 }
5889 }
5890
5891 /// Primitive-owner pin —
5892 /// `EphemeralSpec::with_classification_axis` on a
5893 /// `classification: Some(prior)` carrier composes the axis
5894 /// overlay onto `prior` via [`ClassificationAxis::overlay`],
5895 /// preserving every OTHER axis slot on `prior`. Distinct from the
5896 /// `None`-arm pin above: the `Some(prior)` arm does NOT reset
5897 /// through [`Classification::gate_compute`], and consecutive
5898 /// `.with_classification_axis(...)` calls compose arbitrary
5899 /// N-axis conjunctions on the ephemeral surface with the same
5900 /// order-independence guarantee [`Classification::with_axis`]
5901 /// carries on distinct-slot axes.
5902 #[test]
5903 fn with_classification_axis_on_some_arm_chains_onto_prior() {
5904 fn baseline() -> EphemeralSpec {
5905 EphemeralSpec {
5906 aplicacao: demo_overlay(),
5907 ttl: "1h".into(),
5908 teardown: TeardownPolicy::Always,
5909 max_concurrent: 0,
5910 postconditions: vec![],
5911 preconditions: vec![],
5912 verify_timeout: None,
5913 classification: None,
5914 parent: None,
5915 exports: vec![],
5916 routing: None,
5917 }
5918 }
5919 // Prior authored point_type = Fork; overlay substrate = Storage
5920 // preserves the Fork point_type on the composed classification.
5921 let seeded = baseline().with_classification_axis(ConvergencePointType::Fork);
5922 let composed = seeded.with_classification_axis(SubstrateType::Storage);
5923 let classification = composed
5924 .classification
5925 .as_ref()
5926 .expect("with_classification_axis populates Some(_)");
5927 assert_eq!(classification.point_type, ConvergencePointType::Fork);
5928 assert_eq!(classification.substrate, SubstrateType::Storage);
5929 // Order independence on distinct-slot axes: swapping the axis
5930 // chain reads the SAME final classification.
5931 let forward = baseline()
5932 .with_classification_axis(ConvergencePointType::Fork)
5933 .with_classification_axis(SubstrateType::Storage)
5934 .with_classification_axis(CalmClassification::NonMonotone)
5935 .with_classification_axis(DataClassification::Pii)
5936 .classification
5937 .unwrap();
5938 let reverse = baseline()
5939 .with_classification_axis(DataClassification::Pii)
5940 .with_classification_axis(CalmClassification::NonMonotone)
5941 .with_classification_axis(SubstrateType::Storage)
5942 .with_classification_axis(ConvergencePointType::Fork)
5943 .classification
5944 .unwrap();
5945 assert_eq!(
5946 forward, reverse,
5947 "with_classification_axis chain must be order-independent on distinct-slot axes",
5948 );
5949 // Nested horizon-sub-slot overlays compose onto the same
5950 // carrier without stomping each other: the (kind, direction)
5951 // pair rides both chains.
5952 let paired = baseline()
5953 .with_classification_axis(HorizonKind::Asymptotic)
5954 .with_classification_axis(OptimizationDirection::Maximize)
5955 .classification
5956 .unwrap();
5957 assert_eq!(paired.horizon.kind, HorizonKind::Asymptotic);
5958 assert_eq!(
5959 paired.horizon.direction,
5960 Some(OptimizationDirection::Maximize)
5961 );
5962 }
5963
5964 /// Primitive-owner pin —
5965 /// `EphemeralSpec::with_classification_axis` composes byte-for-
5966 /// byte with the pre-sweep hand-authored two-shape callsite
5967 /// pattern that recurred at ~36 sites in
5968 /// `tatara-reconciler::bin::tatara-check`: either
5969 /// `let mut c = Classification::gate_compute(); c.<axis> =
5970 /// populated; EphemeralSpec { classification: Some(c), ..
5971 /// baseline }`, or the newer `let c =
5972 /// Classification::gate_compute_with_axis(populated); EphemeralSpec
5973 /// { classification: Some(c), ..baseline }`. Both restated
5974 /// pre-sweep shapes classify identically to
5975 /// `baseline.with_classification_axis(populated)` on every
5976 /// [`ClassificationAxis`] impl. A regression that drifted the
5977 /// composer body away from the pre-sweep shape (a stray reset of a
5978 /// non-classification slot, a stomping of a nested horizon sub-
5979 /// slot on the direct-scalar axes) fails HERE at ONE landmark site
5980 /// before drifting through the ~36 swept callsites in tatara-
5981 /// check.rs.
5982 #[test]
5983 fn with_classification_axis_matches_pre_sweep_hand_authored_shape() {
5984 fn baseline() -> EphemeralSpec {
5985 EphemeralSpec {
5986 aplicacao: demo_overlay(),
5987 ttl: "1h".into(),
5988 teardown: TeardownPolicy::Always,
5989 max_concurrent: 0,
5990 postconditions: vec![],
5991 preconditions: vec![],
5992 verify_timeout: None,
5993 classification: None,
5994 parent: None,
5995 exports: vec![],
5996 routing: None,
5997 }
5998 }
5999 // Direct-scalar axes: `<eph>.with_classification_axis(kind)`
6000 // matches the pre-sweep two-shape callsite pattern on every
6001 // ConvergencePointType variant.
6002 for kind in ConvergencePointType::ALL {
6003 let via_composer = baseline().with_classification_axis(kind);
6004 let mut hand_classification = Classification::gate_compute();
6005 hand_classification.point_type = kind;
6006 let via_hand = EphemeralSpec {
6007 classification: Some(hand_classification),
6008 ..baseline()
6009 };
6010 assert_eq!(
6011 via_composer.classification, via_hand.classification,
6012 "ConvergencePointType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6013 );
6014 }
6015 for kind in SubstrateType::ALL {
6016 let via_composer = baseline().with_classification_axis(kind);
6017 let mut hand_classification = Classification::gate_compute();
6018 hand_classification.substrate = kind;
6019 let via_hand = EphemeralSpec {
6020 classification: Some(hand_classification),
6021 ..baseline()
6022 };
6023 assert_eq!(
6024 via_composer.classification, via_hand.classification,
6025 "SubstrateType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6026 );
6027 }
6028 for kind in CalmClassification::ALL {
6029 let via_composer = baseline().with_classification_axis(kind);
6030 let mut hand_classification = Classification::gate_compute();
6031 hand_classification.calm = kind;
6032 let via_hand = EphemeralSpec {
6033 classification: Some(hand_classification),
6034 ..baseline()
6035 };
6036 assert_eq!(
6037 via_composer.classification, via_hand.classification,
6038 "CalmClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6039 );
6040 }
6041 for kind in DataClassification::ALL {
6042 let via_composer = baseline().with_classification_axis(kind);
6043 let mut hand_classification = Classification::gate_compute();
6044 hand_classification.data_classification = kind;
6045 let via_hand = EphemeralSpec {
6046 classification: Some(hand_classification),
6047 ..baseline()
6048 };
6049 assert_eq!(
6050 via_composer.classification, via_hand.classification,
6051 "DataClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6052 );
6053 }
6054 // Horizon-nested axes: composer matches the newer
6055 // `gate_compute_with_axis` shape used on the horizon-nested
6056 // sweep sites in tatara-check.rs.
6057 for kind in HorizonKind::ALL {
6058 let via_composer = baseline().with_classification_axis(kind);
6059 let via_hand = EphemeralSpec {
6060 classification: Some(Classification::gate_compute_with_axis(kind)),
6061 ..baseline()
6062 };
6063 assert_eq!(
6064 via_composer.classification, via_hand.classification,
6065 "HorizonKind::{kind:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
6066 );
6067 }
6068 for direction in OptimizationDirection::ALL {
6069 let via_composer = baseline().with_classification_axis(direction);
6070 let via_hand = EphemeralSpec {
6071 classification: Some(Classification::gate_compute_with_axis(direction)),
6072 ..baseline()
6073 };
6074 assert_eq!(
6075 via_composer.classification, via_hand.classification,
6076 "OptimizationDirection::{direction:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
6077 );
6078 }
6079 }
6080
6081 fn demo_overlay() -> AplicacaoIntent {
6082 AplicacaoIntent {
6083 chart_ref: "oci://ghcr.io/pleme-io/charts/lareira-demo-app".into(),
6084 version: "0.5.5".into(),
6085 profile: "all-in-one".into(),
6086 values_overlay: serde_json::json!({
6087 "cluster": { "name": "ephemeral-test-01", "namespace": "demo-test" },
6088 "data": { "mysql": { "persistence": { "enabled": false } } },
6089 "compliance": { "overlays": [] }
6090 }),
6091 release_name: Some("demo-app-consolidated".into()),
6092 target_namespace: Some("demo-test".into()),
6093 install_timeout: Some("25m".into()),
6094 }
6095 }
6096
6097 #[test]
6098 fn defaults_resolve_for_ephemeral_spec() {
6099 let e = EphemeralSpec {
6100 aplicacao: demo_overlay(),
6101 ttl: crate::lifetime::default_ephemeral_ttl(),
6102 teardown: TeardownPolicy::default(),
6103 max_concurrent: crate::lifetime::default_ephemeral_max_concurrent(),
6104 postconditions: vec![],
6105 preconditions: vec![],
6106 verify_timeout: None,
6107 classification: None,
6108 parent: None,
6109 exports: vec![],
6110 routing: None,
6111 };
6112 let ps: ProcessSpec = e.into();
6113 // Intent must resolve to Aplicacao.
6114 match ps.intent.variant().unwrap() {
6115 IntentVariant::Aplicacao(a) => {
6116 assert_eq!(a.profile, "all-in-one");
6117 assert_eq!(a.install_timeout.as_deref(), Some("25m"));
6118 }
6119 other => panic!("expected Aplicacao, got {other:?}"),
6120 }
6121 // Lifetime must resolve to Ephemeral with defaults.
6122 match ps.lifetime.variant().unwrap() {
6123 LifetimeVariant::Ephemeral(e) => {
6124 assert_eq!(e.ttl, "1h");
6125 assert_eq!(e.teardown_policy, TeardownPolicy::Always);
6126 }
6127 other => panic!("expected ephemeral, got {other:?}"),
6128 }
6129 // Default classification gates the Process at Compute/Internal.
6130 assert_eq!(ps.classification.point_type, ConvergencePointType::Gate);
6131 assert_eq!(ps.classification.substrate, SubstrateType::Compute);
6132 }
6133
6134 #[test]
6135 fn ephemeral_lisp_round_trip() {
6136 let src = r#"
6137 (defephemeral closed-loop-attest
6138 :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
6139 :version "0.5.5"
6140 :profile "all-in-one"
6141 :values-overlay (:cluster (:name "ephemeral-test-01")
6142 :data (:mysql (:persistence (:enabled #f)))
6143 :compliance (:overlays []))
6144 :release-name "demo-app-consolidated"
6145 :target-namespace "demo-test"
6146 :install-timeout "25m")
6147 :ttl "1h"
6148 :teardown OnAttested
6149 :max-concurrent 1
6150 :postconditions
6151 ((:kind HelmReleaseReleased
6152 :params (:name "demo-app-consolidated"
6153 :namespace "demo-test"))
6154 (:kind ClosedLoopAuth
6155 :params (:issuer (:service "demo-app-issuer" :port 8080)
6156 :consumer (:service "demo-app-gateway" :port 8000)
6157 :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
6158 "#;
6159 let defs = compile_ephemeral_source(src).expect("compile");
6160 assert_eq!(defs.len(), 1);
6161 let d = &defs[0];
6162 assert_eq!(d.name, "closed-loop-attest");
6163
6164 // Aplicacao body landed correctly.
6165 assert_eq!(
6166 d.spec.aplicacao.chart_ref,
6167 "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
6168 );
6169 assert_eq!(d.spec.aplicacao.profile, "all-in-one");
6170 assert_eq!(
6171 d.spec.aplicacao.target_namespace.as_deref(),
6172 Some("demo-test")
6173 );
6174 // values-overlay JSON is preserved.
6175 assert_eq!(
6176 d.spec.aplicacao.values_overlay["cluster"]["name"],
6177 "ephemeral-test-01"
6178 );
6179 // Boolean #f is preserved as a typed JSON bool (not the string "false").
6180 // tatara-lisp uses Scheme syntax for bools — `#t` / `#f`.
6181 assert_eq!(
6182 d.spec.aplicacao.values_overlay["data"]["mysql"]["persistence"]["enabled"],
6183 false
6184 );
6185
6186 // Lifetime knobs.
6187 assert_eq!(d.spec.ttl, "1h");
6188 assert_eq!(d.spec.teardown, TeardownPolicy::OnAttested);
6189 assert_eq!(d.spec.max_concurrent, 1);
6190
6191 // Two postconditions, both typed.
6192 assert_eq!(d.spec.postconditions.len(), 2);
6193 assert_eq!(
6194 d.spec.postconditions[0].kind,
6195 ConditionKind::HelmReleaseReleased
6196 );
6197 assert_eq!(d.spec.postconditions[1].kind, ConditionKind::ClosedLoopAuth);
6198
6199 // Lowers to ProcessSpec with the right shape.
6200 let ps: ProcessSpec = d.spec.clone().into();
6201 assert!(matches!(
6202 ps.intent.variant().unwrap(),
6203 IntentVariant::Aplicacao(_)
6204 ));
6205 assert!(matches!(
6206 ps.lifetime.variant().unwrap(),
6207 LifetimeVariant::Ephemeral(_)
6208 ));
6209 assert_eq!(ps.boundary.postconditions.len(), 2);
6210 }
6211
6212 /// End-to-end: the `:exports` slot on `(defephemeral …)` compiles
6213 /// into typed `ExportSpec` values via the Universal-Deserialize
6214 /// fallthrough — no per-domain keyword handlers needed.
6215 ///
6216 /// Receipts (empty-body source) is exercised via the Rust serde
6217 /// path only (see `export::tests::export_spec_serde_round_trip`).
6218 /// tatara-lisp's empty-kw-form `(:)` currently parses as a single-
6219 /// element array rather than a JSON `{}`; the same limitation
6220 /// affects `(:permanent)` on Lifetime. Tracked: extend the reader
6221 /// to accept `(:foo (:))` ⇒ `{"foo": {}}` as a typed-empty form,
6222 /// then re-enable Receipts here.
6223 #[test]
6224 fn exports_lisp_round_trip() {
6225 use crate::export::{ArtifactVariant, ChannelVariant, ExportTrigger, ReportFormat};
6226 let src = r#"
6227 (defephemeral closed-loop-attest
6228 :aplicacao (:chart-ref "oci://x"
6229 :version "1.0.0"
6230 :profile "minimal"
6231 :values-overlay ())
6232 :ttl "30m"
6233 :teardown OnAttested
6234 :exports
6235 ((:source (:test-report (:configmap "junit-results"
6236 :key "junit.xml"
6237 :format Junit))
6238 :channel (:nats-subject (:subject "pleme.pleme-dev.ephemeral.r1.test-report"
6239 :stream "EPHEMERAL_TEST_REPORTS"))
6240 :when OnAttested)
6241 (:source (:test-report (:configmap "junit-results"
6242 :key "junit.xml"
6243 :format Junit))
6244 :channel (:http-event (:signal-type "test-report"))
6245 :when Always)
6246 (:source (:run-marker (:labels (:run-id "r1" :phase "end")))
6247 :channel (:http-event (:signal-type "ephemeral-marker"))
6248 :when Always)))
6249 "#;
6250 let defs = compile_ephemeral_source(src).expect("compile");
6251 assert_eq!(defs.len(), 1);
6252 let d = &defs[0];
6253 assert_eq!(d.spec.exports.len(), 3);
6254
6255 // First export — TestReport → NATS subject + OnAttested
6256 let r = &d.spec.exports[0];
6257 match r.source.variant().unwrap() {
6258 ArtifactVariant::TestReport(tr) => {
6259 assert_eq!(tr.configmap, "junit-results");
6260 assert_eq!(tr.format, ReportFormat::Junit);
6261 }
6262 other => panic!("expected TestReport, got {other:?}"),
6263 }
6264 match r.channel.variant().unwrap() {
6265 ChannelVariant::NatsSubject(n) => {
6266 assert_eq!(n.subject, "pleme.pleme-dev.ephemeral.r1.test-report");
6267 assert_eq!(n.stream, "EPHEMERAL_TEST_REPORTS");
6268 }
6269 other => panic!("expected NatsSubject, got {other:?}"),
6270 }
6271 assert_eq!(r.when, ExportTrigger::OnAttested);
6272
6273 // Second export — TestReport → HTTP + Always
6274 let t = &d.spec.exports[1];
6275 match t.channel.variant().unwrap() {
6276 ChannelVariant::HttpEvent(h) => assert_eq!(h.signal_type, "test-report"),
6277 other => panic!("expected HttpEvent, got {other:?}"),
6278 }
6279 assert_eq!(t.when, ExportTrigger::Always);
6280
6281 // Third export — RunMarker (BTreeMap<String,String> round-trip).
6282 // tatara-lisp lowercases + normalizes keyword keys before
6283 // handing off to serde_json — kebab `:run-id` may land as
6284 // either `run-id` or `runId` depending on the reader path.
6285 // Accept either; the round-trip property under test is
6286 // "label survives compile" not "exact case-form".
6287 let m = &d.spec.exports[2];
6288 match m.source.variant().unwrap() {
6289 ArtifactVariant::RunMarker(rm) => {
6290 assert_eq!(rm.labels.len(), 2);
6291 let run_id = rm
6292 .labels
6293 .get("run-id")
6294 .or_else(|| rm.labels.get("runId"))
6295 .or_else(|| rm.labels.get("run_id"))
6296 .expect("run-id label present under some normalization");
6297 assert_eq!(run_id, "r1");
6298 assert_eq!(rm.labels.get("phase").map(String::as_str), Some("end"));
6299 }
6300 other => panic!("expected RunMarker, got {other:?}"),
6301 }
6302
6303 // Lowered ProcessSpec carries the exports through unchanged.
6304 let ps: ProcessSpec = d.spec.clone().into();
6305 assert_eq!(ps.lifetime.ephemeral.as_ref().unwrap().exports.len(), 3);
6306 }
6307
6308 // ── EphemeralSpec::has_condition_kind substrate pins ─────────────
6309 //
6310 // Fail-before-pass-after granularity:
6311 // `EphemeralSpec::has_condition_kind` did not exist before this
6312 // commit — the (preconditions ∪ postconditions .iter().any(|c|
6313 // c.kind == K)) union-probe shape lived at ONE struct-level site
6314 // (`Boundary::has_condition_kind` on the point surface's nested
6315 // [`Boundary`] slot). The lift adds the peer inherent method on the
6316 // [`EphemeralSpec`] sugar-surface so both struct-level union
6317 // callers compose against the SAME slice-level substrate primitive
6318 // [`ConditionSliceExt::has_kind`] in lockstep. A regression that
6319 // (a) hard-coded the arm to a single kind, (b) dropped the pre-
6320 // condition side of the OR (a re-inheritance of the pre-lift
6321 // ephemeral `closed-loop-auth` post-only shape at the union-tag
6322 // level), or (c) probed the wrong slot fails HERE at the substrate
6323 // primitive rather than as silent operator-facing drift at the
6324 // ephemeral `condition-<kind>` require-tag surface.
6325
6326 fn empty_ephemeral() -> EphemeralSpec {
6327 EphemeralSpec {
6328 aplicacao: AplicacaoIntent::chart_only("oci://ghcr.io/x", "1"),
6329 ttl: "1h".into(),
6330 teardown: TeardownPolicy::Always,
6331 max_concurrent: 0,
6332 postconditions: vec![],
6333 preconditions: vec![],
6334 verify_timeout: None,
6335 classification: None,
6336 parent: None,
6337 exports: vec![],
6338 routing: None,
6339 }
6340 }
6341
6342 fn cond(kind: ConditionKind) -> Condition {
6343 Condition {
6344 kind,
6345 params: serde_json::json!({}),
6346 }
6347 }
6348
6349 /// EMPTY-SPEC pin — a default [`EphemeralSpec`] (empty
6350 /// preconditions, empty postconditions) returns `false` for EVERY
6351 /// [`ConditionKind`]. Sweep `ConditionKind::ALL` so a new variant
6352 /// added without a matching arm in the presence probe surfaces at
6353 /// rustc's exhaustiveness gate on the ALL literal (arity forced by
6354 /// `[Self; 8]`) rather than as a silent false-positive at every
6355 /// downstream `condition-<kind>` ephemeral require-tag callsite.
6356 /// Byte-for-byte peer of
6357 /// `has_condition_kind_returns_false_on_empty_boundary_for_every_kind`
6358 /// on the [`Boundary`] surface.
6359 #[test]
6360 fn has_condition_kind_returns_false_on_empty_ephemeral_for_every_kind() {
6361 let spec = empty_ephemeral();
6362 for kind in ConditionKind::ALL {
6363 assert!(
6364 !spec.has_condition_kind(kind),
6365 "empty ephemeral spec must return false for {kind:?}",
6366 );
6367 }
6368 }
6369
6370 /// POSTCONDITION-only pin — an ephemeral spec that carries the
6371 /// kind on ONLY postconditions returns `true` for that kind,
6372 /// `false` for every other variant. Sweep the ALL × ALL cross so
6373 /// a regression that hard-coded the arm to a single kind or
6374 /// probed the wrong slot fails HERE at the substrate primitive.
6375 #[test]
6376 fn has_condition_kind_reads_ephemeral_postconditions_per_kind() {
6377 for populated in ConditionKind::ALL {
6378 let mut spec = empty_ephemeral();
6379 spec.postconditions.push(cond(populated));
6380 for query in ConditionKind::ALL {
6381 let expected = query == populated;
6382 assert_eq!(
6383 spec.has_condition_kind(query),
6384 expected,
6385 "ephemeral postcondition populated={populated:?}: \
6386 query {query:?} drifted",
6387 );
6388 }
6389 }
6390 }
6391
6392 /// PRECONDITION-only pin — mirrors the postcondition sweep on the
6393 /// other half of the union. Locks the union semantics on both
6394 /// halves separately so a regression that dropped the pre-
6395 /// condition side of the OR fails here even though the
6396 /// postcondition-side pin above passes.
6397 #[test]
6398 fn has_condition_kind_reads_ephemeral_preconditions_per_kind() {
6399 for populated in ConditionKind::ALL {
6400 let mut spec = empty_ephemeral();
6401 spec.preconditions.push(cond(populated));
6402 for query in ConditionKind::ALL {
6403 let expected = query == populated;
6404 assert_eq!(
6405 spec.has_condition_kind(query),
6406 expected,
6407 "ephemeral precondition populated={populated:?}: \
6408 query {query:?} drifted",
6409 );
6410 }
6411 }
6412 }
6413
6414 /// UNION pin — a kind that appears on preconditions returns
6415 /// `true` even when postconditions carries a DIFFERENT kind, and
6416 /// vice versa. Pins the OR-composition of the two halves so a
6417 /// regression that collapsed the union to an intersection (AND)
6418 /// silently reclassifies pre-only or post-only kinds as absent.
6419 /// Byte-for-byte peer of
6420 /// `has_condition_kind_unions_pre_and_post_condition_arms` on the
6421 /// [`Boundary`] surface.
6422 #[test]
6423 fn has_condition_kind_unions_pre_and_post_ephemeral_condition_arms() {
6424 let mut spec = empty_ephemeral();
6425 spec.preconditions
6426 .push(cond(ConditionKind::KustomizationHealthy));
6427 spec.postconditions
6428 .push(cond(ConditionKind::ClosedLoopAuth));
6429 assert!(
6430 spec.has_condition_kind(ConditionKind::KustomizationHealthy),
6431 "pre-only kind must resolve through the union",
6432 );
6433 assert!(
6434 spec.has_condition_kind(ConditionKind::ClosedLoopAuth),
6435 "post-only kind must resolve through the union",
6436 );
6437 assert!(
6438 !spec.has_condition_kind(ConditionKind::PromQL),
6439 "an absent kind must return false even with populated halves",
6440 );
6441 }
6442
6443 /// COMPOSITION pin — [`EphemeralSpec::has_condition_kind`] equals
6444 /// the OR of the two slice-level probes on the pre/post fields.
6445 /// The struct-level union body composes ONLY [`ConditionSliceExt::has_kind`]
6446 /// on each half; a regression that inlined a wide-net predicate
6447 /// (`.iter().any(|c| c.kind != kind).not()`, an `all` instead of
6448 /// `any`) drifts from the slice-level primitive here. Byte-for-
6449 /// byte peer of the
6450 /// `boundary_has_condition_kind_equals_or_of_half_slice_probes`
6451 /// composition pin on the [`Boundary`] surface.
6452 #[test]
6453 fn ephemeral_has_condition_kind_equals_or_of_half_slice_probes() {
6454 // Sweep every ConditionKind on both halves independently so the
6455 // cross of half-slice probes reaches the OR-composition body
6456 // exhaustively.
6457 for populated in ConditionKind::ALL {
6458 let mut spec = empty_ephemeral();
6459 spec.preconditions.push(cond(populated));
6460 spec.postconditions.push(cond(ConditionKind::PromQL));
6461 for query in ConditionKind::ALL {
6462 let via_or_of_halves =
6463 spec.preconditions.has_kind(query) || spec.postconditions.has_kind(query);
6464 assert_eq!(
6465 spec.has_condition_kind(query),
6466 via_or_of_halves,
6467 "populated={populated:?} query={query:?}: struct-level \
6468 union drifted from OR of slice-level probes",
6469 );
6470 }
6471 }
6472 }
6473
6474 // ── EphemeralSpec::has_(pre|post)condition_kind substrate pins ──
6475 //
6476 // Fail-before-pass-after granularity: the two half-slice arms did
6477 // not exist on the ephemeral surface before this commit — the
6478 // ephemeral require-tag classifier in `tatara-check` and the
6479 // `closed-loop-auth` fixed-tag arm reached
6480 // `spec.postconditions.has_kind(K)` through direct field access,
6481 // asymmetric with the union-arm [`EphemeralSpec::has_condition_kind`]
6482 // that already routed through the named struct method. The lift
6483 // closes the (precondition, postcondition, union) triad on the
6484 // ephemeral sugar surface so a future normalization at the
6485 // presence-probe shape lands at ONE site per surface for all
6486 // three arms.
6487
6488 /// EMPTY-SPEC pin — an ephemeral spec with no preconditions and
6489 /// no postconditions returns `false` for EVERY [`ConditionKind`]
6490 /// on both half-slice arms. Sweep `ConditionKind::ALL` so a new
6491 /// variant added without a matching arm surfaces at rustc's
6492 /// exhaustiveness gate on the ALL literal (arity forced by the
6493 /// closed-set array) rather than as a silent false-positive at
6494 /// every downstream require-tag callsite on the ephemeral
6495 /// surface.
6496 #[test]
6497 fn ephemeral_has_precondition_and_postcondition_kind_return_false_on_empty_spec() {
6498 let spec = empty_ephemeral();
6499 for kind in ConditionKind::ALL {
6500 assert!(
6501 !spec.has_precondition_kind(kind),
6502 "empty ephemeral must return false on precondition arm for {kind:?}",
6503 );
6504 assert!(
6505 !spec.has_postcondition_kind(kind),
6506 "empty ephemeral must return false on postcondition arm for {kind:?}",
6507 );
6508 }
6509 }
6510
6511 /// SLICE-SELECTIVITY pin (precondition arm) — an ephemeral spec
6512 /// with a kind on the precondition side ONLY resolves `true` at
6513 /// [`EphemeralSpec::has_precondition_kind`] and `false` at
6514 /// [`EphemeralSpec::has_postcondition_kind`]. Locks the (side-
6515 /// select, kind-select) partition so a regression that pointed
6516 /// the precondition arm at `self.postconditions` (a copy-paste
6517 /// from the sibling arm during the lift) surfaces HERE.
6518 #[test]
6519 fn ephemeral_has_precondition_kind_reads_preconditions_slice_only() {
6520 for populated in ConditionKind::ALL {
6521 let mut spec = empty_ephemeral();
6522 spec.preconditions.push(cond(populated));
6523 for query in ConditionKind::ALL {
6524 let expected_pre = query == populated;
6525 assert_eq!(
6526 spec.has_precondition_kind(query),
6527 expected_pre,
6528 "precondition-only populated={populated:?}: query {query:?} \
6529 drifted on ephemeral precondition arm",
6530 );
6531 assert!(
6532 !spec.has_postcondition_kind(query),
6533 "precondition-only populated={populated:?}: query {query:?} must \
6534 return false on ephemeral postcondition arm (postconditions is empty)",
6535 );
6536 }
6537 }
6538 }
6539
6540 /// SLICE-SELECTIVITY pin (postcondition arm) — mirror of the
6541 /// precondition-only sweep on the other half. Locks the
6542 /// postcondition arm's binding to `self.postconditions` so a
6543 /// regression that pointed it at `self.preconditions` fails HERE
6544 /// even though the precondition-arm pin above passes.
6545 #[test]
6546 fn ephemeral_has_postcondition_kind_reads_postconditions_slice_only() {
6547 for populated in ConditionKind::ALL {
6548 let mut spec = empty_ephemeral();
6549 spec.postconditions.push(cond(populated));
6550 for query in ConditionKind::ALL {
6551 let expected_post = query == populated;
6552 assert_eq!(
6553 spec.has_postcondition_kind(query),
6554 expected_post,
6555 "postcondition-only populated={populated:?}: query {query:?} \
6556 drifted on ephemeral postcondition arm",
6557 );
6558 assert!(
6559 !spec.has_precondition_kind(query),
6560 "postcondition-only populated={populated:?}: query {query:?} must \
6561 return false on ephemeral precondition arm (preconditions is empty)",
6562 );
6563 }
6564 }
6565 }
6566
6567 /// COMPOSITION-LAW pin — [`EphemeralSpec::has_condition_kind`]
6568 /// equals `has_precondition_kind(k) || has_postcondition_kind(k)`
6569 /// at EVERY (pre-populated, post-populated, query) triple on
6570 /// `ConditionKind::ALL`. Byte-for-byte peer of the
6571 /// `boundary_has_condition_kind_composes_precondition_and_postcondition_arms`
6572 /// composition-law pin on the [`Boundary`] surface — the
6573 /// two-surface parity contract binds the ephemeral sugar type
6574 /// and the point-domain boundary type through the SAME
6575 /// (`condition_kind = precondition_kind ∨ postcondition_kind`)
6576 /// composition, so every downstream `condition-<K>` require-tag
6577 /// classifier on either surface inherits the composition
6578 /// mechanically.
6579 #[test]
6580 fn ephemeral_has_condition_kind_composes_precondition_and_postcondition_arms() {
6581 for pre_kind in ConditionKind::ALL {
6582 for post_kind in ConditionKind::ALL {
6583 let mut spec = empty_ephemeral();
6584 spec.preconditions.push(cond(pre_kind));
6585 spec.postconditions.push(cond(post_kind));
6586 for query in ConditionKind::ALL {
6587 let via_arms =
6588 spec.has_precondition_kind(query) || spec.has_postcondition_kind(query);
6589 assert_eq!(
6590 spec.has_condition_kind(query),
6591 via_arms,
6592 "ephemeral union arm drifted from OR of half-slice arms: \
6593 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6594 );
6595 }
6596 }
6597 }
6598 }
6599
6600 /// SUBSTRATE-DELEGATION pin — the two half-slice arms on the
6601 /// ephemeral surface delegate verbatim to
6602 /// [`crate::boundary::ConditionSliceExt::has_kind`] on the
6603 /// underlying [`Vec<Condition>`] slice, no inline reimplementation.
6604 /// Sweep the full `ConditionKind::ALL` × `ConditionKind::ALL`
6605 /// cross so a regression that inlined a divergent walk at either
6606 /// arm surfaces HERE at the substrate boundary rather than as
6607 /// silent skew between the struct-level arm and the slice-level
6608 /// primitive.
6609 #[test]
6610 fn ephemeral_has_precondition_and_postcondition_kind_delegate_to_slice_has_kind() {
6611 for populated in ConditionKind::ALL {
6612 let mut spec = empty_ephemeral();
6613 spec.preconditions.push(cond(populated));
6614 spec.postconditions.push(cond(populated));
6615 for query in ConditionKind::ALL {
6616 assert_eq!(
6617 spec.has_precondition_kind(query),
6618 spec.preconditions.has_kind(query),
6619 "ephemeral precondition arm must delegate to preconditions.has_kind: \
6620 populated={populated:?} query={query:?}",
6621 );
6622 assert_eq!(
6623 spec.has_postcondition_kind(query),
6624 spec.postconditions.has_kind(query),
6625 "ephemeral postcondition arm must delegate to postconditions.has_kind: \
6626 populated={populated:?} query={query:?}",
6627 );
6628 }
6629 }
6630 }
6631
6632 // ── EphemeralSpec::find_(pre|post|)condition_kind widened triad ──
6633 //
6634 // Fail-before-pass-after granularity: the three widened
6635 // `find_*_kind` arms did not exist on the ephemeral surface before
6636 // this commit — the (widened `Option<&Condition>` return) axis
6637 // lived at ONE struct-level site (`Boundary::find_condition_kind`
6638 // on the point surface's nested [`Boundary`] slot). The lift adds
6639 // the peer inherent methods on the [`EphemeralSpec`] sugar-surface
6640 // so both struct-level widened callers compose against the SAME
6641 // slice-level substrate primitive
6642 // [`crate::boundary::ConditionSliceExt::find_kind`] in lockstep.
6643 // A regression that (a) hard-coded the arm to a single kind, (b)
6644 // reversed the walk order on the union (postcondition first), or
6645 // (c) collapsed `or_else` to `and_then` (silently narrowing the
6646 // union to an intersection) fails HERE at the substrate primitive
6647 // rather than as silent operator-facing drift at the ephemeral
6648 // require-tag surface.
6649
6650 /// EMPTY-SPEC pin (find-triad) — a default [`EphemeralSpec`]
6651 /// (empty preconditions, empty postconditions) returns `None`
6652 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
6653 /// `ConditionKind::ALL` × three-arm cross so a new variant added
6654 /// without a matching arm surfaces at rustc's exhaustiveness gate
6655 /// on the ALL literal (arity forced by the closed-set array)
6656 /// rather than as a silent false-`Some` at every downstream
6657 /// widened callsite on the ephemeral surface.
6658 #[test]
6659 fn ephemeral_find_condition_kind_triad_returns_none_on_empty_spec() {
6660 let spec = empty_ephemeral();
6661 for kind in ConditionKind::ALL {
6662 assert!(
6663 spec.find_precondition_kind(kind).is_none(),
6664 "empty ephemeral must return None on precondition find arm for {kind:?}",
6665 );
6666 assert!(
6667 spec.find_postcondition_kind(kind).is_none(),
6668 "empty ephemeral must return None on postcondition find arm for {kind:?}",
6669 );
6670 assert!(
6671 spec.find_condition_kind(kind).is_none(),
6672 "empty ephemeral must return None on union find arm for {kind:?}",
6673 );
6674 }
6675 }
6676
6677 /// SUBSTRATE-DELEGATION pin (ephemeral find-triad) — the three
6678 /// widened `find_*_kind` methods on [`EphemeralSpec`] delegate
6679 /// verbatim to [`crate::boundary::ConditionSliceExt::find_kind`]
6680 /// on the underlying [`Vec<Condition>`] slices, no inline
6681 /// reimplementation. The `find_condition_kind` union walks
6682 /// preconditions first then postconditions via `Option::or_else`.
6683 /// Sweep `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
6684 /// so a regression that (a) inlined a divergent walk at either
6685 /// half-slice arm, (b) reversed the union walk order on the
6686 /// ephemeral surface only (breaking two-surface parity with
6687 /// [`crate::boundary::Boundary::find_condition_kind`]), or (c)
6688 /// collapsed `or_else` to `and_then` surfaces HERE at the substrate
6689 /// boundary. Byte-for-byte peer of the point-domain
6690 /// `find_condition_kind_triad_delegates_to_slice_find_kind` pin.
6691 #[test]
6692 fn ephemeral_find_condition_kind_triad_delegates_to_slice_find_kind() {
6693 for pre_kind in ConditionKind::ALL {
6694 for post_kind in ConditionKind::ALL {
6695 let mut spec = empty_ephemeral();
6696 spec.preconditions.push(cond(pre_kind));
6697 spec.postconditions.push(cond(post_kind));
6698 for query in ConditionKind::ALL {
6699 let via_pre = spec.preconditions.find_kind(query);
6700 let via_post = spec.postconditions.find_kind(query);
6701 assert_eq!(
6702 spec.find_precondition_kind(query).map(|c| c.kind),
6703 via_pre.map(|c| c.kind),
6704 "ephemeral precondition find arm must delegate: \
6705 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6706 );
6707 assert_eq!(
6708 spec.find_postcondition_kind(query).map(|c| c.kind),
6709 via_post.map(|c| c.kind),
6710 "ephemeral postcondition find arm must delegate: \
6711 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6712 );
6713 let expected_union = via_pre.or(via_post).map(|c| c.kind);
6714 assert_eq!(
6715 spec.find_condition_kind(query).map(|c| c.kind),
6716 expected_union,
6717 "ephemeral union find arm must equal precondition.or_else(postcondition): \
6718 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6719 );
6720 }
6721 }
6722 }
6723 }
6724
6725 /// PRECONDITION-PRECEDENCE pin (ephemeral) — a kind authored on
6726 /// BOTH sides returns the precondition-side [`Condition`] from
6727 /// `find_condition_kind`. Byte-for-byte peer of the point-domain
6728 /// `find_condition_kind_returns_precondition_side_on_dual_populated`
6729 /// pin, so the two-surface parity contract binds the walk order
6730 /// on both surfaces through ONE composition law. Uses two params-
6731 /// distinguishable [`Condition`]s so a regression on the ephemeral
6732 /// surface only that reversed the walk order surfaces at the
6733 /// returned params payload rather than silently at the presence
6734 /// bit.
6735 #[test]
6736 fn ephemeral_find_condition_kind_returns_precondition_side_on_dual_populated() {
6737 let mut spec = empty_ephemeral();
6738 spec.preconditions.push(Condition {
6739 kind: ConditionKind::ClosedLoopAuth,
6740 params: serde_json::json!({ "side": "pre" }),
6741 });
6742 spec.postconditions.push(Condition {
6743 kind: ConditionKind::ClosedLoopAuth,
6744 params: serde_json::json!({ "side": "post" }),
6745 });
6746 let hit = spec
6747 .find_condition_kind(ConditionKind::ClosedLoopAuth)
6748 .expect("dual-populated ephemeral spec must resolve Some");
6749 assert_eq!(
6750 hit.params.get("side").and_then(serde_json::Value::as_str),
6751 Some("pre"),
6752 "ephemeral find_condition_kind must walk preconditions first",
6753 );
6754 }
6755
6756 /// STRUCT-LEVEL DELEGATION pin (ephemeral has ↔ find) — the three
6757 /// [`EphemeralSpec`] `has_*_kind` arms equal their widened peers'
6758 /// `.is_some()` projection at EVERY (pre-populated, post-populated,
6759 /// query) triple on `ConditionKind::ALL`. Byte-for-byte peer of
6760 /// the point-domain
6761 /// `boundary_has_triad_equals_find_triad_is_some_projection` pin,
6762 /// so both surfaces' has/find refinement bridge stays symmetric by
6763 /// construction — a future consumer that reads
6764 /// `spec.has_condition_kind(k)` as sugar for
6765 /// `spec.find_condition_kind(k).is_some()` on either surface stays
6766 /// typed against the SAME truth table across the two-surface
6767 /// parity contract.
6768 #[test]
6769 fn ephemeral_has_triad_equals_find_triad_is_some_projection() {
6770 for pre_kind in ConditionKind::ALL {
6771 for post_kind in ConditionKind::ALL {
6772 let mut spec = empty_ephemeral();
6773 spec.preconditions.push(cond(pre_kind));
6774 spec.postconditions.push(cond(post_kind));
6775 for query in ConditionKind::ALL {
6776 assert_eq!(
6777 spec.has_precondition_kind(query),
6778 spec.find_precondition_kind(query).is_some(),
6779 "ephemeral precondition has/find bridge drifted: \
6780 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6781 );
6782 assert_eq!(
6783 spec.has_postcondition_kind(query),
6784 spec.find_postcondition_kind(query).is_some(),
6785 "ephemeral postcondition has/find bridge drifted: \
6786 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6787 );
6788 assert_eq!(
6789 spec.has_condition_kind(query),
6790 spec.find_condition_kind(query).is_some(),
6791 "ephemeral union has/find bridge drifted: \
6792 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6793 );
6794 }
6795 }
6796 }
6797 }
6798
6799 // ── EphemeralSpec::iter_(pre|post|)condition_kind widened triad ──
6800 //
6801 // Fail-before-pass-after granularity: the three widened
6802 // `iter_*_kind` arms did not exist on the ephemeral surface before
6803 // this commit — the (widened `impl Iterator<Item = &Condition>`
6804 // stream) axis lived at ONE struct-level site
6805 // (`Boundary::iter_condition_kind` on the point surface's nested
6806 // [`Boundary`] slot). The lift adds the peer inherent methods on
6807 // the [`EphemeralSpec`] sugar-surface so both struct-level widened
6808 // callers compose against the SAME slice-level substrate primitive
6809 // [`crate::boundary::ConditionSliceExt::iter_kind`] in lockstep.
6810 // A regression that (a) hard-coded the arm to a single kind, (b)
6811 // reversed the chain order on the union (postcondition first), or
6812 // (c) collapsed the chain to a `.zip(...)` (silently narrowing the
6813 // union to an intersection-by-position) fails HERE at the
6814 // substrate primitive rather than as silent operator-facing drift
6815 // at the ephemeral require-tag surface.
6816
6817 /// EMPTY-SPEC pin (iter-triad) — a default [`EphemeralSpec`]
6818 /// (empty preconditions, empty postconditions) yields nothing
6819 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
6820 /// `ConditionKind::ALL` × three-arm cross so a new variant added
6821 /// without a matching arm surfaces at rustc's exhaustiveness gate
6822 /// on the ALL literal rather than as a silent phantom-yield at
6823 /// every downstream widened callsite on the ephemeral surface.
6824 #[test]
6825 fn ephemeral_iter_condition_kind_triad_yields_nothing_on_empty_spec() {
6826 let spec = empty_ephemeral();
6827 for kind in ConditionKind::ALL {
6828 assert_eq!(
6829 spec.iter_precondition_kind(kind).count(),
6830 0,
6831 "empty ephemeral must yield nothing on precondition iter arm for {kind:?}",
6832 );
6833 assert_eq!(
6834 spec.iter_postcondition_kind(kind).count(),
6835 0,
6836 "empty ephemeral must yield nothing on postcondition iter arm for {kind:?}",
6837 );
6838 assert_eq!(
6839 spec.iter_condition_kind(kind).count(),
6840 0,
6841 "empty ephemeral must yield nothing on union iter arm for {kind:?}",
6842 );
6843 }
6844 }
6845
6846 /// SUBSTRATE-DELEGATION pin (ephemeral iter-triad) — the three
6847 /// widened `iter_*_kind` methods on [`EphemeralSpec`] delegate
6848 /// verbatim to [`crate::boundary::ConditionSliceExt::iter_kind`]
6849 /// on the underlying [`Vec<Condition>`] slices, no inline
6850 /// reimplementation. The `iter_condition_kind` union chains
6851 /// preconditions first then postconditions via
6852 /// [`Iterator::chain`]. Sweep
6853 /// `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
6854 /// so a regression that (a) inlined a divergent walk at either
6855 /// half-slice arm, (b) reversed the chain order on the ephemeral
6856 /// surface only (breaking two-surface parity with
6857 /// [`crate::boundary::Boundary::iter_condition_kind`]), or (c)
6858 /// collapsed the chain to a `.zip(...)` surfaces HERE at the
6859 /// substrate boundary. Byte-for-byte peer of the point-domain
6860 /// `iter_condition_kind_triad_delegates_to_slice_iter_kind` pin.
6861 #[test]
6862 fn ephemeral_iter_condition_kind_triad_delegates_to_slice_iter_kind() {
6863 for pre_kind in ConditionKind::ALL {
6864 for post_kind in ConditionKind::ALL {
6865 let mut spec = empty_ephemeral();
6866 spec.preconditions.push(cond(pre_kind));
6867 spec.postconditions.push(cond(post_kind));
6868 for query in ConditionKind::ALL {
6869 let via_pre: Vec<_> = spec
6870 .preconditions
6871 .iter_kind(query)
6872 .map(|c| c.kind)
6873 .collect();
6874 let via_post: Vec<_> = spec
6875 .postconditions
6876 .iter_kind(query)
6877 .map(|c| c.kind)
6878 .collect();
6879 assert_eq!(
6880 spec.iter_precondition_kind(query)
6881 .map(|c| c.kind)
6882 .collect::<Vec<_>>(),
6883 via_pre,
6884 "ephemeral precondition iter arm must delegate: \
6885 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6886 );
6887 assert_eq!(
6888 spec.iter_postcondition_kind(query)
6889 .map(|c| c.kind)
6890 .collect::<Vec<_>>(),
6891 via_post,
6892 "ephemeral postcondition iter arm must delegate: \
6893 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6894 );
6895 let mut expected_union = via_pre.clone();
6896 expected_union.extend(via_post.iter().copied());
6897 assert_eq!(
6898 spec.iter_condition_kind(query)
6899 .map(|c| c.kind)
6900 .collect::<Vec<_>>(),
6901 expected_union,
6902 "ephemeral union iter arm must chain precondition ⨟ postcondition: \
6903 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6904 );
6905 }
6906 }
6907 }
6908 }
6909
6910 /// PRECONDITION-PRECEDENCE pin (ephemeral iter) — a kind
6911 /// authored on BOTH sides yields precondition-side matches
6912 /// FIRST in the union chain. Byte-for-byte peer of the
6913 /// point-domain
6914 /// `iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated`
6915 /// pin — the two-surface parity contract binds the chain order
6916 /// on both surfaces through ONE composition law. Uses two
6917 /// params-distinguishable [`Condition`]s so a regression on the
6918 /// ephemeral surface only that reversed the chain order surfaces
6919 /// at the returned params payload rather than silently at the
6920 /// count.
6921 #[test]
6922 fn ephemeral_iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated()
6923 {
6924 let mut spec = empty_ephemeral();
6925 spec.preconditions.push(Condition {
6926 kind: ConditionKind::ClosedLoopAuth,
6927 params: serde_json::json!({ "side": "pre-1" }),
6928 });
6929 spec.postconditions.push(Condition {
6930 kind: ConditionKind::ClosedLoopAuth,
6931 params: serde_json::json!({ "side": "post-1" }),
6932 });
6933 spec.postconditions.push(Condition {
6934 kind: ConditionKind::ClosedLoopAuth,
6935 params: serde_json::json!({ "side": "post-2" }),
6936 });
6937 let sides: Vec<_> = spec
6938 .iter_condition_kind(ConditionKind::ClosedLoopAuth)
6939 .map(|c| {
6940 c.params
6941 .get("side")
6942 .and_then(serde_json::Value::as_str)
6943 .unwrap_or_default()
6944 .to_owned()
6945 })
6946 .collect();
6947 assert_eq!(
6948 sides,
6949 vec!["pre-1".to_owned(), "post-1".to_owned(), "post-2".to_owned(),],
6950 "ephemeral iter_condition_kind must yield every precondition-side match before \
6951 any postcondition-side match (chain order pinned by two-surface parity)",
6952 );
6953 }
6954
6955 /// STRUCT-LEVEL DELEGATION pin (find ↔ iter on EphemeralSpec) —
6956 /// the three [`EphemeralSpec`] `find_*_kind` arms equal their
6957 /// widened peers' `.next()` projection at EVERY (pre-populated,
6958 /// post-populated, query) triple on `ConditionKind::ALL`.
6959 /// Byte-for-byte peer of the point-domain
6960 /// `boundary_find_triad_equals_iter_triad_next_projection` pin,
6961 /// so both surfaces' find/iter refinement bridge stays symmetric
6962 /// by construction across the two-surface parity contract.
6963 #[test]
6964 fn ephemeral_find_triad_equals_iter_triad_next_projection() {
6965 for pre_kind in ConditionKind::ALL {
6966 for post_kind in ConditionKind::ALL {
6967 let mut spec = empty_ephemeral();
6968 spec.preconditions.push(cond(pre_kind));
6969 spec.postconditions.push(cond(post_kind));
6970 for query in ConditionKind::ALL {
6971 assert_eq!(
6972 spec.find_precondition_kind(query).map(|c| c.kind),
6973 spec.iter_precondition_kind(query).next().map(|c| c.kind),
6974 "ephemeral precondition find/iter bridge drifted: \
6975 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6976 );
6977 assert_eq!(
6978 spec.find_postcondition_kind(query).map(|c| c.kind),
6979 spec.iter_postcondition_kind(query).next().map(|c| c.kind),
6980 "ephemeral postcondition find/iter bridge drifted: \
6981 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6982 );
6983 assert_eq!(
6984 spec.find_condition_kind(query).map(|c| c.kind),
6985 spec.iter_condition_kind(query).next().map(|c| c.kind),
6986 "ephemeral union find/iter bridge drifted: \
6987 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6988 );
6989 }
6990 }
6991 }
6992 }
6993
6994 // ── EphemeralSpec count triad — scalar cardinality peers ─────────
6995 //
6996 // Byte-for-byte peers of the point-domain `Boundary`
6997 // `count_(pre|post|)condition_kind` triad, tested at the ephemeral
6998 // sugar surface. Same SUM composition on the union arm, same
6999 // slice-level substrate delegation, same composition-law bridge
7000 // against the widened iter refinement.
7001
7002 /// EMPTY-SPEC pin (count-triad) — a default [`EphemeralSpec`]
7003 /// counts `0` from every arm of the count triad for EVERY
7004 /// [`ConditionKind`].
7005 #[test]
7006 fn ephemeral_count_condition_kind_triad_returns_zero_on_empty_spec() {
7007 let spec = empty_ephemeral();
7008 for kind in ConditionKind::ALL {
7009 assert_eq!(
7010 spec.count_precondition_kind(kind),
7011 0,
7012 "empty ephemeral must count 0 on precondition arm for {kind:?}",
7013 );
7014 assert_eq!(
7015 spec.count_postcondition_kind(kind),
7016 0,
7017 "empty ephemeral must count 0 on postcondition arm for {kind:?}",
7018 );
7019 assert_eq!(
7020 spec.count_condition_kind(kind),
7021 0,
7022 "empty ephemeral must count 0 on union arm for {kind:?}",
7023 );
7024 }
7025 }
7026
7027 /// SUBSTRATE-DELEGATION pin (ephemeral count-triad) — the three
7028 /// widened `count_*_kind` methods on [`EphemeralSpec`] delegate
7029 /// verbatim to [`crate::boundary::ConditionSliceExt::count_kind`]
7030 /// on the underlying [`Vec<Condition>`] slices. The
7031 /// `count_condition_kind` union SUMS preconditions and
7032 /// postconditions. Byte-for-byte peer of the point-domain
7033 /// `boundary_count_condition_kind_triad_delegates_and_sums_slice_count_kind`
7034 /// pin; a regression that (a) subtracted rather than summed, (b)
7035 /// collapsed the sum to [`std::cmp::max`], or (c) inlined a
7036 /// divergent count at either half-slice arm on the ephemeral
7037 /// surface only (breaking two-surface parity with [`Boundary`])
7038 /// surfaces HERE.
7039 #[test]
7040 fn ephemeral_count_condition_kind_triad_delegates_and_sums_slice_count_kind() {
7041 for pre_kind in ConditionKind::ALL {
7042 for post_kind in ConditionKind::ALL {
7043 let mut spec = empty_ephemeral();
7044 spec.preconditions.push(cond(pre_kind));
7045 spec.postconditions.push(cond(post_kind));
7046 for query in ConditionKind::ALL {
7047 let via_pre = spec.preconditions.count_kind(query);
7048 let via_post = spec.postconditions.count_kind(query);
7049 assert_eq!(
7050 spec.count_precondition_kind(query),
7051 via_pre,
7052 "ephemeral precondition count arm must delegate: \
7053 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7054 );
7055 assert_eq!(
7056 spec.count_postcondition_kind(query),
7057 via_post,
7058 "ephemeral postcondition count arm must delegate: \
7059 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7060 );
7061 assert_eq!(
7062 spec.count_condition_kind(query),
7063 via_pre + via_post,
7064 "ephemeral union count arm must SUM pre + post: \
7065 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7066 );
7067 }
7068 }
7069 }
7070 }
7071
7072 /// STRUCT-LEVEL DELEGATION pin (count ↔ iter on EphemeralSpec) —
7073 /// the three [`EphemeralSpec`] `count_*_kind` arms equal their
7074 /// widened peers' `.count()` projection at EVERY (pre-populated
7075 /// twice, post-populated, query) triple. Byte-for-byte peer of
7076 /// the point-domain
7077 /// `boundary_count_triad_equals_iter_triad_count_projection`
7078 /// pin. Uses two-preconditions authoring so the union arm's SUM
7079 /// composition witnesses a nontrivial cardinality (rather than
7080 /// coinciding with the presence bit).
7081 #[test]
7082 fn ephemeral_count_triad_equals_iter_triad_count_projection() {
7083 for pre_kind in ConditionKind::ALL {
7084 for post_kind in ConditionKind::ALL {
7085 let mut spec = empty_ephemeral();
7086 spec.preconditions.push(cond(pre_kind));
7087 spec.preconditions.push(cond(pre_kind));
7088 spec.postconditions.push(cond(post_kind));
7089 for query in ConditionKind::ALL {
7090 assert_eq!(
7091 spec.count_precondition_kind(query),
7092 spec.iter_precondition_kind(query).count(),
7093 "ephemeral precondition count/iter bridge drifted: \
7094 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7095 );
7096 assert_eq!(
7097 spec.count_postcondition_kind(query),
7098 spec.iter_postcondition_kind(query).count(),
7099 "ephemeral postcondition count/iter bridge drifted: \
7100 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7101 );
7102 assert_eq!(
7103 spec.count_condition_kind(query),
7104 spec.iter_condition_kind(query).count(),
7105 "ephemeral union count/iter bridge drifted: \
7106 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7107 );
7108 }
7109 }
7110 }
7111 }
7112
7113 // ── EphemeralSpec distinct-set triad — substrate-delegation pin ──
7114 //
7115 // The (precondition, postcondition, condition-union) distinct-set
7116 // triad on [`EphemeralSpec`] delegates to the slice-level substrate
7117 // primitive [`crate::boundary::ConditionSliceExt::distinct_kinds`]
7118 // on each half-slice and composes the union via
7119 // [`Self::has_condition_kind`] over [`ConditionKind::ALL`] — byte-
7120 // for-byte peer of the point-surface distinct-set triad on
7121 // [`crate::boundary::Boundary`]. The two-surface parity contract
7122 // now covers FIVE refinements on the condition axis: the four
7123 // point-probe refinements (has / find / iter / count) AND the ONE
7124 // closed-set-inversion refinement (distinct-set) on both surfaces.
7125
7126 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-kind-count
7127 /// triad) — the three `distinct_*_kind_count` methods on
7128 /// [`EphemeralSpec`] delegate to the slice-level substrate
7129 /// primitive [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
7130 /// over the two `Vec<Condition>` slots and compose the union
7131 /// scalar via `ConditionKind::ALL.filter(|k|
7132 /// has_condition_kind(*k)).count()`. Byte-for-byte peer of the
7133 /// point-surface pin
7134 /// `distinct_condition_kind_count_triad_delegates_to_slice_distinct_kind_count`
7135 /// on [`crate::boundary::Boundary`] — the two-surface parity
7136 /// contract now binds every downstream scalar-cardinality consumer
7137 /// on either surface to the SAME closed-set walk through ONE
7138 /// substrate rather than through per-surface `.distinct_*_kinds().len()`
7139 /// re-materializations that pay for a heap allocation.
7140 #[test]
7141 fn ephemeral_distinct_condition_kind_count_triad_delegates_and_matches_distinct_kinds_len() {
7142 // Empty spec — every arm returns 0.
7143 let spec = empty_ephemeral();
7144 for kind in ConditionKind::ALL {
7145 assert_eq!(
7146 spec.distinct_precondition_kind_count(),
7147 0,
7148 "empty ephemeral spec must return 0 on distinct_precondition_kind_count, kind={kind:?}",
7149 );
7150 assert_eq!(
7151 spec.distinct_postcondition_kind_count(),
7152 0,
7153 "empty ephemeral spec must return 0 on distinct_postcondition_kind_count, kind={kind:?}",
7154 );
7155 assert_eq!(
7156 spec.distinct_condition_kind_count(),
7157 0,
7158 "empty ephemeral spec must return 0 on distinct_condition_kind_count, kind={kind:?}",
7159 );
7160 }
7161
7162 for pre_kind in ConditionKind::ALL {
7163 for post_kind in ConditionKind::ALL {
7164 let mut spec = empty_ephemeral();
7165 spec.preconditions.push(cond(pre_kind));
7166 spec.postconditions.push(cond(post_kind));
7167
7168 assert_eq!(
7169 spec.distinct_precondition_kind_count(),
7170 spec.preconditions.distinct_kind_count(),
7171 "EphemeralSpec::distinct_precondition_kind_count must delegate verbatim to \
7172 preconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7173 );
7174 assert_eq!(
7175 spec.distinct_precondition_kind_count(),
7176 spec.distinct_precondition_kinds().len(),
7177 "EphemeralSpec::distinct_precondition_kind_count must equal \
7178 distinct_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7179 );
7180 assert_eq!(
7181 spec.distinct_postcondition_kind_count(),
7182 spec.postconditions.distinct_kind_count(),
7183 "EphemeralSpec::distinct_postcondition_kind_count must delegate verbatim to \
7184 postconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7185 );
7186 assert_eq!(
7187 spec.distinct_postcondition_kind_count(),
7188 spec.distinct_postcondition_kinds().len(),
7189 "EphemeralSpec::distinct_postcondition_kind_count must equal \
7190 distinct_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7191 );
7192 let expected_union_count = if pre_kind == post_kind { 1 } else { 2 };
7193 assert_eq!(
7194 spec.distinct_condition_kind_count(),
7195 expected_union_count,
7196 "EphemeralSpec::distinct_condition_kind_count must count distinct union kinds \
7197 for pre={pre_kind:?} post={post_kind:?}",
7198 );
7199 assert_eq!(
7200 spec.distinct_condition_kind_count(),
7201 spec.distinct_condition_kinds().len(),
7202 "EphemeralSpec::distinct_condition_kind_count must equal \
7203 distinct_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7204 );
7205 }
7206 }
7207 }
7208
7209 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-set triad)
7210 /// — the three `distinct_*_kinds` methods on [`EphemeralSpec`]
7211 /// delegate to the slice-level substrate primitive over the two
7212 /// `Vec<Condition>` slots and compose the union via
7213 /// `ConditionKind::ALL.filter(|k| has_condition_kind(*k))`. Byte-
7214 /// for-byte peer of the point-surface pin
7215 /// `distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds`
7216 /// on [`crate::boundary::Boundary`] — the two-surface parity
7217 /// contract binds every downstream distinct-set consumer on either
7218 /// surface to the SAME closed-set-inversion primitive through ONE
7219 /// substrate rather than through per-surface re-authored sweeps.
7220 #[test]
7221 fn ephemeral_distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds() {
7222 for pre_kind in ConditionKind::ALL {
7223 for post_kind in ConditionKind::ALL {
7224 let mut spec = empty_ephemeral();
7225 spec.preconditions.push(cond(pre_kind));
7226 spec.postconditions.push(cond(post_kind));
7227
7228 assert_eq!(
7229 spec.distinct_precondition_kinds(),
7230 spec.preconditions.distinct_kinds(),
7231 "EphemeralSpec::distinct_precondition_kinds must delegate verbatim to \
7232 preconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
7233 );
7234 assert_eq!(
7235 spec.distinct_postcondition_kinds(),
7236 spec.postconditions.distinct_kinds(),
7237 "EphemeralSpec::distinct_postcondition_kinds must delegate verbatim to \
7238 postconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
7239 );
7240 let expected_union: Vec<_> = ConditionKind::ALL
7241 .into_iter()
7242 .filter(|k| pre_kind == *k || post_kind == *k)
7243 .collect();
7244 assert_eq!(
7245 spec.distinct_condition_kinds(),
7246 expected_union,
7247 "EphemeralSpec::distinct_condition_kinds must equal ConditionKind::ALL-ordered \
7248 set-union of the two half-slice distinct-sets for pre={pre_kind:?} post={post_kind:?}",
7249 );
7250 }
7251 }
7252 }
7253
7254 /// SUBSTRATE-DELEGATION pin (EphemeralSpec distinct-set ITERATOR
7255 /// triad) — the three `iter_distinct_*_condition_kinds` methods on
7256 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7257 /// [`crate::boundary::ConditionSliceExt::iter_distinct_kinds`] over
7258 /// the two `Vec<Condition>` slots and compose the union via
7259 /// `ConditionKind::ALL.iter().copied().filter(|&k|
7260 /// has_condition_kind(k))`. Byte-for-byte peer of
7261 /// `iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
7262 /// on the point-domain [`crate::boundary::Boundary`] surface — both
7263 /// peers compose against the SAME slice-level iterator substrate.
7264 #[test]
7265 fn ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds() {
7266 for pre_kind in ConditionKind::ALL {
7267 for post_kind in ConditionKind::ALL {
7268 let mut spec = empty_ephemeral();
7269 spec.preconditions.push(cond(pre_kind));
7270 spec.postconditions.push(cond(post_kind));
7271
7272 let pre_via_iter: Vec<_> = spec.iter_distinct_precondition_kinds().collect();
7273 assert_eq!(
7274 pre_via_iter,
7275 spec.distinct_precondition_kinds(),
7276 "EphemeralSpec::iter_distinct_precondition_kinds().collect() drifted from \
7277 distinct_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7278 );
7279 let post_via_iter: Vec<_> = spec.iter_distinct_postcondition_kinds().collect();
7280 assert_eq!(
7281 post_via_iter,
7282 spec.distinct_postcondition_kinds(),
7283 "EphemeralSpec::iter_distinct_postcondition_kinds().collect() drifted from \
7284 distinct_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7285 );
7286 let union_via_iter: Vec<_> = spec.iter_distinct_condition_kinds().collect();
7287 assert_eq!(
7288 union_via_iter,
7289 spec.distinct_condition_kinds(),
7290 "EphemeralSpec::iter_distinct_condition_kinds().collect() drifted from \
7291 distinct_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7292 );
7293 }
7294 }
7295 }
7296
7297 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set ITERATOR
7298 /// triad) — the three `iter_missing_*_condition_kinds` methods on
7299 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7300 /// [`crate::boundary::ConditionSliceExt::iter_missing_kinds`] over
7301 /// the two `Vec<Condition>` slots and compose the union via
7302 /// `ConditionKind::ALL.iter().copied().filter(|&k|
7303 /// !has_condition_kind(k))`. Peer of
7304 /// `ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
7305 /// on the missing side under a NEGATED point-probe.
7306 #[test]
7307 fn ephemeral_iter_missing_condition_kinds_triad_delegates_to_slice_iter_missing_kinds() {
7308 let empty = empty_ephemeral();
7309 let all: Vec<_> = ConditionKind::ALL.to_vec();
7310 assert_eq!(
7311 empty.iter_missing_precondition_kinds().collect::<Vec<_>>(),
7312 all,
7313 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_precondition_kinds",
7314 );
7315 assert_eq!(
7316 empty.iter_missing_postcondition_kinds().collect::<Vec<_>>(),
7317 all,
7318 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_postcondition_kinds",
7319 );
7320 assert_eq!(
7321 empty.iter_missing_condition_kinds().collect::<Vec<_>>(),
7322 all,
7323 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_condition_kinds",
7324 );
7325
7326 for pre_kind in ConditionKind::ALL {
7327 for post_kind in ConditionKind::ALL {
7328 let mut spec = empty_ephemeral();
7329 spec.preconditions.push(cond(pre_kind));
7330 spec.postconditions.push(cond(post_kind));
7331
7332 let pre_via_iter: Vec<_> = spec.iter_missing_precondition_kinds().collect();
7333 assert_eq!(
7334 pre_via_iter,
7335 spec.missing_precondition_kinds(),
7336 "EphemeralSpec::iter_missing_precondition_kinds().collect() drifted from \
7337 missing_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7338 );
7339 let post_via_iter: Vec<_> = spec.iter_missing_postcondition_kinds().collect();
7340 assert_eq!(
7341 post_via_iter,
7342 spec.missing_postcondition_kinds(),
7343 "EphemeralSpec::iter_missing_postcondition_kinds().collect() drifted from \
7344 missing_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7345 );
7346 let union_via_iter: Vec<_> = spec.iter_missing_condition_kinds().collect();
7347 assert_eq!(
7348 union_via_iter,
7349 spec.missing_condition_kinds(),
7350 "EphemeralSpec::iter_missing_condition_kinds().collect() drifted from \
7351 missing_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7352 );
7353 }
7354 }
7355 }
7356
7357 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set triad) —
7358 /// the three `missing_*_kinds` methods on [`EphemeralSpec`]
7359 /// delegate to the slice-level substrate primitive
7360 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over the
7361 /// two `Vec<Condition>` slots and compose the union via
7362 /// `ConditionKind::ALL.filter(|k| !has_condition_kind(*k))`. Sweep
7363 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
7364 /// `missing_condition_kinds_triad_delegates_to_slice_missing_kinds`
7365 /// on the point-domain [`crate::boundary::Boundary`] surface —
7366 /// both peers compose against the SAME slice-level substrate
7367 /// primitive so a regression at the per-slice complement walk
7368 /// fails at that primitive's tests rather than as silent drift at
7369 /// either struct-level arm.
7370 #[test]
7371 fn ephemeral_missing_condition_kinds_triad_delegates_to_slice_missing_kinds() {
7372 // Empty ephemeral spec — every arm returns ConditionKind::ALL.
7373 let empty = empty_ephemeral();
7374 let all_kinds = ConditionKind::ALL.to_vec();
7375 assert_eq!(
7376 empty.missing_precondition_kinds(),
7377 all_kinds,
7378 "empty ephemeral spec must return ConditionKind::ALL on missing_precondition_kinds",
7379 );
7380 assert_eq!(
7381 empty.missing_postcondition_kinds(),
7382 all_kinds,
7383 "empty ephemeral spec must return ConditionKind::ALL on missing_postcondition_kinds",
7384 );
7385 assert_eq!(
7386 empty.missing_condition_kinds(),
7387 all_kinds,
7388 "empty ephemeral spec must return ConditionKind::ALL on missing_condition_kinds",
7389 );
7390
7391 for pre_kind in ConditionKind::ALL {
7392 for post_kind in ConditionKind::ALL {
7393 let mut spec = empty_ephemeral();
7394 spec.preconditions.push(cond(pre_kind));
7395 spec.postconditions.push(cond(post_kind));
7396
7397 assert_eq!(
7398 spec.missing_precondition_kinds(),
7399 spec.preconditions.missing_kinds(),
7400 "EphemeralSpec::missing_precondition_kinds must delegate verbatim to \
7401 preconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7402 );
7403 assert_eq!(
7404 spec.missing_postcondition_kinds(),
7405 spec.postconditions.missing_kinds(),
7406 "EphemeralSpec::missing_postcondition_kinds must delegate verbatim to \
7407 postconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7408 );
7409 // Union: a kind is missing from the union iff it is
7410 // missing from BOTH half-slices (SET-INTERSECTION).
7411 let expected_union: Vec<_> = ConditionKind::ALL
7412 .into_iter()
7413 .filter(|k| pre_kind != *k && post_kind != *k)
7414 .collect();
7415 assert_eq!(
7416 spec.missing_condition_kinds(),
7417 expected_union,
7418 "EphemeralSpec::missing_condition_kinds must equal ConditionKind::ALL-ordered \
7419 set-INTERSECTION of the two half-slice missing-sets for pre={pre_kind:?} post={post_kind:?}",
7420 );
7421 // Partition invariant (distinct ∪ missing == ALL, disjoint).
7422 let distinct = spec.distinct_condition_kinds();
7423 let missing = spec.missing_condition_kinds();
7424 for kind in ConditionKind::ALL {
7425 assert!(
7426 distinct.contains(&kind) ^ missing.contains(&kind),
7427 "EphemeralSpec (distinct, missing) partition violated on {kind:?} for pre={pre_kind:?} post={post_kind:?}",
7428 );
7429 }
7430 assert_eq!(
7431 distinct.len() + missing.len(),
7432 ConditionKind::ALL.len(),
7433 "EphemeralSpec (distinct, missing) cardinality partition drift for pre={pre_kind:?} post={post_kind:?}",
7434 );
7435 }
7436 }
7437 }
7438
7439 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-kind-count triad)
7440 /// — the three `missing_*_kind_count` methods on [`EphemeralSpec`]
7441 /// delegate to the slice-level substrate primitive
7442 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
7443 /// the two `Vec<Condition>` slots and compose the union scalar via
7444 /// `ConditionKind::ALL.iter().filter(|k|
7445 /// !has_condition_kind(**k)).count()`. Sweep
7446 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
7447 /// `missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count`
7448 /// on the point-domain [`crate::boundary::Boundary`] surface —
7449 /// both peers compose against the SAME slice-level substrate
7450 /// primitive so a regression at the per-slice negated closed-set
7451 /// walk fails at that primitive's tests rather than as silent drift
7452 /// at either struct-level scalar-cardinality arm. Also pins the
7453 /// scalar-partition invariant `distinct_kind_count +
7454 /// missing_kind_count == ConditionKind::ALL.len()` per arrangement.
7455 #[test]
7456 fn ephemeral_missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count() {
7457 // Empty ephemeral spec — every arm returns ConditionKind::ALL.len().
7458 let empty = empty_ephemeral();
7459 let total = ConditionKind::ALL.len();
7460 assert_eq!(
7461 empty.missing_precondition_kind_count(),
7462 total,
7463 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_precondition_kind_count",
7464 );
7465 assert_eq!(
7466 empty.missing_postcondition_kind_count(),
7467 total,
7468 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_postcondition_kind_count",
7469 );
7470 assert_eq!(
7471 empty.missing_condition_kind_count(),
7472 total,
7473 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_condition_kind_count",
7474 );
7475
7476 for pre_kind in ConditionKind::ALL {
7477 for post_kind in ConditionKind::ALL {
7478 let mut spec = empty_ephemeral();
7479 spec.preconditions.push(cond(pre_kind));
7480 spec.postconditions.push(cond(post_kind));
7481
7482 // Half-slice arms delegate byte-for-byte to the slice
7483 // substrate primitive.
7484 assert_eq!(
7485 spec.missing_precondition_kind_count(),
7486 spec.preconditions.missing_kind_count(),
7487 "EphemeralSpec::missing_precondition_kind_count must delegate verbatim to \
7488 preconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7489 );
7490 assert_eq!(
7491 spec.missing_precondition_kind_count(),
7492 spec.missing_precondition_kinds().len(),
7493 "EphemeralSpec::missing_precondition_kind_count must equal \
7494 missing_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7495 );
7496 assert_eq!(
7497 spec.missing_postcondition_kind_count(),
7498 spec.postconditions.missing_kind_count(),
7499 "EphemeralSpec::missing_postcondition_kind_count must delegate verbatim to \
7500 postconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7501 );
7502 assert_eq!(
7503 spec.missing_postcondition_kind_count(),
7504 spec.missing_postcondition_kinds().len(),
7505 "EphemeralSpec::missing_postcondition_kind_count must equal \
7506 missing_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7507 );
7508 // Union arm equals missing_condition_kinds().len().
7509 assert_eq!(
7510 spec.missing_condition_kind_count(),
7511 spec.missing_condition_kinds().len(),
7512 "EphemeralSpec::missing_condition_kind_count must equal \
7513 missing_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7514 );
7515 // Scalar-partition invariant: distinct + missing == ALL.
7516 assert_eq!(
7517 spec.distinct_condition_kind_count() + spec.missing_condition_kind_count(),
7518 ConditionKind::ALL.len(),
7519 "EphemeralSpec (distinct, missing) scalar partition drift for pre={pre_kind:?} post={post_kind:?}",
7520 );
7521 }
7522 }
7523 }
7524
7525 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-distinct-kind
7526 /// triad) — the three `first_distinct_*_kind` methods on
7527 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7528 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] over
7529 /// the two `Vec<Condition>` slots and compose the union via
7530 /// `ConditionKind::ALL.iter().copied().find(|k|
7531 /// has_condition_kind(*k))`. Byte-for-byte peer of
7532 /// `first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind`
7533 /// on the point-domain [`crate::boundary::Boundary`] surface — both
7534 /// peers compose against the SAME slice-level substrate primitive
7535 /// so a regression at the per-slice short-circuit walk fails at
7536 /// that primitive's tests rather than as silent drift at either
7537 /// struct-level earliest-element arm.
7538 #[test]
7539 fn ephemeral_first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind() {
7540 // Empty ephemeral spec — every arm returns None.
7541 let empty = empty_ephemeral();
7542 assert_eq!(
7543 empty.first_distinct_precondition_kind(),
7544 None,
7545 "empty ephemeral spec must return None on first_distinct_precondition_kind",
7546 );
7547 assert_eq!(
7548 empty.first_distinct_postcondition_kind(),
7549 None,
7550 "empty ephemeral spec must return None on first_distinct_postcondition_kind",
7551 );
7552 assert_eq!(
7553 empty.first_distinct_condition_kind(),
7554 None,
7555 "empty ephemeral spec must return None on first_distinct_condition_kind",
7556 );
7557
7558 for pre_kind in ConditionKind::ALL {
7559 for post_kind in ConditionKind::ALL {
7560 let mut spec = empty_ephemeral();
7561 spec.preconditions.push(cond(pre_kind));
7562 spec.postconditions.push(cond(post_kind));
7563
7564 assert_eq!(
7565 spec.first_distinct_precondition_kind(),
7566 spec.preconditions.first_distinct_kind(),
7567 "EphemeralSpec::first_distinct_precondition_kind must delegate verbatim to \
7568 preconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7569 );
7570 assert_eq!(
7571 spec.first_distinct_precondition_kind(),
7572 spec.distinct_precondition_kinds().first().copied(),
7573 "EphemeralSpec::first_distinct_precondition_kind must equal \
7574 distinct_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7575 );
7576 assert_eq!(
7577 spec.first_distinct_postcondition_kind(),
7578 spec.postconditions.first_distinct_kind(),
7579 "EphemeralSpec::first_distinct_postcondition_kind must delegate verbatim to \
7580 postconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7581 );
7582 assert_eq!(
7583 spec.first_distinct_postcondition_kind(),
7584 spec.distinct_postcondition_kinds().first().copied(),
7585 "EphemeralSpec::first_distinct_postcondition_kind must equal \
7586 distinct_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7587 );
7588 let expected_union = ConditionKind::ALL
7589 .into_iter()
7590 .find(|k| pre_kind == *k || post_kind == *k);
7591 assert_eq!(
7592 spec.first_distinct_condition_kind(),
7593 expected_union,
7594 "EphemeralSpec::first_distinct_condition_kind must equal earliest ALL entry \
7595 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7596 );
7597 assert_eq!(
7598 spec.first_distinct_condition_kind(),
7599 spec.distinct_condition_kinds().first().copied(),
7600 "EphemeralSpec::first_distinct_condition_kind must equal \
7601 distinct_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7602 );
7603 }
7604 }
7605 }
7606
7607 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-missing-kind triad)
7608 /// — the three `first_missing_*_kind` methods on [`EphemeralSpec`]
7609 /// delegate to the slice-level substrate primitive
7610 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`] over
7611 /// the two `Vec<Condition>` slots and compose the union via
7612 /// `ConditionKind::ALL.iter().copied().find(|k|
7613 /// !has_condition_kind(*k))`. Byte-for-byte peer of
7614 /// `first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind`
7615 /// on the point-domain [`crate::boundary::Boundary`] surface.
7616 #[test]
7617 fn ephemeral_first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind() {
7618 // Empty ephemeral spec — every arm returns Some(ConditionKind::ALL[0]).
7619 let empty = empty_ephemeral();
7620 let first = Some(ConditionKind::ALL[0]);
7621 assert_eq!(
7622 empty.first_missing_precondition_kind(),
7623 first,
7624 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_precondition_kind",
7625 );
7626 assert_eq!(
7627 empty.first_missing_postcondition_kind(),
7628 first,
7629 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_postcondition_kind",
7630 );
7631 assert_eq!(
7632 empty.first_missing_condition_kind(),
7633 first,
7634 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_condition_kind",
7635 );
7636
7637 for pre_kind in ConditionKind::ALL {
7638 for post_kind in ConditionKind::ALL {
7639 let mut spec = empty_ephemeral();
7640 spec.preconditions.push(cond(pre_kind));
7641 spec.postconditions.push(cond(post_kind));
7642
7643 assert_eq!(
7644 spec.first_missing_precondition_kind(),
7645 spec.preconditions.first_missing_kind(),
7646 "EphemeralSpec::first_missing_precondition_kind must delegate verbatim to \
7647 preconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7648 );
7649 assert_eq!(
7650 spec.first_missing_precondition_kind(),
7651 spec.missing_precondition_kinds().first().copied(),
7652 "EphemeralSpec::first_missing_precondition_kind must equal \
7653 missing_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7654 );
7655 assert_eq!(
7656 spec.first_missing_postcondition_kind(),
7657 spec.postconditions.first_missing_kind(),
7658 "EphemeralSpec::first_missing_postcondition_kind must delegate verbatim to \
7659 postconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7660 );
7661 assert_eq!(
7662 spec.first_missing_postcondition_kind(),
7663 spec.missing_postcondition_kinds().first().copied(),
7664 "EphemeralSpec::first_missing_postcondition_kind must equal \
7665 missing_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7666 );
7667 let expected_union = ConditionKind::ALL
7668 .into_iter()
7669 .find(|k| pre_kind != *k && post_kind != *k);
7670 assert_eq!(
7671 spec.first_missing_condition_kind(),
7672 expected_union,
7673 "EphemeralSpec::first_missing_condition_kind must equal earliest ALL entry \
7674 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7675 );
7676 assert_eq!(
7677 spec.first_missing_condition_kind(),
7678 spec.missing_condition_kinds().first().copied(),
7679 "EphemeralSpec::first_missing_condition_kind must equal \
7680 missing_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7681 );
7682 }
7683 }
7684 }
7685
7686 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-distinct-kind
7687 /// triad) — the three `last_distinct_*_kind` methods on
7688 /// [`EphemeralSpec`] delegate to the slice-level substrate
7689 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
7690 /// over the two `Vec<Condition>` slots and compose the union via
7691 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
7692 /// has_condition_kind(*k))`. Byte-for-byte peer of
7693 /// `last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind`
7694 /// on the point-domain [`crate::boundary::Boundary`] surface —
7695 /// both peers compose against the SAME slice-level substrate
7696 /// primitive so a regression at the per-slice REVERSED short-
7697 /// circuit walk fails at that primitive's tests rather than as
7698 /// silent drift at either struct-level latest-element arm.
7699 #[test]
7700 fn ephemeral_last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind() {
7701 // Empty ephemeral spec — every arm returns None.
7702 let empty = empty_ephemeral();
7703 assert_eq!(
7704 empty.last_distinct_precondition_kind(),
7705 None,
7706 "empty ephemeral spec must return None on last_distinct_precondition_kind",
7707 );
7708 assert_eq!(
7709 empty.last_distinct_postcondition_kind(),
7710 None,
7711 "empty ephemeral spec must return None on last_distinct_postcondition_kind",
7712 );
7713 assert_eq!(
7714 empty.last_distinct_condition_kind(),
7715 None,
7716 "empty ephemeral spec must return None on last_distinct_condition_kind",
7717 );
7718
7719 for pre_kind in ConditionKind::ALL {
7720 for post_kind in ConditionKind::ALL {
7721 let mut spec = empty_ephemeral();
7722 spec.preconditions.push(cond(pre_kind));
7723 spec.postconditions.push(cond(post_kind));
7724
7725 assert_eq!(
7726 spec.last_distinct_precondition_kind(),
7727 spec.preconditions.last_distinct_kind(),
7728 "EphemeralSpec::last_distinct_precondition_kind must delegate verbatim to \
7729 preconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7730 );
7731 assert_eq!(
7732 spec.last_distinct_precondition_kind(),
7733 spec.distinct_precondition_kinds().last().copied(),
7734 "EphemeralSpec::last_distinct_precondition_kind must equal \
7735 distinct_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7736 );
7737 assert_eq!(
7738 spec.last_distinct_postcondition_kind(),
7739 spec.postconditions.last_distinct_kind(),
7740 "EphemeralSpec::last_distinct_postcondition_kind must delegate verbatim to \
7741 postconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7742 );
7743 assert_eq!(
7744 spec.last_distinct_postcondition_kind(),
7745 spec.distinct_postcondition_kinds().last().copied(),
7746 "EphemeralSpec::last_distinct_postcondition_kind must equal \
7747 distinct_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7748 );
7749 let expected_union = ConditionKind::ALL
7750 .into_iter()
7751 .rev()
7752 .find(|k| pre_kind == *k || post_kind == *k);
7753 assert_eq!(
7754 spec.last_distinct_condition_kind(),
7755 expected_union,
7756 "EphemeralSpec::last_distinct_condition_kind must equal latest ALL entry \
7757 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7758 );
7759 assert_eq!(
7760 spec.last_distinct_condition_kind(),
7761 spec.distinct_condition_kinds().last().copied(),
7762 "EphemeralSpec::last_distinct_condition_kind must equal \
7763 distinct_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7764 );
7765 }
7766 }
7767 }
7768
7769 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-missing-kind triad)
7770 /// — the three `last_missing_*_kind` methods on [`EphemeralSpec`]
7771 /// delegate to the slice-level substrate primitive
7772 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] over
7773 /// the two `Vec<Condition>` slots and compose the union via
7774 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
7775 /// !has_condition_kind(*k))`. Byte-for-byte peer of
7776 /// `last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind`
7777 /// on the point-domain [`crate::boundary::Boundary`] surface.
7778 #[test]
7779 fn ephemeral_last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind() {
7780 // Empty ephemeral spec — every arm returns Some(*ConditionKind::ALL.last().unwrap()).
7781 let empty = empty_ephemeral();
7782 let last = ConditionKind::ALL.last().copied();
7783 assert_eq!(
7784 empty.last_missing_precondition_kind(),
7785 last,
7786 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_precondition_kind",
7787 );
7788 assert_eq!(
7789 empty.last_missing_postcondition_kind(),
7790 last,
7791 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_postcondition_kind",
7792 );
7793 assert_eq!(
7794 empty.last_missing_condition_kind(),
7795 last,
7796 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_condition_kind",
7797 );
7798
7799 for pre_kind in ConditionKind::ALL {
7800 for post_kind in ConditionKind::ALL {
7801 let mut spec = empty_ephemeral();
7802 spec.preconditions.push(cond(pre_kind));
7803 spec.postconditions.push(cond(post_kind));
7804
7805 assert_eq!(
7806 spec.last_missing_precondition_kind(),
7807 spec.preconditions.last_missing_kind(),
7808 "EphemeralSpec::last_missing_precondition_kind must delegate verbatim to \
7809 preconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7810 );
7811 assert_eq!(
7812 spec.last_missing_precondition_kind(),
7813 spec.missing_precondition_kinds().last().copied(),
7814 "EphemeralSpec::last_missing_precondition_kind must equal \
7815 missing_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7816 );
7817 assert_eq!(
7818 spec.last_missing_postcondition_kind(),
7819 spec.postconditions.last_missing_kind(),
7820 "EphemeralSpec::last_missing_postcondition_kind must delegate verbatim to \
7821 postconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7822 );
7823 assert_eq!(
7824 spec.last_missing_postcondition_kind(),
7825 spec.missing_postcondition_kinds().last().copied(),
7826 "EphemeralSpec::last_missing_postcondition_kind must equal \
7827 missing_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7828 );
7829 let expected_union = ConditionKind::ALL
7830 .into_iter()
7831 .rev()
7832 .find(|k| pre_kind != *k && post_kind != *k);
7833 assert_eq!(
7834 spec.last_missing_condition_kind(),
7835 expected_union,
7836 "EphemeralSpec::last_missing_condition_kind must equal latest ALL entry \
7837 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7838 );
7839 assert_eq!(
7840 spec.last_missing_condition_kind(),
7841 spec.missing_condition_kinds().last().copied(),
7842 "EphemeralSpec::last_missing_condition_kind must equal \
7843 missing_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7844 );
7845 }
7846 }
7847 }
7848
7849 // ── assert_slice_refinement_composition_laws — mirror invocations ──
7850 //
7851 // The substrate testkit primitive
7852 // [`crate::boundary::assert_slice_refinement_composition_laws`]
7853 // pins the FOUR composition laws that bind the
7854 // [`crate::boundary::ConditionSliceExt`] refinement algebra
7855 // (find ↔ iter, count ↔ iter, has ↔ find, has ↔ count) at ONE
7856 // call site per authored arrangement, sweeping
7857 // [`ConditionKind::ALL`]. The two ephemeral-surface tests below
7858 // dispatch the primitive against the two `Vec<Condition>` slots
7859 // ([`EphemeralSpec::preconditions`] +
7860 // [`EphemeralSpec::postconditions`]) authored through the
7861 // ephemeral-surface test-fixture — byte-for-byte peer of the
7862 // point-surface `slice_refinement_composition_laws_hold_across_authored_arrangements`
7863 // + `slice_refinement_composition_laws_hold_on_interleaved_duplicates`
7864 // pins on the [`crate::boundary::Boundary`] surface. Two-surface
7865 // parity contract: the substrate primitive holds on every slice
7866 // reachable through either the point-surface `.preconditions` /
7867 // `.postconditions` fields OR the ephemeral-surface's
7868 // eponymous field pair.
7869
7870 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate
7871 /// primitive [`assert_slice_refinement_composition_laws`] holds
7872 /// on both [`EphemeralSpec::preconditions`] and
7873 /// [`EphemeralSpec::postconditions`] slices for every populated-
7874 /// pair authored through the ephemeral-surface test-fixture.
7875 /// Byte-for-byte peer of
7876 /// `slice_refinement_composition_laws_hold_across_authored_arrangements`
7877 /// on the point surface.
7878 #[test]
7879 fn ephemeral_slice_refinement_composition_laws_hold_across_authored_arrangements() {
7880 let empty = empty_ephemeral();
7881 assert_slice_refinement_composition_laws(empty.preconditions.as_slice());
7882 assert_slice_refinement_composition_laws(empty.postconditions.as_slice());
7883
7884 for pre_kind in ConditionKind::ALL {
7885 for post_kind in ConditionKind::ALL {
7886 let mut spec = empty_ephemeral();
7887 spec.preconditions.push(cond(pre_kind));
7888 spec.postconditions.push(cond(post_kind));
7889 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
7890 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
7891 }
7892 }
7893
7894 for populated in ConditionKind::ALL {
7895 let mut spec = empty_ephemeral();
7896 spec.preconditions.push(cond(populated));
7897 spec.preconditions.push(cond(populated));
7898 spec.preconditions.push(cond(populated));
7899 spec.postconditions.push(cond(populated));
7900 spec.postconditions.push(cond(populated));
7901 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
7902 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
7903 }
7904 }
7905
7906 // ── assert_surface_union_composition_laws — ephemeral surface ────
7907 //
7908 // The substrate testkit macro
7909 // [`crate::assert_surface_union_composition_laws`] pins the FOUR
7910 // union composition laws (has: OR, find: or_else, iter: chain,
7911 // count: SUM) that bind the (pre, post, union) refinement triads
7912 // on the [`EphemeralSpec`] sugar-surface at ONE call site per
7913 // authored arrangement, sweeping [`ConditionKind::ALL`]. Byte-for-
7914 // byte peer of the point-surface
7915 // `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
7916 // / `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
7917 // pins on the [`crate::boundary::Boundary`] surface — the two-
7918 // surface parity contract binds every downstream `condition-<K>`
7919 // / `precondition-<K>` / `postcondition-<K>` require-tag classifier
7920 // on either surface to the SAME four union-composition operators
7921 // through ONE substrate primitive rather than through per-surface
7922 // author-time re-authored sweeps.
7923
7924 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate macro
7925 /// [`crate::assert_surface_union_composition_laws`] passes on
7926 /// [`EphemeralSpec`] for the four canonical authored arrangements
7927 /// (empty spec, precondition-only populated, postcondition-only
7928 /// populated, dual-populated sweep over `ALL × ALL`). Byte-for-byte
7929 /// peer of the point-surface
7930 /// `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
7931 /// pin — the two-surface parity contract binds every union
7932 /// composition law on both surfaces to the SAME substrate
7933 /// primitive.
7934 #[test]
7935 fn ephemeral_surface_union_composition_laws_hold_across_authored_arrangements() {
7936 let empty = empty_ephemeral();
7937 crate::assert_surface_union_composition_laws!(empty);
7938
7939 for populated in ConditionKind::ALL {
7940 let mut pre_only = empty_ephemeral();
7941 pre_only.preconditions.push(cond(populated));
7942 crate::assert_surface_union_composition_laws!(pre_only);
7943
7944 let mut post_only = empty_ephemeral();
7945 post_only.postconditions.push(cond(populated));
7946 crate::assert_surface_union_composition_laws!(post_only);
7947 }
7948
7949 for pre_kind in ConditionKind::ALL {
7950 for post_kind in ConditionKind::ALL {
7951 let mut dual = empty_ephemeral();
7952 dual.preconditions.push(cond(pre_kind));
7953 dual.postconditions.push(cond(post_kind));
7954 crate::assert_surface_union_composition_laws!(dual);
7955 }
7956 }
7957 }
7958
7959 /// SUBSTRATE PANEL pin (ephemeral surface, params-distinguishable
7960 /// duplicates) — the substrate macro holds on an [`EphemeralSpec`]
7961 /// whose two half-slices each carry duplicates of the same kind at
7962 /// multiple positions interleaved with a distinct kind. Byte-for-
7963 /// byte peer of the point-surface
7964 /// `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
7965 /// pin — the non-degenerate composition of every union arm on the
7966 /// sugar-surface binds against the SAME four monoid operators as
7967 /// the point-surface peer. A regression on the ephemeral surface
7968 /// only that (a) collapsed `find`'s `or_else` to `and_then`, (b)
7969 /// collapsed `iter`'s `chain` to `zip`, or (c) collapsed `count`'s
7970 /// SUM to `max` surfaces HERE, breaking two-surface parity.
7971 #[test]
7972 fn ephemeral_surface_union_composition_laws_hold_on_interleaved_duplicates() {
7973 let mut spec = empty_ephemeral();
7974 spec.preconditions.push(Condition {
7975 kind: ConditionKind::ClosedLoopAuth,
7976 params: serde_json::json!({ "side": "pre-1" }),
7977 });
7978 spec.preconditions.push(Condition {
7979 kind: ConditionKind::PromQL,
7980 params: serde_json::json!({ "query": "up" }),
7981 });
7982 spec.preconditions.push(Condition {
7983 kind: ConditionKind::ClosedLoopAuth,
7984 params: serde_json::json!({ "side": "pre-2" }),
7985 });
7986 spec.postconditions.push(Condition {
7987 kind: ConditionKind::PromQL,
7988 params: serde_json::json!({ "query": "healthy" }),
7989 });
7990 spec.postconditions.push(Condition {
7991 kind: ConditionKind::ClosedLoopAuth,
7992 params: serde_json::json!({ "side": "post-1" }),
7993 });
7994 crate::assert_surface_union_composition_laws!(spec);
7995 }
7996
7997 #[test]
7998 fn from_impl_clears_other_intent_variants() {
7999 // Even if someone constructs an EphemeralSpec by hand and the
8000 // resulting ProcessSpec is later mutated, the From bridge sets
8001 // every non-Aplicacao slot to None explicitly.
8002 let e = EphemeralSpec {
8003 aplicacao: demo_overlay(),
8004 ttl: "10m".into(),
8005 teardown: TeardownPolicy::Never,
8006 max_concurrent: 0,
8007 postconditions: vec![],
8008 preconditions: vec![],
8009 verify_timeout: None,
8010 classification: None,
8011 parent: Some("seph.1".into()),
8012 exports: vec![],
8013 routing: None,
8014 };
8015 let ps: ProcessSpec = e.into();
8016 assert!(ps.intent.nix.is_none());
8017 assert!(ps.intent.flux.is_none());
8018 assert!(ps.intent.lisp.is_none());
8019 assert!(ps.intent.container.is_none());
8020 assert!(ps.intent.guest.is_none());
8021 assert!(ps.intent.aplicacao.is_some());
8022 assert_eq!(ps.identity.parent.as_deref(), Some("seph.1"));
8023 }
8024
8025 // ── EphemeralSpec::has_teardown_policy substrate pins ────────────
8026 //
8027 // Fail-before-pass-after granularity:
8028 // `EphemeralSpec::has_teardown_policy` did not exist before this
8029 // commit — the (`self.teardown == kind`) scalar-carrier probe on
8030 // the sugar-surface [`EphemeralSpec`] lived only implicitly via
8031 // hand-authored comparisons at potential future call sites, with
8032 // no analogue to the peer
8033 // [`crate::lifetime::EphemeralLifetime::has_teardown_policy`] on
8034 // the point-surface carrier. The lift adds the peer inherent
8035 // method on the [`EphemeralSpec`] sugar-surface so both surfaces'
8036 // `teardown-policy-<kind>` require-tag families in
8037 // `tatara-reconciler::bin::tatara-check` compose against the SAME
8038 // scalar `==` shape in lockstep. A regression that (a) hard-coded
8039 // the arm to a single kind, (b) inverted the closed-set match
8040 // (silently returning `true` on non-matching variants), or (c)
8041 // probed the wrong slot (a stray comparison against `ttl` /
8042 // `max_concurrent`) fails HERE at the substrate primitive rather
8043 // than as silent operator-facing drift at the ephemeral
8044 // `teardown-policy-<kind>` require-tag surface.
8045
8046 /// STORED-slot pin — an ephemeral spec that carries a given
8047 /// [`TeardownPolicy`] returns `true` for that kind, `false` for
8048 /// every other variant. Sweep the [`TeardownPolicy::ALL`] × ALL
8049 /// cross so a regression that hard-coded the arm to a single kind
8050 /// or wired the closure to a fixed unrelated field fails HERE at
8051 /// the substrate primitive. Byte-for-byte peer of
8052 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_returns_true_iff_variant_matches`]
8053 /// on the point-surface [`crate::lifetime::EphemeralLifetime`]
8054 /// carrier — the two surfaces publish identical `==` scalar
8055 /// semantics on their respective `teardown` / `teardown_policy`
8056 /// slots.
8057 #[test]
8058 fn has_teardown_policy_returns_true_iff_ephemeral_teardown_matches_per_kind() {
8059 for populated in TeardownPolicy::ALL {
8060 let mut spec = empty_ephemeral();
8061 spec.teardown = populated;
8062 for query in TeardownPolicy::ALL {
8063 let expected = query == populated;
8064 assert_eq!(
8065 spec.has_teardown_policy(query),
8066 expected,
8067 "ephemeral teardown={populated:?}: query {query:?} drifted",
8068 );
8069 }
8070 }
8071 }
8072
8073 /// DEFAULT-SLOT pin — an [`EphemeralSpec`] whose `teardown` slot
8074 /// is [`TeardownPolicy::default`] (`Always`) returns `true` for
8075 /// `Always` and `false` for every other variant. The
8076 /// (required-scalar-child) corner has no absent state — a
8077 /// hand-authored spec that omits `:teardown` from the
8078 /// `(defephemeral …)` form IS configured for `Always`, and this
8079 /// pin locks the corner's default-arm short-circuit as identical
8080 /// to the (Option-parent × defaulted-scalar-child) corner's
8081 /// reachable arm on the point surface (both return `true` on
8082 /// `Always` only). Byte-for-byte peer of
8083 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_default_probes_always_only`]
8084 /// on the point-surface carrier.
8085 #[test]
8086 fn has_teardown_policy_default_probes_always_only_on_ephemeral() {
8087 let spec = EphemeralSpec {
8088 teardown: TeardownPolicy::default(),
8089 ..empty_ephemeral()
8090 };
8091 for kind in TeardownPolicy::ALL {
8092 let expected = kind == TeardownPolicy::Always;
8093 assert_eq!(
8094 spec.has_teardown_policy(kind),
8095 expected,
8096 "default ephemeral (teardown=Always) baseline: query {kind:?} must be {expected}",
8097 );
8098 }
8099 }
8100
8101 // ── derived-bool-predicate presence probe on EphemeralSpec ×
8102 // TeardownPolicy × ProcessPhase ──
8103 //
8104 // Fail-before-pass-after granularity:
8105 // [`EphemeralSpec::has_teardown_firing_on`] did not exist before
8106 // this commit — the ephemeral sugar surface's require-tag algebra
8107 // discriminated the teardown axis only by the RAW authored variant
8108 // (via `teardown-policy-<kind>`), never by the derived
8109 // [`ProcessPhase`] transition the stored policy fires on
8110 // ([`TeardownPolicy::should_teardown_on`]). Post-lift the shape
8111 // lives at ONE inherent method that byte-for-byte parallels
8112 // [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
8113 // on the point-surface carrier, and both surfaces' require-tag
8114 // classifiers publish a symmetric `teardown-fires-on-<phase>`
8115 // family through the SAME predicate.
8116
8117 /// TRUTH-TABLE DIAGONAL — for every [`TeardownPolicy`] variant,
8118 /// an [`EphemeralSpec`] whose `teardown` slot is set to that
8119 /// variant returns `has_teardown_firing_on(phase)` in agreement
8120 /// with [`TeardownPolicy::should_teardown_on`] for every
8121 /// [`ProcessPhase`] variant. Sweep [`TeardownPolicy::ALL`] ×
8122 /// [`ProcessPhase::ALL`] full cross so a regression that hard-
8123 /// coded the arm to a single policy, wired to the wrong field, or
8124 /// inverted the predicate direction fails HERE at the substrate
8125 /// primitive on the sugar surface (byte-for-byte peer of
8126 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase`]
8127 /// on the point carrier).
8128 #[test]
8129 fn has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase_on_ephemeral() {
8130 for populated in TeardownPolicy::ALL {
8131 let spec = EphemeralSpec {
8132 teardown: populated,
8133 ..empty_ephemeral()
8134 };
8135 for phase in ProcessPhase::ALL {
8136 assert_eq!(
8137 spec.has_teardown_firing_on(phase),
8138 populated.should_teardown_on(phase),
8139 "teardown={populated:?}, phase={phase:?}: predicate drift from \
8140 should_teardown_on projection",
8141 );
8142 }
8143 }
8144 }
8145
8146 /// TWO-SURFACE PARITY PIN — for every [`TeardownPolicy`] variant
8147 /// and every [`ProcessPhase`] variant, the sugar-surface probe
8148 /// and the lowered point-surface probe agree. The `EphemeralSpec
8149 /// → ProcessSpec` lowering routes the stored `teardown` slot
8150 /// through the SAME [`TeardownPolicy::should_teardown_on`]
8151 /// projection on both sides, so the sugar caller and the lowered
8152 /// caller can never disagree — a regression that (a) drifted
8153 /// [`Self::teardown`] between sugar and lowered, (b) rewired
8154 /// either probe body to bypass the shared substrate primitive, or
8155 /// (c) skewed the (policy, phase) truth table between the two
8156 /// surfaces fails HERE at the two-surface boundary rather than at
8157 /// the operator-facing require-tag classifier.
8158 #[test]
8159 fn has_teardown_firing_on_matches_point_peer_through_lowered_teardown_policy() {
8160 for populated in TeardownPolicy::ALL {
8161 let sugar = EphemeralSpec {
8162 teardown: populated,
8163 ..empty_ephemeral()
8164 };
8165 let lowered: ProcessSpec = sugar.clone().into();
8166 let lowered_eph = lowered
8167 .lifetime
8168 .resolved_ephemeral()
8169 .expect("lowered spec must be ephemeral");
8170 for phase in ProcessPhase::ALL {
8171 assert_eq!(
8172 sugar.has_teardown_firing_on(phase),
8173 lowered_eph.has_teardown_firing_on(phase),
8174 "sugar-vs-lowered predicate drift for teardown={populated:?}, phase={phase:?}",
8175 );
8176 }
8177 }
8178 }
8179
8180 // ── EphemeralSpec::resolved_classification + has_point_type pins ─────
8181 //
8182 // Fail-before-pass-after granularity: `resolved_classification` and
8183 // `has_point_type` did not exist pre-lift on `impl EphemeralSpec` — every
8184 // caller wanting the resolved [`Classification`] on the ephemeral
8185 // sugar-surface (currently zero; future ephemeral-surface classification-
8186 // axis require-tag families in `tatara-reconciler::bin::tatara-check`,
8187 // typed audit hooks, documentation generators listing the ephemeral
8188 // surface's known require-tag vocabulary) restated the two-line
8189 // `self.classification.as_ref().unwrap_or(&default_ephemeral_class())`
8190 // resolver body at their site. Post-lift both callers of the resolver
8191 // (`Self::has_point_type` and every future classification-axis peer)
8192 // route through ONE inherent method that shares the fill-through with
8193 // the sibling `From<EphemeralSpec> for ProcessSpec` lowering
8194 // byte-for-byte. A regression that (a) inverted the arm (`Some` filled
8195 // through the default), (b) drifted the default from the sibling
8196 // primitive `Classification::gate_compute()`, or (c) shifted the
8197 // `Cow<'_, Classification>` return shape (a stray `.clone()` on the
8198 // populated arm) fails HERE at the substrate primitive rather than as
8199 // silent operator-facing drift at a future
8200 // `point-type-<kind>` ephemeral require-tag surface.
8201
8202 /// AUTHORED-slot pin — an [`EphemeralSpec`] whose
8203 /// [`EphemeralSpec::classification`] slot names a concrete
8204 /// [`Classification`] returns [`Cow::Borrowed`] pointing at that
8205 /// authored value from [`Self::resolved_classification`]. Pins the
8206 /// populated-arm zero-allocation contract: a caller reading past
8207 /// the resolver sees the SAME byte address the operator authored,
8208 /// so the resolver does not silently clone the authored slot on
8209 /// the populated arm.
8210 #[test]
8211 fn resolved_classification_borrows_authored_slot() {
8212 let mut spec = empty_ephemeral();
8213 let mut authored = Classification::gate_compute();
8214 authored.point_type = ConvergencePointType::Fork;
8215 spec.classification = Some(authored.clone());
8216 let resolved = spec.resolved_classification();
8217 assert!(matches!(resolved, Cow::Borrowed(_)));
8218 assert_eq!(&*resolved, &authored);
8219 }
8220
8221 /// ABSENT-slot pin — an [`EphemeralSpec`] whose
8222 /// [`EphemeralSpec::classification`] slot is `None` returns
8223 /// [`Cow::Owned`] with the SAME value the sibling
8224 /// [`default_ephemeral_class`] baseline produces. Pins the
8225 /// two-surface parity contract with `From<EphemeralSpec> for
8226 /// ProcessSpec`: both sites fill through the SAME baseline on
8227 /// `None`, so the ephemeral require-tag surface's future
8228 /// `point-type-<kind>` family reads identically on the authored
8229 /// spec and on the mechanically lowered `ProcessSpec`.
8230 #[test]
8231 fn resolved_classification_fills_default_on_absent_slot() {
8232 let spec = empty_ephemeral();
8233 assert!(spec.classification.is_none());
8234 let resolved = spec.resolved_classification();
8235 assert!(matches!(resolved, Cow::Owned(_)));
8236 assert_eq!(&*resolved, &default_ephemeral_class());
8237 }
8238
8239 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8240 /// [`EphemeralSpec::classification`] slot names a concrete
8241 /// [`Classification`] returns `true` from
8242 /// [`Self::has_point_type`] on the authored
8243 /// [`ConvergencePointType`] slot and `false` for every other
8244 /// variant. Sweep the [`ConvergencePointType::ALL`] × ALL cross so
8245 /// a regression that hard-coded the arm to a single kind or wired
8246 /// the closure to a fixed unrelated slot fails HERE at the
8247 /// substrate primitive. Byte-for-byte peer of
8248 /// [`crate::classification::tests`]'s point-surface
8249 /// [`Classification::has_point_type`] populated-slot sweep on the
8250 /// SAME closed-set primitive.
8251 #[test]
8252 fn has_point_type_returns_true_iff_authored_classification_matches_per_kind() {
8253 for populated in ConvergencePointType::ALL {
8254 let mut classification = Classification::gate_compute();
8255 classification.point_type = populated;
8256 let mut spec = empty_ephemeral();
8257 spec.classification = Some(classification);
8258 for query in ConvergencePointType::ALL {
8259 let expected = query == populated;
8260 assert_eq!(
8261 spec.has_point_type(query),
8262 expected,
8263 "ephemeral classification.point_type={populated:?}: query {query:?} drifted",
8264 );
8265 }
8266 }
8267 }
8268
8269 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8270 /// [`EphemeralSpec::classification`] slot is `None` returns
8271 /// `true` from [`Self::has_point_type`] on
8272 /// [`ConvergencePointType::Gate`] (the `default_ephemeral_class`
8273 /// baseline's `point_type`) and `false` on every other variant.
8274 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
8275 /// default-arm short-circuit: on the ephemeral sugar surface the
8276 /// parent Option is filled through the workspace baseline rather
8277 /// than reading `false` on every variant like the encapsulation-
8278 /// mode / encapsulation-target / routing-form Option-parent
8279 /// corners.
8280 #[test]
8281 fn has_point_type_probes_gate_only_on_absent_classification() {
8282 let spec = empty_ephemeral();
8283 assert!(spec.classification.is_none());
8284 for kind in ConvergencePointType::ALL {
8285 let expected = kind == ConvergencePointType::Gate;
8286 assert_eq!(
8287 spec.has_point_type(kind),
8288 expected,
8289 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8290 );
8291 }
8292 }
8293
8294 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8295 /// identically through [`Self::has_point_type`] AND through
8296 /// `<eph.clone().into::<ProcessSpec>>()`
8297 /// `.classification.has_point_type(kind)` on the mechanically-
8298 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8299 /// classification on every [`ConvergencePointType::ALL`] variant)
8300 /// × ALL queries so a future regression on either side of the
8301 /// resolver (a shift in the ephemeral resolver's default, a
8302 /// shift in the `From<EphemeralSpec>` lowering's fill-through)
8303 /// fails HERE at the parity boundary.
8304 #[test]
8305 fn has_point_type_matches_point_peer_through_lowered_classification() {
8306 // Absent classification: both surfaces resolve through the SAME
8307 // default and agree on every variant.
8308 let eph = empty_ephemeral();
8309 let lowered: ProcessSpec = eph.clone().into();
8310 for query in ConvergencePointType::ALL {
8311 assert_eq!(
8312 eph.has_point_type(query),
8313 lowered.classification.has_point_type(query),
8314 "None-classification parity drift on query {query:?}",
8315 );
8316 }
8317 // Authored classification: both surfaces read the same authored
8318 // value verbatim.
8319 for populated in ConvergencePointType::ALL {
8320 let mut classification = Classification::gate_compute();
8321 classification.point_type = populated;
8322 let mut eph = empty_ephemeral();
8323 eph.classification = Some(classification);
8324 let lowered: ProcessSpec = eph.clone().into();
8325 for query in ConvergencePointType::ALL {
8326 assert_eq!(
8327 eph.has_point_type(query),
8328 lowered.classification.has_point_type(query),
8329 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8330 );
8331 }
8332 }
8333 }
8334
8335 // ── EphemeralSpec::has_substrate pins ────────────────────────────
8336 //
8337 // Fail-before-pass-after granularity: [`Self::has_substrate`] did
8338 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8339 // through `.resolved_classification().substrate == kind` or through
8340 // the lowered `ProcessSpec`'s `spec.classification.has_substrate`.
8341 // Post-lift the SECOND classification-axis peer on the ephemeral
8342 // sugar surface routes through the SAME
8343 // [`Self::resolved_classification`] resolver + the sibling closed-
8344 // set primitive [`Classification::has_substrate`], so a regression
8345 // that dropped the resolver hop, inverted the `Some`/`None`
8346 // fill-through, or wired the closure to a fixed unrelated slot
8347 // fails HERE.
8348
8349 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8350 /// [`EphemeralSpec::classification`] slot names a concrete
8351 /// [`Classification`] returns `true` from
8352 /// [`Self::has_substrate`] on the authored [`SubstrateType`] slot
8353 /// and `false` for every other variant. Sweep the
8354 /// [`SubstrateType::ALL`] × ALL cross so a regression that
8355 /// hard-coded the arm to a single kind or wired the closure to a
8356 /// fixed unrelated slot fails HERE at the substrate primitive.
8357 /// Byte-for-byte peer of the point-surface
8358 /// [`Classification::has_substrate`] populated-slot sweep on the
8359 /// SAME closed-set primitive.
8360 #[test]
8361 fn has_substrate_returns_true_iff_authored_classification_matches_per_kind() {
8362 for populated in SubstrateType::ALL {
8363 let mut classification = Classification::gate_compute();
8364 classification.substrate = populated;
8365 let mut spec = empty_ephemeral();
8366 spec.classification = Some(classification);
8367 for query in SubstrateType::ALL {
8368 let expected = query == populated;
8369 assert_eq!(
8370 spec.has_substrate(query),
8371 expected,
8372 "ephemeral classification.substrate={populated:?}: query {query:?} drifted",
8373 );
8374 }
8375 }
8376 }
8377
8378 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8379 /// [`EphemeralSpec::classification`] slot is `None` returns
8380 /// `true` from [`Self::has_substrate`] on
8381 /// [`SubstrateType::Compute`] (the `default_ephemeral_class`
8382 /// baseline's `substrate`) and `false` on every other variant.
8383 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
8384 /// default-arm short-circuit on the SECOND classification-axis
8385 /// peer: on the ephemeral sugar surface the parent Option is
8386 /// filled through the workspace baseline rather than reading
8387 /// `false` on every variant like the Option-parent encapsulates /
8388 /// routing corners.
8389 #[test]
8390 fn has_substrate_probes_compute_only_on_absent_classification() {
8391 let spec = empty_ephemeral();
8392 assert!(spec.classification.is_none());
8393 for kind in SubstrateType::ALL {
8394 let expected = kind == SubstrateType::Compute;
8395 assert_eq!(
8396 spec.has_substrate(kind),
8397 expected,
8398 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8399 );
8400 }
8401 }
8402
8403 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8404 /// identically through [`Self::has_substrate`] AND through
8405 /// `<eph.clone().into::<ProcessSpec>>()`
8406 /// `.classification.has_substrate(kind)` on the mechanically-
8407 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8408 /// classification on every [`SubstrateType::ALL`] variant) × ALL
8409 /// queries so a future regression on either side of the resolver
8410 /// (a shift in the ephemeral resolver's default, a shift in the
8411 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8412 /// the parity boundary. Byte-for-byte peer of the sibling
8413 /// [`Self::has_point_type`] two-surface parity pin on the SAME
8414 /// `Cow`-resolver carrier — the SECOND classification-axis
8415 /// two-surface parity contract on the ephemeral surface.
8416 #[test]
8417 fn has_substrate_matches_point_peer_through_lowered_classification() {
8418 // Absent classification: both surfaces resolve through the SAME
8419 // default and agree on every variant.
8420 let eph = empty_ephemeral();
8421 let lowered: ProcessSpec = eph.clone().into();
8422 for query in SubstrateType::ALL {
8423 assert_eq!(
8424 eph.has_substrate(query),
8425 lowered.classification.has_substrate(query),
8426 "None-classification parity drift on query {query:?}",
8427 );
8428 }
8429 // Authored classification: both surfaces read the same authored
8430 // value verbatim.
8431 for populated in SubstrateType::ALL {
8432 let mut classification = Classification::gate_compute();
8433 classification.substrate = populated;
8434 let mut eph = empty_ephemeral();
8435 eph.classification = Some(classification);
8436 let lowered: ProcessSpec = eph.clone().into();
8437 for query in SubstrateType::ALL {
8438 assert_eq!(
8439 eph.has_substrate(query),
8440 lowered.classification.has_substrate(query),
8441 "authored classification.substrate={populated:?}: parity drift on query {query:?}",
8442 );
8443 }
8444 }
8445 }
8446
8447 // ── EphemeralSpec::has_calm pins ─────────────────────────────────
8448 //
8449 // Fail-before-pass-after granularity: [`Self::has_calm`] did not
8450 // exist pre-lift on `impl EphemeralSpec` — every callsite went
8451 // through `.resolved_classification().calm == kind` or through the
8452 // lowered `ProcessSpec`'s `spec.classification.has_calm`. Post-
8453 // lift the THIRD classification-axis peer on the ephemeral sugar
8454 // surface routes through the SAME
8455 // [`Self::resolved_classification`] resolver + the sibling closed-
8456 // set primitive [`Classification::has_calm`], so a regression that
8457 // dropped the resolver hop, inverted the `Some`/`None` fill-
8458 // through, or wired the closure to a fixed unrelated slot fails
8459 // HERE. Distinct from the FIRST + SECOND peers on the (Option-
8460 // parent × NON-DEFAULT-scalar-child) corner: the (Option-parent ×
8461 // DEFAULTED-scalar-child) corner this peer opens has BOTH the
8462 // parent fill-through baseline (`default_ephemeral_class`) AND the
8463 // child's own `#[default]` land on the SAME variant
8464 // ([`CalmClassification::Monotone`]), a two-defaults composition
8465 // property the three pins below all exercise.
8466
8467 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8468 /// [`EphemeralSpec::classification`] slot names a concrete
8469 /// [`Classification`] returns `true` from [`Self::has_calm`] on
8470 /// the authored [`CalmClassification`] slot and `false` for every
8471 /// other variant. Sweep the [`CalmClassification::ALL`] × ALL
8472 /// cross so a regression that hard-coded the arm to a single
8473 /// kind or wired the closure to a fixed unrelated slot fails HERE
8474 /// at the substrate primitive. Byte-for-byte peer of the point-
8475 /// surface [`Classification::has_calm`] populated-slot sweep on
8476 /// the SAME closed-set primitive.
8477 #[test]
8478 fn has_calm_returns_true_iff_authored_classification_matches_per_kind() {
8479 for populated in CalmClassification::ALL {
8480 let mut classification = Classification::gate_compute();
8481 classification.calm = populated;
8482 let mut spec = empty_ephemeral();
8483 spec.classification = Some(classification);
8484 for query in CalmClassification::ALL {
8485 let expected = query == populated;
8486 assert_eq!(
8487 spec.has_calm(query),
8488 expected,
8489 "ephemeral classification.calm={populated:?}: query {query:?} drifted",
8490 );
8491 }
8492 }
8493 }
8494
8495 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8496 /// [`EphemeralSpec::classification`] slot is `None` returns
8497 /// `true` from [`Self::has_calm`] on
8498 /// [`CalmClassification::Monotone`] (the `default_ephemeral_class`
8499 /// baseline's `calm` axis AND the [`CalmClassification`] child's
8500 /// own `#[default]` variant) and `false` on every other variant.
8501 /// Pins the (Option-parent × DEFAULTED-scalar-child ×
8502 /// operator-resolvable-baseline) corner's default-arm short-
8503 /// circuit on the THIRD classification-axis peer — distinct from
8504 /// the FIRST + SECOND peers on the (Option-parent × NON-DEFAULT-
8505 /// scalar-child) corner which default through a specific chosen
8506 /// baseline ([`ConvergencePointType::Gate`],
8507 /// [`SubstrateType::Compute`]) rather than through the child's
8508 /// own `#[default]`. Two-defaults composition property: both the
8509 /// parent fill-through and the child's `#[default]` land on the
8510 /// SAME variant, so the ephemeral sugar surface's `calm-Monotone`
8511 /// require-tag reads `true` on every operator-authored spec that
8512 /// omits both the `:classification` slot AND the `:calm` sub-slot,
8513 /// pinning the workspace's monotone-by-default posture.
8514 #[test]
8515 fn has_calm_probes_monotone_only_on_absent_classification() {
8516 let spec = empty_ephemeral();
8517 assert!(spec.classification.is_none());
8518 for kind in CalmClassification::ALL {
8519 let expected = kind == CalmClassification::Monotone;
8520 assert_eq!(
8521 spec.has_calm(kind),
8522 expected,
8523 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8524 );
8525 }
8526 }
8527
8528 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8529 /// identically through [`Self::has_calm`] AND through
8530 /// `<eph.clone().into::<ProcessSpec>>()`
8531 /// `.classification.has_calm(kind)` on the mechanically-
8532 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8533 /// classification on every [`CalmClassification::ALL`] variant) ×
8534 /// ALL queries so a future regression on either side of the
8535 /// resolver (a shift in the ephemeral resolver's default, a shift
8536 /// in the `From<EphemeralSpec>` lowering's fill-through) fails
8537 /// HERE at the parity boundary. Byte-for-byte peer of the sibling
8538 /// [`Self::has_point_type`] + [`Self::has_substrate`] two-surface
8539 /// parity pins on the SAME `Cow`-resolver carrier — the THIRD
8540 /// classification-axis two-surface parity contract on the
8541 /// ephemeral surface, and the FIRST on the (Option-parent ×
8542 /// DEFAULTED-scalar-child) corner.
8543 #[test]
8544 fn has_calm_matches_point_peer_through_lowered_classification() {
8545 // Absent classification: both surfaces resolve through the SAME
8546 // default and agree on every variant.
8547 let eph = empty_ephemeral();
8548 let lowered: ProcessSpec = eph.clone().into();
8549 for query in CalmClassification::ALL {
8550 assert_eq!(
8551 eph.has_calm(query),
8552 lowered.classification.has_calm(query),
8553 "None-classification parity drift on query {query:?}",
8554 );
8555 }
8556 // Authored classification: both surfaces read the same authored
8557 // value verbatim.
8558 for populated in CalmClassification::ALL {
8559 let mut classification = Classification::gate_compute();
8560 classification.calm = populated;
8561 let mut eph = empty_ephemeral();
8562 eph.classification = Some(classification);
8563 let lowered: ProcessSpec = eph.clone().into();
8564 for query in CalmClassification::ALL {
8565 assert_eq!(
8566 eph.has_calm(query),
8567 lowered.classification.has_calm(query),
8568 "authored classification.calm={populated:?}: parity drift on query {query:?}",
8569 );
8570 }
8571 }
8572 }
8573
8574 // ── EphemeralSpec::has_data_classification pins ──────────────────
8575 //
8576 // Fail-before-pass-after granularity: [`Self::has_data_classification`]
8577 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
8578 // went through `.resolved_classification().data_classification ==
8579 // kind` or through the lowered `ProcessSpec`'s
8580 // `spec.classification.has_data_classification`. Post-lift the
8581 // FOURTH classification-axis peer on the ephemeral sugar surface
8582 // routes through the SAME [`Self::resolved_classification`]
8583 // resolver + the sibling closed-set primitive
8584 // [`crate::classification::Classification::has_data_classification`],
8585 // so a regression that dropped the resolver hop, inverted the
8586 // `Some`/`None` fill-through, or wired the closure to a fixed
8587 // unrelated slot fails HERE. SECOND occupant on the (Option-parent
8588 // × DEFAULTED-scalar-child × operator-resolvable-baseline) corner
8589 // alongside [`Self::has_calm`]: both the parent fill-through
8590 // baseline (`default_ephemeral_class`) AND the child's own
8591 // `#[default]` land on the SAME variant
8592 // ([`DataClassification::Internal`]), a two-defaults composition
8593 // property the three pins below all exercise.
8594
8595 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8596 /// [`EphemeralSpec::classification`] slot names a concrete
8597 /// [`Classification`] returns `true` from
8598 /// [`Self::has_data_classification`] on the authored
8599 /// [`DataClassification`] slot and `false` for every other
8600 /// variant. Sweep the [`DataClassification::ALL`] × ALL cross so
8601 /// a regression that hard-coded the arm to a single kind or
8602 /// wired the closure to a fixed unrelated slot fails HERE at the
8603 /// substrate primitive. Byte-for-byte peer of the point-surface
8604 /// [`Classification::has_data_classification`] populated-slot
8605 /// sweep on the SAME closed-set primitive.
8606 #[test]
8607 fn has_data_classification_returns_true_iff_authored_classification_matches_per_kind() {
8608 for populated in DataClassification::ALL {
8609 let mut classification = Classification::gate_compute();
8610 classification.data_classification = populated;
8611 let mut spec = empty_ephemeral();
8612 spec.classification = Some(classification);
8613 for query in DataClassification::ALL {
8614 let expected = query == populated;
8615 assert_eq!(
8616 spec.has_data_classification(query),
8617 expected,
8618 "ephemeral classification.data_classification={populated:?}: query {query:?} drifted",
8619 );
8620 }
8621 }
8622 }
8623
8624 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8625 /// [`EphemeralSpec::classification`] slot is `None` returns
8626 /// `true` from [`Self::has_data_classification`] on
8627 /// [`DataClassification::Internal`] (the `default_ephemeral_class`
8628 /// baseline's `data_classification` axis AND the
8629 /// [`DataClassification`] child's own `#[default]` variant) and
8630 /// `false` on every other variant. Pins the (Option-parent ×
8631 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner's
8632 /// default-arm short-circuit on the FOURTH classification-axis
8633 /// peer — SECOND occupant on that corner after [`Self::has_calm`]
8634 /// opened it. Two-defaults composition property: both the parent
8635 /// fill-through and the child's `#[default]` land on the SAME
8636 /// variant, so the ephemeral sugar surface's
8637 /// `data-classification-Internal` require-tag reads `true` on
8638 /// every operator-authored spec that omits both the
8639 /// `:classification` slot AND the `:data-classification` sub-slot,
8640 /// pinning the workspace's internal-by-default sensitivity posture.
8641 #[test]
8642 fn has_data_classification_probes_internal_only_on_absent_classification() {
8643 let spec = empty_ephemeral();
8644 assert!(spec.classification.is_none());
8645 for kind in DataClassification::ALL {
8646 let expected = kind == DataClassification::Internal;
8647 assert_eq!(
8648 spec.has_data_classification(kind),
8649 expected,
8650 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8651 );
8652 }
8653 }
8654
8655 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8656 /// identically through [`Self::has_data_classification`] AND
8657 /// through `<eph.clone().into::<ProcessSpec>>()`
8658 /// `.classification.has_data_classification(kind)` on the
8659 /// mechanically-lowered `ProcessSpec`. Sweeps (`None`
8660 /// classification, `Some(_)` classification on every
8661 /// [`DataClassification::ALL`] variant) × ALL queries so a
8662 /// future regression on either side of the resolver (a shift in
8663 /// the ephemeral resolver's default, a shift in the
8664 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8665 /// the parity boundary. Byte-for-byte peer of the sibling
8666 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
8667 /// [`Self::has_calm`] two-surface parity pins on the SAME
8668 /// `Cow`-resolver carrier — the FOURTH classification-axis
8669 /// two-surface parity contract on the ephemeral surface, and the
8670 /// SECOND on the (Option-parent × DEFAULTED-scalar-child) corner.
8671 #[test]
8672 fn has_data_classification_matches_point_peer_through_lowered_classification() {
8673 // Absent classification: both surfaces resolve through the SAME
8674 // default and agree on every variant.
8675 let eph = empty_ephemeral();
8676 let lowered: ProcessSpec = eph.clone().into();
8677 for query in DataClassification::ALL {
8678 assert_eq!(
8679 eph.has_data_classification(query),
8680 lowered.classification.has_data_classification(query),
8681 "None-classification parity drift on query {query:?}",
8682 );
8683 }
8684 // Authored classification: both surfaces read the same authored
8685 // value verbatim.
8686 for populated in DataClassification::ALL {
8687 let mut classification = Classification::gate_compute();
8688 classification.data_classification = populated;
8689 let mut eph = empty_ephemeral();
8690 eph.classification = Some(classification);
8691 let lowered: ProcessSpec = eph.clone().into();
8692 for query in DataClassification::ALL {
8693 assert_eq!(
8694 eph.has_data_classification(query),
8695 lowered.classification.has_data_classification(query),
8696 "authored classification.data_classification={populated:?}: parity drift on query {query:?}",
8697 );
8698 }
8699 }
8700 }
8701
8702 // ── EphemeralSpec::has_horizon_kind pins ─────────────────────────
8703 //
8704 // Fail-before-pass-after granularity: [`Self::has_horizon_kind`]
8705 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
8706 // went through `.resolved_classification().horizon.kind == kind`
8707 // or through the lowered `ProcessSpec`'s
8708 // `spec.classification.has_horizon_kind`. Post-lift the FIFTH
8709 // classification-axis peer on the ephemeral sugar surface routes
8710 // through the SAME [`Self::resolved_classification`] resolver +
8711 // the sibling closed-set primitive
8712 // [`crate::classification::Classification::has_horizon_kind`], so
8713 // a regression that dropped the resolver hop, inverted the
8714 // `Some`/`None` fill-through, or wired the closure to a fixed
8715 // unrelated slot fails HERE. OPENS a fresh (Option-parent ×
8716 // NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
8717 // corner on the ephemeral surface — distinct from the four prior
8718 // scalar-carrier peers on the (Option-parent × NON-DEFAULT-scalar-
8719 // child) and (Option-parent × DEFAULTED-scalar-child) corners, all
8720 // of which reach a discriminator DIRECTLY off a scalar
8721 // [`Classification`] slot. Both the parent Option's fill-through
8722 // baseline (`default_ephemeral_class`, which fills
8723 // `horizon: Horizon::default()`) AND the child's own `#[default]`
8724 // land on the SAME variant ([`HorizonKind::Bounded`]) — a two-
8725 // defaults composition property the three pins below all
8726 // exercise.
8727
8728 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8729 /// [`EphemeralSpec::classification`] slot names a concrete
8730 /// [`Classification`] returns `true` from
8731 /// [`Self::has_horizon_kind`] on the authored [`HorizonKind`] slot
8732 /// and `false` for every other variant. Sweep the
8733 /// [`HorizonKind::ALL`] × ALL cross so a regression that hard-
8734 /// coded the arm to a single kind or wired the closure to a
8735 /// fixed unrelated slot (e.g. reading `self.classification` as if
8736 /// it were a scalar rather than routing through
8737 /// `resolved_classification().horizon.kind`) fails HERE at the
8738 /// substrate primitive. Byte-for-byte peer of the point-surface
8739 /// [`Classification::has_horizon_kind`] populated-slot sweep on
8740 /// the SAME closed-set primitive.
8741 #[test]
8742 fn has_horizon_kind_returns_true_iff_authored_classification_matches_per_kind() {
8743 for populated in HorizonKind::ALL {
8744 let classification = Classification::gate_compute_with_axis(populated);
8745 let mut spec = empty_ephemeral();
8746 spec.classification = Some(classification);
8747 for query in HorizonKind::ALL {
8748 let expected = query == populated;
8749 assert_eq!(
8750 spec.has_horizon_kind(query),
8751 expected,
8752 "ephemeral classification.horizon.kind={populated:?}: query {query:?} drifted",
8753 );
8754 }
8755 }
8756 }
8757
8758 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8759 /// [`EphemeralSpec::classification`] slot is `None` returns
8760 /// `true` from [`Self::has_horizon_kind`] on
8761 /// [`HorizonKind::Bounded`] (the `default_ephemeral_class`
8762 /// baseline's `horizon.kind` axis AND the [`HorizonKind`] child's
8763 /// own `#[default]` variant) and `false` on every other variant.
8764 /// Pins the fresh (Option-parent × NESTED-STRUCT-scalar-child ×
8765 /// operator-resolvable-baseline) corner's default-arm short-
8766 /// circuit on the FIFTH classification-axis peer. Two-defaults
8767 /// composition property through a NESTED-STRUCT hop: both the
8768 /// parent Option's fill-through baseline
8769 /// (`default_ephemeral_class` fills `horizon: Horizon::default()`)
8770 /// AND the child's own `#[default]` (`HorizonKind::Bounded` via
8771 /// `#[default]` on the closed set) land on the SAME variant, so
8772 /// the ephemeral sugar surface's `horizon-Bounded` require-tag
8773 /// reads `true` on every operator-authored spec that omits both
8774 /// the `:classification` slot AND the `:horizon` sub-slot,
8775 /// pinning the workspace's bounded-by-default lifetime posture.
8776 #[test]
8777 fn has_horizon_kind_probes_bounded_only_on_absent_classification() {
8778 let spec = empty_ephemeral();
8779 assert!(spec.classification.is_none());
8780 for kind in HorizonKind::ALL {
8781 let expected = kind == HorizonKind::Bounded;
8782 assert_eq!(
8783 spec.has_horizon_kind(kind),
8784 expected,
8785 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8786 );
8787 }
8788 }
8789
8790 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8791 /// identically through [`Self::has_horizon_kind`] AND through
8792 /// `<eph.clone().into::<ProcessSpec>>()`
8793 /// `.classification.has_horizon_kind(kind)` on the mechanically-
8794 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8795 /// classification on every [`HorizonKind::ALL`] variant) × ALL
8796 /// queries so a future regression on either side of the resolver
8797 /// (a shift in the ephemeral resolver's default, a shift in the
8798 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8799 /// the parity boundary. Byte-for-byte peer of the sibling
8800 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
8801 /// [`Self::has_calm`] + [`Self::has_data_classification`] two-
8802 /// surface parity pins on the SAME `Cow`-resolver carrier — the
8803 /// FIFTH classification-axis two-surface parity contract on the
8804 /// ephemeral surface, and the FIRST on the (Option-parent ×
8805 /// NESTED-STRUCT-scalar-child) corner.
8806 #[test]
8807 fn has_horizon_kind_matches_point_peer_through_lowered_classification() {
8808 // Absent classification: both surfaces resolve through the SAME
8809 // default and agree on every variant.
8810 let eph = empty_ephemeral();
8811 let lowered: ProcessSpec = eph.clone().into();
8812 for query in HorizonKind::ALL {
8813 assert_eq!(
8814 eph.has_horizon_kind(query),
8815 lowered.classification.has_horizon_kind(query),
8816 "None-classification parity drift on query {query:?}",
8817 );
8818 }
8819 // Authored classification: both surfaces read the same authored
8820 // value verbatim.
8821 for populated in HorizonKind::ALL {
8822 let classification = Classification::gate_compute_with_axis(populated);
8823 let mut eph = empty_ephemeral();
8824 eph.classification = Some(classification);
8825 let lowered: ProcessSpec = eph.clone().into();
8826 for query in HorizonKind::ALL {
8827 assert_eq!(
8828 eph.has_horizon_kind(query),
8829 lowered.classification.has_horizon_kind(query),
8830 "authored classification.horizon.kind={populated:?}: parity drift on query {query:?}",
8831 );
8832 }
8833 }
8834 }
8835
8836 // ── EphemeralSpec::has_optimization_direction pins ───────────────
8837 //
8838 // Fail-before-pass-after granularity:
8839 // [`Self::has_optimization_direction`] did not exist pre-lift on
8840 // `impl EphemeralSpec` — every callsite went through
8841 // `.resolved_classification().horizon.direction.unwrap_or_default() == kind`
8842 // or through the lowered `ProcessSpec`'s
8843 // `spec.classification.has_optimization_direction`. Post-lift the
8844 // SIXTH classification-axis peer on the ephemeral sugar surface
8845 // routes through the SAME [`Self::resolved_classification`]
8846 // resolver + the sibling closed-set primitive
8847 // [`crate::classification::Classification::has_optimization_direction`],
8848 // so a regression that dropped the resolver hop, inverted the
8849 // `Some`/`None` fill-through, wired the closure to a fixed
8850 // unrelated slot, or flipped [`OptimizationDirection`]'s
8851 // `#[default]` off `Minimize` fails HERE. SECOND occupant on the
8852 // (Option-parent × NESTED-STRUCT-scalar-child × operator-
8853 // resolvable-baseline) corner alongside
8854 // [`Self::has_horizon_kind`] — pinning the corner as a proven-
8855 // repeatable primitive shape on the ephemeral surface with a
8856 // second nested-struct-child probe, and DEMONSTRATING that the
8857 // corner admits both direct-scalar and Option-scalar traversals
8858 // through the SAME nested [`Horizon`] intermediary via the closed
8859 // set's `Default` on the inner `Option<OptimizationDirection>`
8860 // slot.
8861
8862 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8863 /// [`EphemeralSpec::classification`] slot names a concrete
8864 /// [`Classification`] whose [`crate::classification::Horizon::direction`]
8865 /// slot carries `Some(<direction>)` returns `true` from
8866 /// [`Self::has_optimization_direction`] on the authored
8867 /// [`OptimizationDirection`] variant and `false` for every other
8868 /// variant. Sweep the [`OptimizationDirection::ALL`] × ALL cross
8869 /// so a regression that hard-coded the arm to a single kind, or
8870 /// dropped the `Option::unwrap_or_default` collapse, or wired the
8871 /// closure to a fixed unrelated slot (e.g. reading `self.horizon.kind`)
8872 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
8873 /// point-surface
8874 /// [`Classification::has_optimization_direction`] populated-slot
8875 /// sweep on the SAME closed-set primitive.
8876 #[test]
8877 fn has_optimization_direction_returns_true_iff_authored_direction_matches_per_kind() {
8878 for populated in OptimizationDirection::ALL {
8879 let classification = Classification::gate_compute_with_axis(populated);
8880 let mut spec = empty_ephemeral();
8881 spec.classification = Some(classification);
8882 for query in OptimizationDirection::ALL {
8883 let expected = query == populated;
8884 assert_eq!(
8885 spec.has_optimization_direction(query),
8886 expected,
8887 "ephemeral classification.horizon.direction=Some({populated:?}): query {query:?} drifted",
8888 );
8889 }
8890 }
8891 }
8892
8893 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8894 /// [`EphemeralSpec::classification`] slot is `None` returns
8895 /// `true` from [`Self::has_optimization_direction`] on
8896 /// [`OptimizationDirection::Minimize`] (the `default_ephemeral_class`
8897 /// baseline fills `horizon: Horizon::default()`, which in turn
8898 /// leaves `direction: None`, and the substrate's
8899 /// `Option::unwrap_or_default` collapse then reads
8900 /// [`OptimizationDirection::Minimize`] via the closed set's
8901 /// `#[default]`) and `false` on every other variant. Pins the
8902 /// (Option-parent × NESTED-STRUCT-scalar-child × operator-
8903 /// resolvable-baseline) corner's default-arm short-circuit on the
8904 /// SIXTH classification-axis peer through TWO Option-hops: parent
8905 /// `EphemeralSpec::classification` and inner `Horizon::direction`
8906 /// both `None`, both collapsing to the closed set's `#[default]`
8907 /// [`OptimizationDirection::Minimize`]. A regression that promoted
8908 /// [`OptimizationDirection::Maximize`] to `#[default]` (silently
8909 /// inverting every unadorned Process's rate-window evaluator
8910 /// polarity), dropped `Option::unwrap_or_default`, or wired the arm
8911 /// to a fixed variant answer fails HERE.
8912 #[test]
8913 fn has_optimization_direction_probes_minimize_only_on_absent_classification() {
8914 let spec = empty_ephemeral();
8915 assert!(spec.classification.is_none());
8916 for kind in OptimizationDirection::ALL {
8917 let expected = kind == OptimizationDirection::Minimize;
8918 assert_eq!(
8919 spec.has_optimization_direction(kind),
8920 expected,
8921 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8922 );
8923 }
8924 }
8925
8926 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8927 /// identically through [`Self::has_optimization_direction`] AND
8928 /// through
8929 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
8930 /// on the mechanically-lowered `ProcessSpec`. Sweeps three arms —
8931 /// (`None` classification), (`Some(_)` classification with
8932 /// `direction: None`), and (`Some(_)` classification on every
8933 /// [`OptimizationDirection::ALL`] variant) — × ALL queries so a
8934 /// future regression on either side of the resolver (an ephemeral-
8935 /// side fill-through drift, a lowering-side `From<EphemeralSpec>`
8936 /// `unwrap_or_else(default_ephemeral_class)` drift, an inner
8937 /// `Option::unwrap_or_default` collapse drift on either side)
8938 /// fails HERE at the parity boundary. Byte-for-byte peer of the
8939 /// sibling [`Self::has_point_type`] + [`Self::has_substrate`] +
8940 /// [`Self::has_calm`] + [`Self::has_data_classification`] +
8941 /// [`Self::has_horizon_kind`] two-surface parity pins on the SAME
8942 /// `Cow`-resolver carrier — the SIXTH classification-axis two-
8943 /// surface parity contract on the ephemeral surface, and the
8944 /// SECOND on the (Option-parent × NESTED-STRUCT-scalar-child)
8945 /// corner.
8946 #[test]
8947 fn has_optimization_direction_matches_point_peer_through_lowered_classification() {
8948 // Absent classification: both surfaces resolve through the SAME
8949 // default and agree on every variant.
8950 let eph = empty_ephemeral();
8951 let lowered: ProcessSpec = eph.clone().into();
8952 for query in OptimizationDirection::ALL {
8953 assert_eq!(
8954 eph.has_optimization_direction(query),
8955 lowered.classification.has_optimization_direction(query),
8956 "None-classification parity drift on query {query:?}",
8957 );
8958 }
8959 // Authored classification with `direction: None` — the inner
8960 // Option collapses through `unwrap_or_default` on both sides,
8961 // reading `Minimize`.
8962 let mut classification = Classification::gate_compute();
8963 classification.horizon = Horizon::default();
8964 let mut eph = empty_ephemeral();
8965 eph.classification = Some(classification);
8966 let lowered: ProcessSpec = eph.clone().into();
8967 for query in OptimizationDirection::ALL {
8968 assert_eq!(
8969 eph.has_optimization_direction(query),
8970 lowered.classification.has_optimization_direction(query),
8971 "authored classification with horizon.direction=None: parity drift on query {query:?}",
8972 );
8973 }
8974 // Authored classification with `direction: Some(_)` — both
8975 // surfaces read the same authored value verbatim.
8976 for populated in OptimizationDirection::ALL {
8977 let classification = Classification::gate_compute_with_axis(populated);
8978 let mut eph = empty_ephemeral();
8979 eph.classification = Some(classification);
8980 let lowered: ProcessSpec = eph.clone().into();
8981 for query in OptimizationDirection::ALL {
8982 assert_eq!(
8983 eph.has_optimization_direction(query),
8984 lowered.classification.has_optimization_direction(query),
8985 "authored classification.horizon.direction=Some({populated:?}): parity drift on query {query:?}",
8986 );
8987 }
8988 }
8989 }
8990
8991 // ── EphemeralSpec::has_input_arity pins ──────────────────────────
8992 //
8993 // Fail-before-pass-after granularity: [`Self::has_input_arity`] did
8994 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8995 // through `.resolved_classification().point_type.input_arity() ==
8996 // kind` or through the lowered `ProcessSpec`'s
8997 // `spec.classification.has_input_arity`. Post-lift the SEVENTH
8998 // classification-axis peer on the ephemeral sugar surface routes
8999 // through the SAME [`Self::resolved_classification`] resolver + the
9000 // sibling closed-set primitive
9001 // [`crate::classification::Classification::has_input_arity`], so a
9002 // regression that dropped the resolver hop, dropped the
9003 // `.input_arity()` projection call, inverted the projection (`One
9004 // ↔ Many`), or crossed the wires with the sibling
9005 // [`ConvergencePointType::output_arity`] projection fails HERE.
9006 // OPENS the (Option-parent × NESTED-STRUCT-scalar-child ×
9007 // derived-typed-projection) corner on the ephemeral surface —
9008 // distinct from the two prior nested-scalar peers on the corner
9009 // (`has_horizon_kind` reads `horizon.kind` directly;
9010 // `has_optimization_direction` reads `horizon.direction` through an
9011 // Option collapse), both of which reach a discriminator DIRECTLY off
9012 // a scalar. This peer instead threads through a many-to-one closed-
9013 // set typed projection so the child's closed set is REACHED THROUGH
9014 // a projection layer, pinning the corner as admitting three
9015 // ephemeral-surface traversal shapes (direct-scalar, Option-scalar-
9016 // with-default, derived-typed-projection) through the SAME resolver
9017 // walk.
9018
9019 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
9020 /// [`EphemeralSpec::classification`] slot names a concrete
9021 /// [`Classification`] with an authored [`ConvergencePointType`]
9022 /// returns `true` from [`Self::has_input_arity`] on the [`Arity`]
9023 /// value the projection [`ConvergencePointType::input_arity`] maps
9024 /// the authored point-type to and `false` for every other variant.
9025 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
9026 /// a regression that (a) dropped the projection call, (b) inverted
9027 /// the projection, (c) probed [`ConvergencePointType`] directly, or
9028 /// (d) crossed wires with [`ConvergencePointType::output_arity`]
9029 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9030 /// point-surface [`Classification::has_input_arity`] populated-slot
9031 /// sweep on the SAME closed-set primitive routed through the SAME
9032 /// projection.
9033 #[test]
9034 fn has_input_arity_returns_true_iff_authored_point_type_projects_per_kind() {
9035 for populated in ConvergencePointType::ALL {
9036 let mut classification = Classification::gate_compute();
9037 classification.point_type = populated;
9038 let mut spec = empty_ephemeral();
9039 spec.classification = Some(classification);
9040 let projected = populated.input_arity();
9041 for query in Arity::ALL {
9042 let expected = query == projected;
9043 assert_eq!(
9044 spec.has_input_arity(query),
9045 expected,
9046 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
9047 );
9048 }
9049 }
9050 }
9051
9052 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
9053 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
9054 /// from [`Self::has_input_arity`] on [`Arity::Many`] (the
9055 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
9056 /// and [`ConvergencePointType::input_arity`] projects
9057 /// `Gate → Arity::Many`) and `false` on [`Arity::One`]. Pins the
9058 /// (Option-parent × NESTED-STRUCT-scalar-child × derived-typed-
9059 /// projection) corner's baseline projection on the SEVENTH
9060 /// classification-axis peer through a chain of TWO fill-throughs
9061 /// composed with ONE projection: the parent Option's
9062 /// `unwrap_or_else(default_ephemeral_class)` picks the substrate
9063 /// baseline, and the projection then collapses the baseline's
9064 /// point-type through the closed-set-driven many-to-one bucket
9065 /// walk. [`Arity`] carries no `#[default]`, so there is NO default-
9066 /// arm short-circuit shortcut here — the answer flows entirely
9067 /// through the projection's bucket-membership decision. A
9068 /// regression that promoted the baseline's `point_type` off `Gate`
9069 /// (silently flipping every unadorned Process's convergent-by-
9070 /// default input-side posture to endomorphic or diffusive), dropped
9071 /// the projection call, inverted the projection, or crossed wires
9072 /// with [`ConvergencePointType::output_arity`] (which would flip
9073 /// the baseline answer from `Many` to `One` for `Gate`) fails HERE.
9074 #[test]
9075 fn has_input_arity_probes_many_only_on_absent_classification() {
9076 let spec = empty_ephemeral();
9077 assert!(spec.classification.is_none());
9078 for kind in Arity::ALL {
9079 let expected = kind == Arity::Many;
9080 assert_eq!(
9081 spec.has_input_arity(kind),
9082 expected,
9083 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many): query {kind:?} must be {expected}",
9084 );
9085 }
9086 }
9087
9088 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9089 /// identically through [`Self::has_input_arity`] AND through
9090 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
9091 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9092 /// classification, `Some(_)` classification on every
9093 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
9094 /// so a future regression on either side of the resolver (a shift
9095 /// in the ephemeral resolver's default, a shift in the
9096 /// `From<EphemeralSpec>` lowering's fill-through, a projection
9097 /// drift on either side) fails HERE at the parity boundary. Byte-
9098 /// for-byte peer of the sibling [`Self::has_point_type`] +
9099 /// [`Self::has_substrate`] + [`Self::has_calm`] +
9100 /// [`Self::has_data_classification`] + [`Self::has_horizon_kind`] +
9101 /// [`Self::has_optimization_direction`] two-surface parity pins on
9102 /// the SAME `Cow`-resolver carrier — the SEVENTH classification-
9103 /// axis two-surface parity contract on the ephemeral surface, and
9104 /// the FIRST on the (Option-parent × NESTED-STRUCT-scalar-child ×
9105 /// derived-typed-projection) corner.
9106 #[test]
9107 fn has_input_arity_matches_point_peer_through_lowered_classification() {
9108 // Absent classification: both surfaces resolve through the SAME
9109 // default and agree on every variant.
9110 let eph = empty_ephemeral();
9111 let lowered: ProcessSpec = eph.clone().into();
9112 for query in Arity::ALL {
9113 assert_eq!(
9114 eph.has_input_arity(query),
9115 lowered.classification.has_input_arity(query),
9116 "None-classification parity drift on query {query:?}",
9117 );
9118 }
9119 // Authored classification: both surfaces read the same authored
9120 // point_type and route through the same projection.
9121 for populated in ConvergencePointType::ALL {
9122 let mut classification = Classification::gate_compute();
9123 classification.point_type = populated;
9124 let mut eph = empty_ephemeral();
9125 eph.classification = Some(classification);
9126 let lowered: ProcessSpec = eph.clone().into();
9127 for query in Arity::ALL {
9128 assert_eq!(
9129 eph.has_input_arity(query),
9130 lowered.classification.has_input_arity(query),
9131 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
9132 );
9133 }
9134 }
9135 }
9136
9137 // ── EphemeralSpec::has_output_arity pins ─────────────────────────
9138 //
9139 // Fail-before-pass-after granularity: [`Self::has_output_arity`] did
9140 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
9141 // through `.resolved_classification().point_type.output_arity() ==
9142 // kind` or through the lowered `ProcessSpec`'s
9143 // `spec.classification.has_output_arity`. Post-lift the EIGHTH
9144 // classification-axis peer on the ephemeral sugar surface routes
9145 // through the SAME [`Self::resolved_classification`] resolver + the
9146 // sibling closed-set primitive
9147 // [`crate::classification::Classification::has_output_arity`], so a
9148 // regression that dropped the resolver hop, dropped the
9149 // `.output_arity()` projection call, inverted the projection (`One
9150 // ↔ Many`), or crossed the wires with the sibling
9151 // [`ConvergencePointType::input_arity`] projection fails HERE.
9152 // CLOSES the (Option-parent × NESTED-STRUCT-scalar-child ×
9153 // derived-typed-projection) corner on the ephemeral surface as the
9154 // SECOND occupant — co-tenant with [`Self::has_input_arity`] on the
9155 // SAME `point_type` scalar carrier through the SAME [`Arity`] closed
9156 // set but through the sibling many-to-one projection, closing the
9157 // DAG-composition arity pair on the ephemeral side.
9158
9159 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
9160 /// [`EphemeralSpec::classification`] slot names a concrete
9161 /// [`Classification`] with an authored [`ConvergencePointType`]
9162 /// returns `true` from [`Self::has_output_arity`] on the [`Arity`]
9163 /// value the projection [`ConvergencePointType::output_arity`] maps
9164 /// the authored point-type to and `false` for every other variant.
9165 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
9166 /// a regression that (a) dropped the projection call, (b) inverted
9167 /// the projection, (c) probed [`ConvergencePointType`] directly, or
9168 /// (d) crossed wires with [`ConvergencePointType::input_arity`]
9169 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9170 /// point-surface [`Classification::has_output_arity`] populated-slot
9171 /// sweep on the SAME closed-set primitive routed through the SAME
9172 /// projection.
9173 #[test]
9174 fn has_output_arity_returns_true_iff_authored_point_type_projects_per_kind() {
9175 for populated in ConvergencePointType::ALL {
9176 let mut classification = Classification::gate_compute();
9177 classification.point_type = populated;
9178 let mut spec = empty_ephemeral();
9179 spec.classification = Some(classification);
9180 let projected = populated.output_arity();
9181 for query in Arity::ALL {
9182 let expected = query == projected;
9183 assert_eq!(
9184 spec.has_output_arity(query),
9185 expected,
9186 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
9187 );
9188 }
9189 }
9190 }
9191
9192 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
9193 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
9194 /// from [`Self::has_output_arity`] on [`Arity::One`] (the
9195 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
9196 /// and [`ConvergencePointType::output_arity`] projects
9197 /// `Gate → Arity::One`) and `false` on [`Arity::Many`]. MIRROR of
9198 /// the [`Self::has_input_arity`] baseline (`Gate → input_arity =
9199 /// Many`) — the DAG-composition arity pair projects the same `Gate`
9200 /// baseline through the two projections to opposite [`Arity`] arms,
9201 /// so this pin locks the output-side half of that pair against a
9202 /// regression that (a) promoted the baseline's `point_type` off
9203 /// `Gate` (silently flipping every unadorned Process's convergent-
9204 /// by-default output-side posture to diffusive), (b) dropped the
9205 /// projection call, (c) inverted the projection, or (d) crossed
9206 /// wires with [`ConvergencePointType::input_arity`] (which would
9207 /// flip the baseline answer from `One` to `Many` for `Gate`).
9208 #[test]
9209 fn has_output_arity_probes_one_only_on_absent_classification() {
9210 let spec = empty_ephemeral();
9211 assert!(spec.classification.is_none());
9212 for kind in Arity::ALL {
9213 let expected = kind == Arity::One;
9214 assert_eq!(
9215 spec.has_output_arity(kind),
9216 expected,
9217 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One): query {kind:?} must be {expected}",
9218 );
9219 }
9220 }
9221
9222 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9223 /// identically through [`Self::has_output_arity`] AND through
9224 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
9225 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9226 /// classification, `Some(_)` classification on every
9227 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
9228 /// so a future regression on either side of the resolver fails HERE
9229 /// at the parity boundary. Byte-for-byte peer of the seven sibling
9230 /// two-surface parity pins on the SAME `Cow`-resolver carrier — the
9231 /// EIGHTH classification-axis two-surface parity contract on the
9232 /// ephemeral surface, closing the SECOND occupant of the (Option-
9233 /// parent × NESTED-STRUCT-scalar-child × derived-typed-projection)
9234 /// corner.
9235 #[test]
9236 fn has_output_arity_matches_point_peer_through_lowered_classification() {
9237 // Absent classification: both surfaces resolve through the SAME
9238 // default and agree on every variant.
9239 let eph = empty_ephemeral();
9240 let lowered: ProcessSpec = eph.clone().into();
9241 for query in Arity::ALL {
9242 assert_eq!(
9243 eph.has_output_arity(query),
9244 lowered.classification.has_output_arity(query),
9245 "None-classification parity drift on query {query:?}",
9246 );
9247 }
9248 // Authored classification: both surfaces read the same authored
9249 // point_type and route through the same projection.
9250 for populated in ConvergencePointType::ALL {
9251 let mut classification = Classification::gate_compute();
9252 classification.point_type = populated;
9253 let mut eph = empty_ephemeral();
9254 eph.classification = Some(classification);
9255 let lowered: ProcessSpec = eph.clone().into();
9256 for query in Arity::ALL {
9257 assert_eq!(
9258 eph.has_output_arity(query),
9259 lowered.classification.has_output_arity(query),
9260 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
9261 );
9262 }
9263 }
9264 }
9265
9266 /// DAG-COMPOSITION ARITY-PAIR pin — the SEVENTH
9267 /// ([`Self::has_input_arity`]) and EIGHTH
9268 /// ([`Self::has_output_arity`]) classification-axis peers on the
9269 /// ephemeral surface walk the SAME `point_type` scalar carrier
9270 /// (routed through the SAME [`Self::resolved_classification`]
9271 /// resolver) through the SAME [`Arity`] closed set but through
9272 /// DIFFERENT typed projections
9273 /// ([`ConvergencePointType::input_arity`] vs.
9274 /// [`ConvergencePointType::output_arity`]). An [`EphemeralSpec`]
9275 /// with `classification.point_type = Fork` (the diffusive `(One,
9276 /// Many)` cell) MUST simultaneously answer `has_input_arity(One)`
9277 /// true AND `has_output_arity(Many)` true AND
9278 /// `has_input_arity(Many)` false AND `has_output_arity(One)` false.
9279 /// An [`EphemeralSpec`] with `point_type = Transform` (endomorphic
9280 /// `(One, One)`) MUST answer BOTH `has_input_arity(One)` and
9281 /// `has_output_arity(One)` true — the two projections AGREE in the
9282 /// endomorphic bucket. The absent-classification baseline (Gate,
9283 /// convergent `(Many, One)`) MUST answer
9284 /// `has_input_arity(Many)` true AND `has_output_arity(One)` true —
9285 /// the mirror of the Fork case. A regression that (a) collapsed
9286 /// `has_output_arity` onto `has_input_arity`, (b) swapped the
9287 /// projection direction, or (c) drifted the topology-bucket
9288 /// contract fails HERE at ONE narrow ephemeral-surface site,
9289 /// symmetric with the point-surface DAG-composition arity-pair pin.
9290 #[test]
9291 fn has_input_arity_and_has_output_arity_pin_dag_composition_pair() {
9292 // Diffusive cell: Fork carries (input, output) = (One, Many)
9293 let mut classification = Classification::gate_compute();
9294 classification.point_type = ConvergencePointType::Fork;
9295 let mut fork = empty_ephemeral();
9296 fork.classification = Some(classification);
9297 assert!(fork.has_input_arity(Arity::One));
9298 assert!(fork.has_output_arity(Arity::Many));
9299 assert!(!fork.has_input_arity(Arity::Many));
9300 assert!(!fork.has_output_arity(Arity::One));
9301
9302 // Endomorphic cell: Transform carries (input, output) = (One, One)
9303 let mut classification = Classification::gate_compute();
9304 classification.point_type = ConvergencePointType::Transform;
9305 let mut transform = empty_ephemeral();
9306 transform.classification = Some(classification);
9307 assert!(transform.has_input_arity(Arity::One));
9308 assert!(transform.has_output_arity(Arity::One));
9309 assert!(!transform.has_input_arity(Arity::Many));
9310 assert!(!transform.has_output_arity(Arity::Many));
9311
9312 // Convergent cell: absent classification defaults to Gate,
9313 // which carries (input, output) = (Many, One).
9314 let gate = empty_ephemeral();
9315 assert!(gate.classification.is_none());
9316 assert!(gate.has_input_arity(Arity::Many));
9317 assert!(gate.has_output_arity(Arity::One));
9318 assert!(!gate.has_input_arity(Arity::One));
9319 assert!(!gate.has_output_arity(Arity::Many));
9320 }
9321
9322 // ── EphemeralSpec::horizon_terminates pins ───────────────────────
9323 //
9324 // Fail-before-pass-after granularity: `horizon_terminates` did not
9325 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9326 // the "does this ephemeral spec's horizon terminate?" question
9327 // went through `.resolved_classification().horizon.kind.terminates()`
9328 // or through the lowered `ProcessSpec`'s
9329 // `spec.classification.horizon.kind.terminates()`. Post-lift the
9330 // NINTH classification-axis peer on the ephemeral surface routes
9331 // through the SAME [`Self::resolved_classification`] resolver +
9332 // the sibling substrate primitive
9333 // [`crate::classification::Classification::horizon_terminates`],
9334 // so the two-surface parity contract holds by construction — a
9335 // regression on either side of the resolver fails at these pins
9336 // before landing at the operator-facing `terminating-horizon`
9337 // fixed tag in `tatara-check`.
9338
9339 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9340 /// [`Classification`] carries a specific [`HorizonKind`] variant
9341 /// answers [`Self::horizon_terminates`] matching the closed
9342 /// set's own [`HorizonKind::terminates`] truth table. Sweep
9343 /// [`HorizonKind::ALL`] so a regression that (a) hard-coded the
9344 /// body to a fixed answer, (b) inverted the projection, or (c)
9345 /// crossed the wires with the antisymmetric partner
9346 /// [`HorizonKind::requires_metric_axes`] fails HERE at the
9347 /// substrate primitive before drifting through the
9348 /// `terminating-horizon` fixed tag or the peer point surface.
9349 #[test]
9350 fn horizon_terminates_returns_horizon_kind_projection_per_kind() {
9351 for populated in HorizonKind::ALL {
9352 let classification = Classification::gate_compute_with_axis(populated);
9353 let mut spec = empty_ephemeral();
9354 spec.classification = Some(classification);
9355 assert_eq!(
9356 spec.horizon_terminates(),
9357 populated.terminates(),
9358 "authored horizon.kind={populated:?}: horizon_terminates() drift",
9359 );
9360 }
9361 }
9362
9363 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9364 /// with `classification: None` routes through the
9365 /// [`Self::resolved_classification`] resolver's substrate default
9366 /// [`Classification::gate_compute`], which uses
9367 /// [`crate::classification::Horizon::default`] whose `kind`
9368 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
9369 /// [`HorizonKind::Bounded::terminates`] projects `true`, so
9370 /// [`Self::horizon_terminates`] returns `true`. Pins the default-
9371 /// arm short-circuit through THREE layers of `Default`
9372 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
9373 /// [`HorizonKind::default`]) reaching this derived-nullary
9374 /// predicate — a regression that dropped the resolver hop
9375 /// (silently answering `false` on an absent classification, as
9376 /// if the operator's absence meant "no horizon at all") fails
9377 /// HERE at ONE narrow ephemeral-surface site.
9378 #[test]
9379 fn horizon_terminates_probes_true_on_absent_classification() {
9380 let spec = empty_ephemeral();
9381 assert!(spec.classification.is_none());
9382 assert!(
9383 spec.horizon_terminates(),
9384 "absent classification (defaults to gate_compute, horizon.kind=Bounded → terminates=true)",
9385 );
9386 }
9387
9388 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9389 /// identically through [`Self::horizon_terminates`] AND through
9390 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_terminates()`
9391 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9392 /// classification, `Some(_)` classification on every
9393 /// [`HorizonKind::ALL`] variant) so a future regression on
9394 /// either side of the resolver fails HERE at the parity
9395 /// boundary. Byte-for-byte peer of the eight sibling two-surface
9396 /// parity pins on the SAME `Cow`-resolver carrier — the NINTH
9397 /// classification-axis two-surface parity contract on the
9398 /// ephemeral surface, and the FIRST via a derived-nullary-
9399 /// boolean predicate rather than a variant-equality probe.
9400 #[test]
9401 fn horizon_terminates_matches_point_peer_through_lowered_classification() {
9402 // Absent classification: both surfaces resolve through the SAME
9403 // default and agree.
9404 let eph = empty_ephemeral();
9405 let lowered: ProcessSpec = eph.clone().into();
9406 assert_eq!(
9407 eph.horizon_terminates(),
9408 lowered.classification.horizon_terminates(),
9409 "None-classification parity drift",
9410 );
9411 // Authored classification: both surfaces read the same authored
9412 // horizon.kind and route through the same projection.
9413 for populated in HorizonKind::ALL {
9414 let classification = Classification::gate_compute_with_axis(populated);
9415 let mut eph = empty_ephemeral();
9416 eph.classification = Some(classification);
9417 let lowered: ProcessSpec = eph.clone().into();
9418 assert_eq!(
9419 eph.horizon_terminates(),
9420 lowered.classification.horizon_terminates(),
9421 "authored horizon.kind={populated:?}: parity drift",
9422 );
9423 }
9424 }
9425
9426 // ── EphemeralSpec::horizon_requires_metric_axes pins ─────────────
9427 //
9428 // Fail-before-pass-after granularity: `horizon_requires_metric_axes`
9429 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9430 // walking the "does this ephemeral spec's horizon require metric
9431 // axes?" question went through
9432 // `.resolved_classification().horizon.kind.requires_metric_axes()`
9433 // or through the lowered `ProcessSpec`'s
9434 // `spec.classification.horizon.kind.requires_metric_axes()`. Post-
9435 // lift the antisymmetric peer of `horizon_terminates` routes
9436 // through the SAME [`Self::resolved_classification`] resolver +
9437 // the sibling substrate primitive
9438 // [`crate::classification::Classification::horizon_requires_metric_axes`],
9439 // so the two-surface parity contract holds by construction — a
9440 // regression on either side of the resolver fails at these pins
9441 // before landing at the operator-facing `metric-axes-required`
9442 // fixed tag in `tatara-check`.
9443
9444 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9445 /// [`Classification`] carries a specific [`HorizonKind`] variant
9446 /// answers [`Self::horizon_requires_metric_axes`] matching the
9447 /// closed set's own [`HorizonKind::requires_metric_axes`] truth
9448 /// table. Sweep [`HorizonKind::ALL`] so a regression that (a)
9449 /// hard-coded the body to a fixed answer, (b) inverted the
9450 /// projection, or (c) crossed the wires with the antisymmetric
9451 /// partner [`HorizonKind::terminates`] fails HERE at the
9452 /// substrate primitive before drifting through the
9453 /// `metric-axes-required` fixed tag or the peer point surface.
9454 #[test]
9455 fn horizon_requires_metric_axes_returns_horizon_kind_projection_per_kind() {
9456 for populated in HorizonKind::ALL {
9457 let classification = Classification::gate_compute_with_axis(populated);
9458 let mut spec = empty_ephemeral();
9459 spec.classification = Some(classification);
9460 assert_eq!(
9461 spec.horizon_requires_metric_axes(),
9462 populated.requires_metric_axes(),
9463 "authored horizon.kind={populated:?}: horizon_requires_metric_axes() drift",
9464 );
9465 }
9466 }
9467
9468 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9469 /// with `classification: None` routes through the
9470 /// [`Self::resolved_classification`] resolver's substrate default
9471 /// [`Classification::gate_compute`], which uses
9472 /// [`crate::classification::Horizon::default`] whose `kind`
9473 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
9474 /// [`HorizonKind::Bounded::requires_metric_axes`] projects
9475 /// `false`, so [`Self::horizon_requires_metric_axes`] returns
9476 /// `false`. Pins the default-arm short-circuit through THREE
9477 /// layers of `Default` ([`Classification::gate_compute`] →
9478 /// [`Horizon::default`] → [`HorizonKind::default`]) reaching this
9479 /// derived-nullary predicate — mirror image of
9480 /// `horizon_terminates_probes_true_on_absent_classification`.
9481 #[test]
9482 fn horizon_requires_metric_axes_probes_false_on_absent_classification() {
9483 let spec = empty_ephemeral();
9484 assert!(spec.classification.is_none());
9485 assert!(
9486 !spec.horizon_requires_metric_axes(),
9487 "absent classification (defaults to gate_compute, horizon.kind=Bounded → requires_metric_axes=false)",
9488 );
9489 }
9490
9491 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9492 /// identically through [`Self::horizon_requires_metric_axes`]
9493 /// AND through
9494 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_requires_metric_axes()`
9495 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9496 /// classification, `Some(_)` classification on every
9497 /// [`HorizonKind::ALL`] variant) so a future regression on
9498 /// either side of the resolver fails HERE at the parity
9499 /// boundary. Byte-for-byte peer of the sibling
9500 /// `horizon_terminates_matches_point_peer_through_lowered_classification`.
9501 #[test]
9502 fn horizon_requires_metric_axes_matches_point_peer_through_lowered_classification() {
9503 // Absent classification.
9504 let eph = empty_ephemeral();
9505 let lowered: ProcessSpec = eph.clone().into();
9506 assert_eq!(
9507 eph.horizon_requires_metric_axes(),
9508 lowered.classification.horizon_requires_metric_axes(),
9509 "None-classification parity drift",
9510 );
9511 // Authored classification.
9512 for populated in HorizonKind::ALL {
9513 let classification = Classification::gate_compute_with_axis(populated);
9514 let mut eph = empty_ephemeral();
9515 eph.classification = Some(classification);
9516 let lowered: ProcessSpec = eph.clone().into();
9517 assert_eq!(
9518 eph.horizon_requires_metric_axes(),
9519 lowered.classification.horizon_requires_metric_axes(),
9520 "authored horizon.kind={populated:?}: parity drift",
9521 );
9522 }
9523 }
9524
9525 // ── EphemeralSpec::calm_requires_coordination pins ───────────────
9526 //
9527 // Fail-before-pass-after granularity: `calm_requires_coordination`
9528 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9529 // walking the "does this ephemeral spec require coordination?"
9530 // question went through
9531 // `.resolved_classification().calm.requires_coordination()` or
9532 // through the lowered `ProcessSpec`'s
9533 // `spec.classification.calm.requires_coordination()`. Post-lift the
9534 // THIRD derived-nullary-boolean peer on the ephemeral surface
9535 // (first on the calm axis, after the two horizon-axis peers)
9536 // routes through the SAME [`Self::resolved_classification`]
9537 // resolver + the sibling substrate primitive
9538 // [`crate::classification::Classification::calm_requires_coordination`],
9539 // so the two-surface parity contract holds by construction — a
9540 // regression on either side of the resolver fails at these pins
9541 // before landing at the operator-facing `coordination-required`
9542 // fixed tag in `tatara-check`.
9543
9544 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9545 /// [`Classification`] carries a specific [`CalmClassification`]
9546 /// variant answers [`Self::calm_requires_coordination`] matching
9547 /// the closed set's own
9548 /// [`CalmClassification::requires_coordination`] truth table.
9549 /// Sweep [`CalmClassification::ALL`] so a regression that (a)
9550 /// hard-coded the body to a fixed answer, (b) inverted the
9551 /// projection, or (c) crossed the wires with a sibling
9552 /// classification-axis probe fails HERE at the substrate primitive
9553 /// before drifting through the `coordination-required` fixed tag
9554 /// or the peer point surface.
9555 #[test]
9556 fn calm_requires_coordination_returns_calm_projection_per_kind() {
9557 for populated in CalmClassification::ALL {
9558 let mut classification = Classification::gate_compute();
9559 classification.calm = populated;
9560 let mut spec = empty_ephemeral();
9561 spec.classification = Some(classification);
9562 assert_eq!(
9563 spec.calm_requires_coordination(),
9564 populated.requires_coordination(),
9565 "authored calm={populated:?}: calm_requires_coordination() drift",
9566 );
9567 }
9568 }
9569
9570 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9571 /// with `classification: None` routes through the
9572 /// [`Self::resolved_classification`] resolver's substrate default
9573 /// [`Classification::gate_compute`], which carries
9574 /// [`CalmClassification::default = Monotone`], and
9575 /// [`CalmClassification::Monotone::requires_coordination`] projects
9576 /// `false`, so [`Self::calm_requires_coordination`] returns
9577 /// `false`. Pins the default-arm short-circuit through TWO layers
9578 /// of `Default` ([`Classification::gate_compute`] →
9579 /// [`CalmClassification::default`]) reaching this derived-nullary
9580 /// predicate — distinct from the sibling `horizon_*` absent-
9581 /// classification pins by ONE structural degree (those walk THREE
9582 /// layers of `Default` because horizon has a nested-struct wrapper;
9583 /// this walks TWO because `calm` is a direct scalar). A regression
9584 /// that dropped the resolver hop (silently answering `true` on an
9585 /// absent classification, as if the operator's absence meant
9586 /// "requires coordination") fails HERE at ONE narrow ephemeral-
9587 /// surface site.
9588 #[test]
9589 fn calm_requires_coordination_probes_false_on_absent_classification() {
9590 let spec = empty_ephemeral();
9591 assert!(spec.classification.is_none());
9592 assert!(
9593 !spec.calm_requires_coordination(),
9594 "absent classification (defaults to gate_compute, calm=Monotone → requires_coordination=false)",
9595 );
9596 }
9597
9598 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9599 /// identically through [`Self::calm_requires_coordination`] AND
9600 /// through
9601 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_requires_coordination()`
9602 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9603 /// classification, `Some(_)` classification on every
9604 /// [`CalmClassification::ALL`] variant) so a future regression on
9605 /// either side of the resolver fails HERE at the parity boundary.
9606 /// Byte-for-byte peer of the sibling
9607 /// `horizon_terminates_matches_point_peer_through_lowered_classification`
9608 /// on the calm axis.
9609 #[test]
9610 fn calm_requires_coordination_matches_point_peer_through_lowered_classification() {
9611 // Absent classification.
9612 let eph = empty_ephemeral();
9613 let lowered: ProcessSpec = eph.clone().into();
9614 assert_eq!(
9615 eph.calm_requires_coordination(),
9616 lowered.classification.calm_requires_coordination(),
9617 "None-classification parity drift",
9618 );
9619 // Authored classification.
9620 for populated in CalmClassification::ALL {
9621 let mut classification = Classification::gate_compute();
9622 classification.calm = populated;
9623 let mut eph = empty_ephemeral();
9624 eph.classification = Some(classification);
9625 let lowered: ProcessSpec = eph.clone().into();
9626 assert_eq!(
9627 eph.calm_requires_coordination(),
9628 lowered.classification.calm_requires_coordination(),
9629 "authored calm={populated:?}: parity drift",
9630 );
9631 }
9632 }
9633
9634 // ── EphemeralSpec::data_is_regulated pins ────────────────────────
9635 //
9636 // Fail-before-pass-after granularity: `data_is_regulated` did not
9637 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9638 // the "does this ephemeral spec carry regulated data?" question
9639 // went through
9640 // `.resolved_classification().data_classification.is_regulated()`
9641 // or through the lowered `ProcessSpec`'s
9642 // `spec.classification.data_classification.is_regulated()`. Post-
9643 // lift the FOURTH derived-nullary-boolean peer on the ephemeral
9644 // surface (first on the data axis, after two horizon-axis peers
9645 // and one calm-axis peer) routes through the SAME
9646 // [`Self::resolved_classification`] resolver + the sibling
9647 // substrate primitive
9648 // [`crate::classification::Classification::data_is_regulated`],
9649 // so the two-surface parity contract holds by construction — a
9650 // regression on either side of the resolver fails at these pins
9651 // before landing at the operator-facing `data-regulated` fixed
9652 // tag in `tatara-check`.
9653
9654 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9655 /// [`Classification`] carries a specific [`DataClassification`]
9656 /// variant answers [`Self::data_is_regulated`] matching the
9657 /// closed set's own [`DataClassification::is_regulated`] truth
9658 /// table. Sweep [`DataClassification::ALL`] so a regression that
9659 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9660 /// projection, or (c) crossed the wires with a sibling
9661 /// classification-axis probe fails HERE at the substrate
9662 /// primitive before drifting through the `data-regulated` fixed
9663 /// tag or the peer point surface.
9664 #[test]
9665 fn data_is_regulated_returns_data_classification_projection_per_kind() {
9666 for populated in DataClassification::ALL {
9667 let mut classification = Classification::gate_compute();
9668 classification.data_classification = populated;
9669 let mut spec = empty_ephemeral();
9670 spec.classification = Some(classification);
9671 assert_eq!(
9672 spec.data_is_regulated(),
9673 populated.is_regulated(),
9674 "authored data_classification={populated:?}: data_is_regulated() drift",
9675 );
9676 }
9677 }
9678
9679 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9680 /// with `classification: None` routes through the
9681 /// [`Self::resolved_classification`] resolver's substrate default
9682 /// [`Classification::gate_compute`], which carries
9683 /// [`DataClassification::default = Internal`], and
9684 /// [`DataClassification::Internal::is_regulated`] projects
9685 /// `false`, so [`Self::data_is_regulated`] returns `false`. Pins
9686 /// the default-arm short-circuit through TWO layers of `Default`
9687 /// ([`Classification::gate_compute`] →
9688 /// [`DataClassification::default`]) reaching this derived-nullary
9689 /// predicate — byte-for-byte structural peer of the sibling
9690 /// `calm_requires_coordination_probes_false_on_absent_classification`
9691 /// on the classification-data axis, distinct from the two
9692 /// `horizon_*` absent-classification pins by ONE structural
9693 /// degree (those walk THREE layers because horizon has a nested-
9694 /// struct wrapper; this walks TWO because `data_classification`
9695 /// is a direct scalar). A regression that dropped the resolver
9696 /// hop (silently answering `true` on an absent classification,
9697 /// as if the operator's absence meant "regulated data") fails
9698 /// HERE at ONE narrow ephemeral-surface site.
9699 #[test]
9700 fn data_is_regulated_probes_false_on_absent_classification() {
9701 let spec = empty_ephemeral();
9702 assert!(spec.classification.is_none());
9703 assert!(
9704 !spec.data_is_regulated(),
9705 "absent classification (defaults to gate_compute, data_classification=Internal → is_regulated=false)",
9706 );
9707 }
9708
9709 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9710 /// identically through [`Self::data_is_regulated`] AND through
9711 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_regulated()`
9712 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9713 /// classification, `Some(_)` classification on every
9714 /// [`DataClassification::ALL`] variant) so a future regression on
9715 /// either side of the resolver fails HERE at the parity boundary.
9716 /// Byte-for-byte peer of the sibling
9717 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
9718 /// on the data axis.
9719 #[test]
9720 fn data_is_regulated_matches_point_peer_through_lowered_classification() {
9721 // Absent classification.
9722 let eph = empty_ephemeral();
9723 let lowered: ProcessSpec = eph.clone().into();
9724 assert_eq!(
9725 eph.data_is_regulated(),
9726 lowered.classification.data_is_regulated(),
9727 "None-classification parity drift",
9728 );
9729 // Authored classification.
9730 for populated in DataClassification::ALL {
9731 let mut classification = Classification::gate_compute();
9732 classification.data_classification = populated;
9733 let mut eph = empty_ephemeral();
9734 eph.classification = Some(classification);
9735 let lowered: ProcessSpec = eph.clone().into();
9736 assert_eq!(
9737 eph.data_is_regulated(),
9738 lowered.classification.data_is_regulated(),
9739 "authored data_classification={populated:?}: parity drift",
9740 );
9741 }
9742 }
9743
9744 // ── EphemeralSpec::data_is_restricted pins ───────────────────────
9745 //
9746 // Fail-before-pass-after granularity: `data_is_restricted` did not
9747 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9748 // the "does this ephemeral spec require access controls?" question
9749 // went through
9750 // `.resolved_classification().data_classification.is_restricted()`
9751 // or through the lowered `ProcessSpec`'s
9752 // `spec.classification.data_classification.is_restricted()`. Post-
9753 // lift the FIFTH derived-nullary-boolean peer on the ephemeral
9754 // surface (second on the data axis, after
9755 // [`Self::data_is_regulated`] opened the axis) routes through the
9756 // SAME [`Self::resolved_classification`] resolver + the sibling
9757 // substrate primitive
9758 // [`crate::classification::Classification::data_is_restricted`],
9759 // so the two-surface parity contract holds by construction — a
9760 // regression on either side of the resolver fails at these pins
9761 // before landing at the operator-facing `data-restricted` fixed
9762 // tag in `tatara-check`. FIRST direct-scalar ephemeral-surface
9763 // peer whose absent-classification baseline projects to `true`
9764 // rather than `false`.
9765
9766 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9767 /// [`Classification`] carries a specific [`DataClassification`]
9768 /// variant answers [`Self::data_is_restricted`] matching the
9769 /// closed set's own [`DataClassification::is_restricted`] truth
9770 /// table. Sweep [`DataClassification::ALL`] so a regression that
9771 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9772 /// projection, or (c) crossed the wires with the sibling
9773 /// [`DataClassification::is_regulated`] projection fails HERE at
9774 /// the substrate primitive before drifting through the
9775 /// `data-restricted` fixed tag or the peer point surface.
9776 #[test]
9777 fn data_is_restricted_returns_data_classification_projection_per_kind() {
9778 for populated in DataClassification::ALL {
9779 let mut classification = Classification::gate_compute();
9780 classification.data_classification = populated;
9781 let mut spec = empty_ephemeral();
9782 spec.classification = Some(classification);
9783 assert_eq!(
9784 spec.data_is_restricted(),
9785 populated.is_restricted(),
9786 "authored data_classification={populated:?}: data_is_restricted() drift",
9787 );
9788 }
9789 }
9790
9791 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9792 /// with `classification: None` routes through the
9793 /// [`Self::resolved_classification`] resolver's substrate default
9794 /// [`Classification::gate_compute`], which carries
9795 /// [`DataClassification::default = Internal`], and
9796 /// [`DataClassification::Internal::is_restricted`] projects
9797 /// `true`, so [`Self::data_is_restricted`] returns `true`. Pins
9798 /// the default-arm short-circuit through TWO layers of `Default`
9799 /// ([`Classification::gate_compute`] →
9800 /// [`DataClassification::default`]) reaching this derived-nullary
9801 /// predicate. FIRST direct-scalar ephemeral-surface peer whose
9802 /// absent-classification baseline answers `true`, not `false`
9803 /// (the four earlier direct-scalar peers on this surface —
9804 /// `data_is_regulated`, `calm_requires_coordination`, plus the
9805 /// nested-struct `horizon_requires_metric_axes` — all project
9806 /// `false` on the same absent classification, and only the
9807 /// sibling nested-struct `horizon_terminates` projects `true`).
9808 /// A regression that dropped the resolver hop (silently answering
9809 /// `false` on an absent classification, as if the operator's
9810 /// absence meant "freely distributable"), or that inverted the
9811 /// projection while the closed-set primitive stayed intact,
9812 /// fails HERE at ONE narrow ephemeral-surface site.
9813 #[test]
9814 fn data_is_restricted_probes_true_on_absent_classification() {
9815 let spec = empty_ephemeral();
9816 assert!(spec.classification.is_none());
9817 assert!(
9818 spec.data_is_restricted(),
9819 "absent classification (defaults to gate_compute, data_classification=Internal → is_restricted=true)",
9820 );
9821 }
9822
9823 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9824 /// identically through [`Self::data_is_restricted`] AND through
9825 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_restricted()`
9826 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9827 /// classification, `Some(_)` classification on every
9828 /// [`DataClassification::ALL`] variant) so a future regression on
9829 /// either side of the resolver fails HERE at the parity boundary.
9830 /// Byte-for-byte peer of the sibling
9831 /// `data_is_regulated_matches_point_peer_through_lowered_classification`
9832 /// on the same classification-data axis, published a second time
9833 /// through the antisymmetric closed-set projection.
9834 #[test]
9835 fn data_is_restricted_matches_point_peer_through_lowered_classification() {
9836 // Absent classification.
9837 let eph = empty_ephemeral();
9838 let lowered: ProcessSpec = eph.clone().into();
9839 assert_eq!(
9840 eph.data_is_restricted(),
9841 lowered.classification.data_is_restricted(),
9842 "None-classification parity drift",
9843 );
9844 // Authored classification.
9845 for populated in DataClassification::ALL {
9846 let mut classification = Classification::gate_compute();
9847 classification.data_classification = populated;
9848 let mut eph = empty_ephemeral();
9849 eph.classification = Some(classification);
9850 let lowered: ProcessSpec = eph.clone().into();
9851 assert_eq!(
9852 eph.data_is_restricted(),
9853 lowered.classification.data_is_restricted(),
9854 "authored data_classification={populated:?}: parity drift",
9855 );
9856 }
9857 }
9858
9859 /// COMPOSED IMPLICATION pin — the ephemeral-surface counterpart of
9860 /// the closed-set-internal
9861 /// `data_classification_regulated_implies_restricted` and its
9862 /// parent-composed peer
9863 /// `classification_data_is_regulated_implies_data_is_restricted_over_all`:
9864 /// for every ([`EphemeralSpec`] with authored classification
9865 /// carrying every [`DataClassification`] variant, plus the
9866 /// absent-classification case), the resolver-hop probe pair
9867 /// satisfies `data_is_regulated() ⇒ data_is_restricted()`. Pins
9868 /// the implication contract at the ephemeral-surface site so a
9869 /// regression that (a) inverted the ephemeral
9870 /// [`Self::data_is_regulated`] resolver hop, (b) inverted the
9871 /// ephemeral [`Self::data_is_restricted`] resolver hop, or (c)
9872 /// crossed their wires while the underlying substrate primitives
9873 /// stayed intact fails HERE. FIRST ephemeral-surface corner-peer
9874 /// pair whose two projections carry a non-trivial closed-set-
9875 /// internal implication relationship.
9876 #[test]
9877 fn ephemeral_data_is_regulated_implies_data_is_restricted_over_all() {
9878 // Absent classification.
9879 let eph = empty_ephemeral();
9880 assert!(
9881 !eph.data_is_regulated() || eph.data_is_restricted(),
9882 "None-classification: data_is_regulated ⇒ data_is_restricted violated",
9883 );
9884 // Authored classification.
9885 for populated in DataClassification::ALL {
9886 let mut classification = Classification::gate_compute();
9887 classification.data_classification = populated;
9888 let mut eph = empty_ephemeral();
9889 eph.classification = Some(classification);
9890 assert!(
9891 !eph.data_is_regulated() || eph.data_is_restricted(),
9892 "authored data_classification={populated:?}: data_is_regulated ⇒ data_is_restricted violated",
9893 );
9894 }
9895 }
9896
9897 // ── EphemeralSpec::point_is_endomorphic pins ─────────────────────
9898 //
9899 // Fail-before-pass-after granularity: `point_is_endomorphic` did
9900 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9901 // walking the "does this ephemeral spec's point-type project to
9902 // the 1→1 endomorphic bucket?" question went through
9903 // `.resolved_classification().point_type.is_endomorphic()` or the
9904 // lowered `ProcessSpec`'s
9905 // `spec.classification.point_type.is_endomorphic()`. Post-lift the
9906 // SIXTH derived-nullary-boolean peer on the ephemeral surface
9907 // (first on the `point_type` axis) routes through the SAME
9908 // [`Self::resolved_classification`] resolver + the sibling
9909 // substrate primitive
9910 // [`crate::classification::Classification::point_is_endomorphic`],
9911 // so the two-surface parity contract holds by construction — a
9912 // regression on either side of the resolver fails at these pins
9913 // before landing at the operator-facing `endomorphic-point` fixed
9914 // tag in `tatara-check`.
9915
9916 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9917 /// [`Classification`] carries a specific [`ConvergencePointType`]
9918 /// variant answers [`Self::point_is_endomorphic`] matching the
9919 /// closed set's own [`ConvergencePointType::is_endomorphic`] truth
9920 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9921 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9922 /// projection, or (c) crossed the wires with the sibling
9923 /// [`ConvergencePointType::is_diffusive`] /
9924 /// [`ConvergencePointType::is_convergent`] projections fails
9925 /// HERE at the substrate primitive before drifting through the
9926 /// `endomorphic-point` fixed tag or the peer point surface.
9927 #[test]
9928 fn point_is_endomorphic_returns_point_type_projection_per_kind() {
9929 for populated in ConvergencePointType::ALL {
9930 let mut classification = Classification::gate_compute();
9931 classification.point_type = populated;
9932 let mut spec = empty_ephemeral();
9933 spec.classification = Some(classification);
9934 assert_eq!(
9935 spec.point_is_endomorphic(),
9936 populated.is_endomorphic(),
9937 "authored point_type={populated:?}: point_is_endomorphic() drift",
9938 );
9939 }
9940 }
9941
9942 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9943 /// with `classification: None` routes through the
9944 /// [`Self::resolved_classification`] resolver's substrate default
9945 /// [`Classification::gate_compute`], which carries
9946 /// [`ConvergencePointType::Gate`] (a convergent barrier, not an
9947 /// endomorphism), and
9948 /// [`ConvergencePointType::Gate::is_endomorphic`] projects `false`,
9949 /// so [`Self::point_is_endomorphic`] returns `false`. Pins the
9950 /// resolver's chosen-field baseline at ONE narrow site — a
9951 /// regression that dropped the resolver hop, or that promoted
9952 /// [`ConvergencePointType::Transform`] to the gate-compute
9953 /// baseline (silently retargeting every unadorned ephemeral
9954 /// spec's topology bucket), fails HERE at ONE narrow ephemeral-
9955 /// surface site. FIRST direct-scalar ephemeral-surface peer whose
9956 /// absent-classification baseline is a chosen-field answer on the
9957 /// resolver's [`Classification::gate_compute`] default rather
9958 /// than a substrate-`#[default]` short-circuit on the closed-set
9959 /// side ([`ConvergencePointType`] has no `impl Default`).
9960 #[test]
9961 fn point_is_endomorphic_probes_false_on_absent_classification() {
9962 let spec = empty_ephemeral();
9963 assert!(spec.classification.is_none());
9964 assert!(
9965 !spec.point_is_endomorphic(),
9966 "absent classification (defaults to gate_compute, point_type=Gate → is_endomorphic=false)",
9967 );
9968 }
9969
9970 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9971 /// identically through [`Self::point_is_endomorphic`] AND through
9972 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_endomorphic()`
9973 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9974 /// classification, `Some(_)` classification on every
9975 /// [`ConvergencePointType::ALL`] variant) so a future regression
9976 /// on either side of the resolver fails HERE at the parity
9977 /// boundary. Byte-for-byte peer of the sibling
9978 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
9979 /// on a DIFFERENT closed-set axis, published a first time through
9980 /// the `point_type` closed-set projection.
9981 #[test]
9982 fn point_is_endomorphic_matches_point_peer_through_lowered_classification() {
9983 // Absent classification.
9984 let eph = empty_ephemeral();
9985 let lowered: ProcessSpec = eph.clone().into();
9986 assert_eq!(
9987 eph.point_is_endomorphic(),
9988 lowered.classification.point_is_endomorphic(),
9989 "None-classification parity drift",
9990 );
9991 // Authored classification.
9992 for populated in ConvergencePointType::ALL {
9993 let mut classification = Classification::gate_compute();
9994 classification.point_type = populated;
9995 let mut eph = empty_ephemeral();
9996 eph.classification = Some(classification);
9997 let lowered: ProcessSpec = eph.clone().into();
9998 assert_eq!(
9999 eph.point_is_endomorphic(),
10000 lowered.classification.point_is_endomorphic(),
10001 "authored point_type={populated:?}: parity drift",
10002 );
10003 }
10004 }
10005
10006 // ── EphemeralSpec::point_is_diffusive pins ───────────────────────
10007 //
10008 // Fail-before-pass-after granularity: `point_is_diffusive` did not
10009 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10010 // the "does this ephemeral spec's point-type project to the 1→N
10011 // diffusive fan-out bucket?" question went through
10012 // `.resolved_classification().point_type.is_diffusive()` or the
10013 // lowered `ProcessSpec`'s
10014 // `spec.classification.point_type.is_diffusive()`. Post-lift the
10015 // SEVENTH derived-nullary-boolean peer on the ephemeral surface
10016 // (SECOND on the `point_type` axis) routes through the SAME
10017 // [`Self::resolved_classification`] resolver + the sibling
10018 // substrate primitive
10019 // [`crate::classification::Classification::point_is_diffusive`],
10020 // so the two-surface parity contract holds by construction.
10021
10022 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10023 /// [`Classification`] carries a specific [`ConvergencePointType`]
10024 /// variant answers [`Self::point_is_diffusive`] matching the
10025 /// closed set's own [`ConvergencePointType::is_diffusive`] truth
10026 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10027 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10028 /// projection, or (c) crossed the wires with the sibling
10029 /// [`ConvergencePointType::is_endomorphic`] /
10030 /// [`ConvergencePointType::is_convergent`] projections fails HERE
10031 /// at the substrate primitive before drifting through the
10032 /// `diffusive-point` fixed tag or the peer point surface.
10033 #[test]
10034 fn point_is_diffusive_returns_point_type_projection_per_kind() {
10035 for populated in ConvergencePointType::ALL {
10036 let mut classification = Classification::gate_compute();
10037 classification.point_type = populated;
10038 let mut spec = empty_ephemeral();
10039 spec.classification = Some(classification);
10040 assert_eq!(
10041 spec.point_is_diffusive(),
10042 populated.is_diffusive(),
10043 "authored point_type={populated:?}: point_is_diffusive() drift",
10044 );
10045 }
10046 }
10047
10048 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10049 /// with `classification: None` routes through the
10050 /// [`Self::resolved_classification`] resolver's substrate default
10051 /// [`Classification::gate_compute`], which carries
10052 /// [`ConvergencePointType::Gate`] (a convergent barrier, not a
10053 /// diffusive fan-out), and
10054 /// [`ConvergencePointType::Gate::is_diffusive`] projects `false`,
10055 /// so [`Self::point_is_diffusive`] returns `false`. Pins the
10056 /// resolver's chosen-field baseline at ONE narrow site.
10057 #[test]
10058 fn point_is_diffusive_probes_false_on_absent_classification() {
10059 let spec = empty_ephemeral();
10060 assert!(spec.classification.is_none());
10061 assert!(
10062 !spec.point_is_diffusive(),
10063 "absent classification (defaults to gate_compute, point_type=Gate → is_diffusive=false)",
10064 );
10065 }
10066
10067 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10068 /// identically through [`Self::point_is_diffusive`] AND through
10069 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_diffusive()`
10070 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10071 /// classification, `Some(_)` classification on every
10072 /// [`ConvergencePointType::ALL`] variant) so a future regression
10073 /// on either side of the resolver fails HERE at the parity
10074 /// boundary. Byte-for-byte peer of
10075 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
10076 /// on the SAME closed-set axis via a sibling projection.
10077 #[test]
10078 fn point_is_diffusive_matches_point_peer_through_lowered_classification() {
10079 // Absent classification.
10080 let eph = empty_ephemeral();
10081 let lowered: ProcessSpec = eph.clone().into();
10082 assert_eq!(
10083 eph.point_is_diffusive(),
10084 lowered.classification.point_is_diffusive(),
10085 "None-classification parity drift",
10086 );
10087 // Authored classification.
10088 for populated in ConvergencePointType::ALL {
10089 let mut classification = Classification::gate_compute();
10090 classification.point_type = populated;
10091 let mut eph = empty_ephemeral();
10092 eph.classification = Some(classification);
10093 let lowered: ProcessSpec = eph.clone().into();
10094 assert_eq!(
10095 eph.point_is_diffusive(),
10096 lowered.classification.point_is_diffusive(),
10097 "authored point_type={populated:?}: parity drift",
10098 );
10099 }
10100 }
10101
10102 /// MUTEX pin — [`Self::point_is_endomorphic`] AND
10103 /// [`Self::point_is_diffusive`] are NEVER simultaneously true for
10104 /// ANY [`EphemeralSpec`] (authored or defaulted), since the
10105 /// underlying [`ConvergencePointType`] closed set carves its
10106 /// eight variants into THREE disjoint buckets. Sweep the absent-
10107 /// classification case + every [`ConvergencePointType::ALL`]
10108 /// variant so a regression that crossed the wires between the
10109 /// two ephemeral-surface corner peers (one probe silently
10110 /// composing the wrong closed-set arm at the resolver-hop layer)
10111 /// fails HERE rather than at every downstream consumer that
10112 /// trusts the two probes partition the resolver's output into
10113 /// disjoint buckets. FIRST ephemeral-surface corner-peer pair on
10114 /// the `point_type` axis whose two projections carry a non-
10115 /// trivial closed-set-internal MUTEX relationship (distinct from
10116 /// the sibling `data`-axis pair whose two projections carry a
10117 /// non-trivial IMPLICATION relationship, sealed by
10118 /// `ephemeral_data_is_regulated_implies_data_is_restricted_over_all`).
10119 #[test]
10120 fn ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all() {
10121 // Absent classification.
10122 let eph = empty_ephemeral();
10123 assert!(
10124 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
10125 "None-classification: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
10126 );
10127 // Authored classification.
10128 for populated in ConvergencePointType::ALL {
10129 let mut classification = Classification::gate_compute();
10130 classification.point_type = populated;
10131 let mut eph = empty_ephemeral();
10132 eph.classification = Some(classification);
10133 assert!(
10134 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
10135 "authored point_type={populated:?}: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
10136 );
10137 }
10138 }
10139
10140 // ── EphemeralSpec::point_is_convergent pins ──────────────────────
10141 //
10142 // Fail-before-pass-after granularity: `point_is_convergent` did
10143 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10144 // walking the "does this ephemeral spec's point-type project to
10145 // the N→1 convergent fan-in bucket?" question went through
10146 // `.resolved_classification().point_type.is_convergent()` or the
10147 // lowered `ProcessSpec`'s
10148 // `spec.classification.point_type.is_convergent()`. Post-lift the
10149 // EIGHTH derived-nullary-boolean peer on the ephemeral surface
10150 // (THIRD on the `point_type` axis) routes through the SAME
10151 // [`Self::resolved_classification`] resolver + the sibling
10152 // substrate primitive
10153 // [`crate::classification::Classification::point_is_convergent`],
10154 // so the two-surface parity contract holds by construction, AND
10155 // the THREE `point_type`-axis peers on this surface close into
10156 // the FULL three-way XOR partition contract.
10157
10158 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10159 /// [`Classification`] carries a specific [`ConvergencePointType`]
10160 /// variant answers [`Self::point_is_convergent`] matching the
10161 /// closed set's own [`ConvergencePointType::is_convergent`] truth
10162 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10163 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10164 /// projection, or (c) crossed the wires with the sibling
10165 /// [`ConvergencePointType::is_endomorphic`] /
10166 /// [`ConvergencePointType::is_diffusive`] projections fails HERE
10167 /// at the substrate primitive before drifting through the
10168 /// `convergent-point` fixed tag or the peer point surface.
10169 #[test]
10170 fn point_is_convergent_returns_point_type_projection_per_kind() {
10171 for populated in ConvergencePointType::ALL {
10172 let mut classification = Classification::gate_compute();
10173 classification.point_type = populated;
10174 let mut spec = empty_ephemeral();
10175 spec.classification = Some(classification);
10176 assert_eq!(
10177 spec.point_is_convergent(),
10178 populated.is_convergent(),
10179 "authored point_type={populated:?}: point_is_convergent() drift",
10180 );
10181 }
10182 }
10183
10184 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10185 /// with `classification: None` routes through the
10186 /// [`Self::resolved_classification`] resolver's substrate default
10187 /// [`Classification::gate_compute`], which carries
10188 /// [`ConvergencePointType::Gate`] (the canonical convergent
10189 /// barrier), and [`ConvergencePointType::Gate::is_convergent`]
10190 /// projects `true`, so [`Self::point_is_convergent`] returns
10191 /// `true`. Pins the resolver's chosen-field baseline at ONE
10192 /// narrow site — FIRST direct-scalar ephemeral-surface peer whose
10193 /// absent-classification baseline projects `true` through the
10194 /// resolver's chosen-field answer, mirror-inverted from the two
10195 /// sibling `point_is_endomorphic` / `point_is_diffusive`
10196 /// ephemeral-surface baselines which both project `false`.
10197 #[test]
10198 fn point_is_convergent_probes_true_on_absent_classification() {
10199 let spec = empty_ephemeral();
10200 assert!(spec.classification.is_none());
10201 assert!(
10202 spec.point_is_convergent(),
10203 "absent classification (defaults to gate_compute, point_type=Gate → is_convergent=true)",
10204 );
10205 }
10206
10207 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10208 /// identically through [`Self::point_is_convergent`] AND through
10209 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_convergent()`
10210 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10211 /// classification, `Some(_)` classification on every
10212 /// [`ConvergencePointType::ALL`] variant) so a future regression
10213 /// on either side of the resolver fails HERE at the parity
10214 /// boundary. Byte-for-byte peer of
10215 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
10216 /// and
10217 /// `point_is_diffusive_matches_point_peer_through_lowered_classification`
10218 /// on the SAME closed-set axis via a sibling projection.
10219 #[test]
10220 fn point_is_convergent_matches_point_peer_through_lowered_classification() {
10221 // Absent classification.
10222 let eph = empty_ephemeral();
10223 let lowered: ProcessSpec = eph.clone().into();
10224 assert_eq!(
10225 eph.point_is_convergent(),
10226 lowered.classification.point_is_convergent(),
10227 "None-classification parity drift",
10228 );
10229 // Authored classification.
10230 for populated in ConvergencePointType::ALL {
10231 let mut classification = Classification::gate_compute();
10232 classification.point_type = populated;
10233 let mut eph = empty_ephemeral();
10234 eph.classification = Some(classification);
10235 let lowered: ProcessSpec = eph.clone().into();
10236 assert_eq!(
10237 eph.point_is_convergent(),
10238 lowered.classification.point_is_convergent(),
10239 "authored point_type={populated:?}: parity drift",
10240 );
10241 }
10242 }
10243
10244 /// THREE-WAY XOR PARTITION pin — for the absent-classification
10245 /// baseline AND every [`ConvergencePointType::ALL`] variant,
10246 /// EXACTLY ONE of [`Self::point_is_endomorphic`],
10247 /// [`Self::point_is_diffusive`], and [`Self::point_is_convergent`]
10248 /// returns `true`. Closes the mutex pair
10249 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`
10250 /// into the FULL ternary XOR partition contract on the ephemeral
10251 /// surface — the resolver-hop peer of the parent-composed
10252 /// `classification_point_type_probes_form_three_way_xor_partition_over_all`
10253 /// test. Guarantees the absent-classification case lands in the
10254 /// convergent bucket (`gate_compute` → Gate → is_convergent =
10255 /// true), so every unadorned `(defephemeral …)` audits under a
10256 /// definite non-empty topology bucket.
10257 #[test]
10258 fn ephemeral_point_type_probes_form_three_way_xor_partition_over_all() {
10259 // Absent classification.
10260 let eph = empty_ephemeral();
10261 let buckets = [
10262 eph.point_is_endomorphic(),
10263 eph.point_is_diffusive(),
10264 eph.point_is_convergent(),
10265 ];
10266 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10267 assert_eq!(
10268 hits, 1,
10269 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10270 );
10271 // Authored classification.
10272 for populated in ConvergencePointType::ALL {
10273 let mut classification = Classification::gate_compute();
10274 classification.point_type = populated;
10275 let mut eph = empty_ephemeral();
10276 eph.classification = Some(classification);
10277 let buckets = [
10278 eph.point_is_endomorphic(),
10279 eph.point_is_diffusive(),
10280 eph.point_is_convergent(),
10281 ];
10282 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10283 assert_eq!(
10284 hits, 1,
10285 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10286 );
10287 }
10288 }
10289
10290 // ── EphemeralSpec::substrate_is_resource pins ────────────────────
10291 //
10292 // Fail-before-pass-after granularity: `substrate_is_resource` did
10293 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10294 // walking the "does this ephemeral spec's substrate project to
10295 // the resource plane?" question went through
10296 // `.resolved_classification().substrate.is_resource()` or the
10297 // lowered `ProcessSpec`'s
10298 // `spec.classification.substrate.is_resource()`. Post-lift the
10299 // NINTH derived-nullary-boolean peer on the ephemeral surface
10300 // (FIRST on the `substrate` axis) routes through the SAME
10301 // [`Self::resolved_classification`] resolver + the sibling
10302 // substrate primitive
10303 // [`crate::classification::Classification::substrate_is_resource`],
10304 // so the two-surface parity contract holds by construction.
10305
10306 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10307 /// [`Classification`] carries a specific
10308 /// [`crate::classification::SubstrateType`] variant answers
10309 /// [`Self::substrate_is_resource`] matching the closed set's own
10310 /// [`crate::classification::SubstrateType::is_resource`] truth
10311 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10312 /// so a regression that (a) hard-coded the body to a fixed
10313 /// answer, (b) inverted the projection, or (c) crossed the wires
10314 /// with the sibling
10315 /// [`crate::classification::SubstrateType::is_policy`] /
10316 /// [`crate::classification::SubstrateType::is_telemetry`]
10317 /// projections fails HERE at the substrate primitive before
10318 /// drifting through the `resource-substrate` fixed tag or the
10319 /// peer point surface.
10320 #[test]
10321 fn substrate_is_resource_returns_substrate_projection_per_kind() {
10322 for populated in SubstrateType::ALL {
10323 let mut classification = Classification::gate_compute();
10324 classification.substrate = populated;
10325 let mut spec = empty_ephemeral();
10326 spec.classification = Some(classification);
10327 assert_eq!(
10328 spec.substrate_is_resource(),
10329 populated.is_resource(),
10330 "authored substrate={populated:?}: substrate_is_resource() drift",
10331 );
10332 }
10333 }
10334
10335 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10336 /// with `classification: None` routes through the
10337 /// [`Self::resolved_classification`] resolver's substrate default
10338 /// [`Classification::gate_compute`], which carries
10339 /// [`crate::classification::SubstrateType::Compute`] (the
10340 /// canonical resource-plane substrate), and
10341 /// [`crate::classification::SubstrateType::Compute::is_resource`]
10342 /// projects `true`, so [`Self::substrate_is_resource`] returns
10343 /// `true`. Pins the resolver's chosen-field baseline at ONE
10344 /// narrow site — mirror-aligned with the sibling
10345 /// `point_is_convergent_probes_true_on_absent_classification`
10346 /// baseline (both projections on `gate_compute` chosen fields
10347 /// answer `true`).
10348 #[test]
10349 fn substrate_is_resource_probes_true_on_absent_classification() {
10350 let spec = empty_ephemeral();
10351 assert!(spec.classification.is_none());
10352 assert!(
10353 spec.substrate_is_resource(),
10354 "absent classification (defaults to gate_compute, substrate=Compute → is_resource=true)",
10355 );
10356 }
10357
10358 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10359 /// identically through [`Self::substrate_is_resource`] AND through
10360 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_resource()`
10361 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10362 /// classification, `Some(_)` classification on every
10363 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10364 /// future regression on either side of the resolver fails HERE
10365 /// at the parity boundary. Byte-for-byte peer of
10366 /// `point_is_convergent_matches_point_peer_through_lowered_classification`
10367 /// on a sibling classification axis.
10368 #[test]
10369 fn substrate_is_resource_matches_point_peer_through_lowered_classification() {
10370 // Absent classification.
10371 let eph = empty_ephemeral();
10372 let lowered: ProcessSpec = eph.clone().into();
10373 assert_eq!(
10374 eph.substrate_is_resource(),
10375 lowered.classification.substrate_is_resource(),
10376 "None-classification parity drift",
10377 );
10378 // Authored classification.
10379 for populated in SubstrateType::ALL {
10380 let mut classification = Classification::gate_compute();
10381 classification.substrate = populated;
10382 let mut eph = empty_ephemeral();
10383 eph.classification = Some(classification);
10384 let lowered: ProcessSpec = eph.clone().into();
10385 assert_eq!(
10386 eph.substrate_is_resource(),
10387 lowered.classification.substrate_is_resource(),
10388 "authored substrate={populated:?}: parity drift",
10389 );
10390 }
10391 }
10392
10393 // ── EphemeralSpec::substrate_is_policy pins ──────────────────────
10394 //
10395 // Fail-before-pass-after granularity: `substrate_is_policy` did
10396 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10397 // walking the "does this ephemeral spec's substrate project to
10398 // the policy plane?" question went through
10399 // `.resolved_classification().substrate.is_policy()` or the
10400 // lowered `ProcessSpec`'s
10401 // `spec.classification.substrate.is_policy()`. Post-lift the
10402 // TENTH derived-nullary-boolean peer on the ephemeral surface
10403 // (SECOND on the `substrate` axis) routes through the SAME
10404 // [`Self::resolved_classification`] resolver + the sibling
10405 // substrate primitive
10406 // [`crate::classification::Classification::substrate_is_policy`],
10407 // so the two-surface parity contract holds by construction, AND
10408 // the two `substrate`-axis peers on this surface open the
10409 // MUTEX pair on the axis via
10410 // `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`.
10411
10412 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10413 /// [`Classification`] carries a specific
10414 /// [`crate::classification::SubstrateType`] variant answers
10415 /// [`Self::substrate_is_policy`] matching the closed set's own
10416 /// [`crate::classification::SubstrateType::is_policy`] truth
10417 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10418 /// so a regression that (a) hard-coded the body to a fixed
10419 /// answer, (b) inverted the projection, or (c) crossed the wires
10420 /// with the sibling
10421 /// [`crate::classification::SubstrateType::is_resource`] /
10422 /// [`crate::classification::SubstrateType::is_telemetry`]
10423 /// projections fails HERE at the substrate primitive before
10424 /// drifting through the `policy-substrate` fixed tag or the
10425 /// peer point surface.
10426 #[test]
10427 fn substrate_is_policy_returns_substrate_projection_per_kind() {
10428 for populated in SubstrateType::ALL {
10429 let mut classification = Classification::gate_compute();
10430 classification.substrate = populated;
10431 let mut spec = empty_ephemeral();
10432 spec.classification = Some(classification);
10433 assert_eq!(
10434 spec.substrate_is_policy(),
10435 populated.is_policy(),
10436 "authored substrate={populated:?}: substrate_is_policy() drift",
10437 );
10438 }
10439 }
10440
10441 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10442 /// with `classification: None` routes through the
10443 /// [`Self::resolved_classification`] resolver's substrate default
10444 /// [`Classification::gate_compute`], which carries
10445 /// [`crate::classification::SubstrateType::Compute`] (the
10446 /// canonical resource-plane substrate, NOT a policy plane), and
10447 /// [`crate::classification::SubstrateType::Compute::is_policy`]
10448 /// projects `false`, so [`Self::substrate_is_policy`] returns
10449 /// `false`. Pins the resolver's chosen-field baseline at ONE
10450 /// narrow site — mirror-inverted from the sibling
10451 /// `substrate_is_resource_probes_true_on_absent_classification`
10452 /// (both projections on `gate_compute`'s chosen `substrate`
10453 /// field, but the sibling answers `true` where this one
10454 /// answers `false` — the closed set's disjoint plane partition
10455 /// forbids both being true).
10456 #[test]
10457 fn substrate_is_policy_probes_false_on_absent_classification() {
10458 let spec = empty_ephemeral();
10459 assert!(spec.classification.is_none());
10460 assert!(
10461 !spec.substrate_is_policy(),
10462 "absent classification (defaults to gate_compute, substrate=Compute → is_policy=false)",
10463 );
10464 }
10465
10466 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10467 /// identically through [`Self::substrate_is_policy`] AND through
10468 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_policy()`
10469 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10470 /// classification, `Some(_)` classification on every
10471 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10472 /// future regression on either side of the resolver fails HERE
10473 /// at the parity boundary. Byte-for-byte peer of
10474 /// `substrate_is_resource_matches_point_peer_through_lowered_classification`
10475 /// on the SAME closed-set axis via a sibling projection.
10476 #[test]
10477 fn substrate_is_policy_matches_point_peer_through_lowered_classification() {
10478 // Absent classification.
10479 let eph = empty_ephemeral();
10480 let lowered: ProcessSpec = eph.clone().into();
10481 assert_eq!(
10482 eph.substrate_is_policy(),
10483 lowered.classification.substrate_is_policy(),
10484 "None-classification parity drift",
10485 );
10486 // Authored classification.
10487 for populated in SubstrateType::ALL {
10488 let mut classification = Classification::gate_compute();
10489 classification.substrate = populated;
10490 let mut eph = empty_ephemeral();
10491 eph.classification = Some(classification);
10492 let lowered: ProcessSpec = eph.clone().into();
10493 assert_eq!(
10494 eph.substrate_is_policy(),
10495 lowered.classification.substrate_is_policy(),
10496 "authored substrate={populated:?}: parity drift",
10497 );
10498 }
10499 }
10500
10501 /// MUTEX pin — [`Self::substrate_is_resource`] AND
10502 /// [`Self::substrate_is_policy`] are NEVER simultaneously true
10503 /// for ANY [`EphemeralSpec`] (authored or defaulted), since the
10504 /// underlying [`crate::classification::SubstrateType`] closed set
10505 /// carves its eight variants into THREE disjoint buckets. Sweep
10506 /// the absent-classification case + every
10507 /// [`crate::classification::SubstrateType::ALL`] variant so a
10508 /// regression that crossed the wires between the two ephemeral-
10509 /// surface corner peers (one probe silently composing the wrong
10510 /// closed-set arm at the resolver-hop layer) fails HERE rather
10511 /// than at every downstream consumer that trusts the two probes
10512 /// partition the resolver's output into disjoint buckets.
10513 /// FIRST ephemeral-surface `substrate`-axis corner-peer pair
10514 /// carrying a non-trivial MUTEX relationship — structural twin
10515 /// of the sibling `point_type`-axis MUTEX pair sealed on this
10516 /// surface by
10517 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
10518 #[test]
10519 fn ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all() {
10520 // Absent classification.
10521 let eph = empty_ephemeral();
10522 assert!(
10523 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
10524 "None-classification: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
10525 );
10526 // Authored classification.
10527 for populated in SubstrateType::ALL {
10528 let mut classification = Classification::gate_compute();
10529 classification.substrate = populated;
10530 let mut eph = empty_ephemeral();
10531 eph.classification = Some(classification);
10532 assert!(
10533 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
10534 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
10535 );
10536 }
10537 }
10538
10539 // ── EphemeralSpec::substrate_is_telemetry pins ───────────────────
10540 //
10541 // Fail-before-pass-after granularity: `substrate_is_telemetry`
10542 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10543 // walking the "does this ephemeral spec's substrate project to
10544 // the telemetry plane?" question went through
10545 // `.resolved_classification().substrate.is_telemetry()` or the
10546 // lowered `ProcessSpec`'s
10547 // `spec.classification.substrate.is_telemetry()`. Post-lift the
10548 // ELEVENTH derived-nullary-boolean peer on the ephemeral surface
10549 // (THIRD on the `substrate` axis) routes through the SAME
10550 // [`Self::resolved_classification`] resolver + the sibling
10551 // substrate primitive
10552 // [`crate::classification::Classification::substrate_is_telemetry`],
10553 // so the two-surface parity contract holds by construction, AND
10554 // the three `substrate`-axis peers on this surface CLOSE the
10555 // axis into the FULL three-way XOR partition contract via
10556 // `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
10557
10558 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10559 /// [`Classification`] carries a specific
10560 /// [`crate::classification::SubstrateType`] variant answers
10561 /// [`Self::substrate_is_telemetry`] matching the closed set's own
10562 /// [`crate::classification::SubstrateType::is_telemetry`] truth
10563 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10564 /// so a regression that (a) hard-coded the body to a fixed
10565 /// answer, (b) inverted the projection, or (c) crossed the wires
10566 /// with the sibling
10567 /// [`crate::classification::SubstrateType::is_resource`] /
10568 /// [`crate::classification::SubstrateType::is_policy`]
10569 /// projections fails HERE at the substrate primitive before
10570 /// drifting through the `telemetry-substrate` fixed tag or the
10571 /// peer point surface.
10572 #[test]
10573 fn substrate_is_telemetry_returns_substrate_projection_per_kind() {
10574 for populated in SubstrateType::ALL {
10575 let mut classification = Classification::gate_compute();
10576 classification.substrate = populated;
10577 let mut spec = empty_ephemeral();
10578 spec.classification = Some(classification);
10579 assert_eq!(
10580 spec.substrate_is_telemetry(),
10581 populated.is_telemetry(),
10582 "authored substrate={populated:?}: substrate_is_telemetry() drift",
10583 );
10584 }
10585 }
10586
10587 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10588 /// with `classification: None` routes through the
10589 /// [`Self::resolved_classification`] resolver's substrate default
10590 /// [`Classification::gate_compute`], which carries
10591 /// [`crate::classification::SubstrateType::Compute`] (the
10592 /// canonical resource-plane substrate, NOT a telemetry plane),
10593 /// and
10594 /// [`crate::classification::SubstrateType::Compute::is_telemetry`]
10595 /// projects `false`, so [`Self::substrate_is_telemetry`] returns
10596 /// `false`. Pins the resolver's chosen-field baseline at ONE
10597 /// narrow site — aligned with the sibling
10598 /// `substrate_is_policy_probes_false_on_absent_classification`
10599 /// (both projections on `gate_compute`'s chosen `substrate`
10600 /// field project `false` since `Compute` lives in the resource
10601 /// plane), mirror-inverted from
10602 /// `substrate_is_resource_probes_true_on_absent_classification`.
10603 #[test]
10604 fn substrate_is_telemetry_probes_false_on_absent_classification() {
10605 let spec = empty_ephemeral();
10606 assert!(spec.classification.is_none());
10607 assert!(
10608 !spec.substrate_is_telemetry(),
10609 "absent classification (defaults to gate_compute, substrate=Compute → is_telemetry=false)",
10610 );
10611 }
10612
10613 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10614 /// identically through [`Self::substrate_is_telemetry`] AND
10615 /// through
10616 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_telemetry()`
10617 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10618 /// classification, `Some(_)` classification on every
10619 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10620 /// future regression on either side of the resolver fails HERE
10621 /// at the parity boundary. Byte-for-byte peer of
10622 /// `substrate_is_policy_matches_point_peer_through_lowered_classification`
10623 /// on the SAME closed-set axis via a sibling projection.
10624 #[test]
10625 fn substrate_is_telemetry_matches_point_peer_through_lowered_classification() {
10626 // Absent classification.
10627 let eph = empty_ephemeral();
10628 let lowered: ProcessSpec = eph.clone().into();
10629 assert_eq!(
10630 eph.substrate_is_telemetry(),
10631 lowered.classification.substrate_is_telemetry(),
10632 "None-classification parity drift",
10633 );
10634 // Authored classification.
10635 for populated in SubstrateType::ALL {
10636 let mut classification = Classification::gate_compute();
10637 classification.substrate = populated;
10638 let mut eph = empty_ephemeral();
10639 eph.classification = Some(classification);
10640 let lowered: ProcessSpec = eph.clone().into();
10641 assert_eq!(
10642 eph.substrate_is_telemetry(),
10643 lowered.classification.substrate_is_telemetry(),
10644 "authored substrate={populated:?}: parity drift",
10645 );
10646 }
10647 }
10648
10649 /// MUTEX pin — [`Self::substrate_is_resource`] AND
10650 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
10651 /// for ANY [`EphemeralSpec`] (authored or defaulted). Second
10652 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
10653 /// peer of
10654 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
10655 /// on a sibling closed-set projection.
10656 #[test]
10657 fn ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all() {
10658 // Absent classification.
10659 let eph = empty_ephemeral();
10660 assert!(
10661 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
10662 "None-classification: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
10663 );
10664 // Authored classification.
10665 for populated in SubstrateType::ALL {
10666 let mut classification = Classification::gate_compute();
10667 classification.substrate = populated;
10668 let mut eph = empty_ephemeral();
10669 eph.classification = Some(classification);
10670 assert!(
10671 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
10672 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
10673 );
10674 }
10675 }
10676
10677 /// MUTEX pin — [`Self::substrate_is_policy`] AND
10678 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
10679 /// for ANY [`EphemeralSpec`] (authored or defaulted). Third
10680 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
10681 /// completes the three pairwise MUTEX relations alongside
10682 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
10683 /// and
10684 /// `ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all`.
10685 #[test]
10686 fn ephemeral_substrate_is_policy_and_substrate_is_telemetry_are_mutex_over_all() {
10687 // Absent classification.
10688 let eph = empty_ephemeral();
10689 assert!(
10690 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
10691 "None-classification: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
10692 );
10693 // Authored classification.
10694 for populated in SubstrateType::ALL {
10695 let mut classification = Classification::gate_compute();
10696 classification.substrate = populated;
10697 let mut eph = empty_ephemeral();
10698 eph.classification = Some(classification);
10699 assert!(
10700 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
10701 "authored substrate={populated:?}: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
10702 );
10703 }
10704 }
10705
10706 /// THREE-WAY XOR PARTITION pin — for the absent-classification
10707 /// baseline AND every [`crate::classification::SubstrateType::ALL`]
10708 /// variant, EXACTLY ONE of [`Self::substrate_is_resource`],
10709 /// [`Self::substrate_is_policy`], and
10710 /// [`Self::substrate_is_telemetry`] returns `true`. CLOSES the
10711 /// three pairwise MUTEX pins on the substrate axis
10712 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`,
10713 /// `substrate_is_resource ⇒ ¬substrate_is_telemetry`,
10714 /// `substrate_is_policy ⇒ ¬substrate_is_telemetry`) into the
10715 /// FULL ternary XOR partition contract on the ephemeral surface
10716 /// — the resolver-hop peer of the parent-composed
10717 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`
10718 /// test. Structural twin of the sibling `point_type`-axis
10719 /// ternary lift sealed on this surface by
10720 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
10721 /// Guarantees the absent-classification case lands in the
10722 /// resource bucket (`gate_compute` → Compute → is_resource =
10723 /// true), so every unadorned `(defephemeral …)` audits under a
10724 /// definite non-empty plane bucket.
10725 #[test]
10726 fn ephemeral_substrate_probes_form_three_way_xor_partition_over_all() {
10727 // Absent classification.
10728 let eph = empty_ephemeral();
10729 let buckets = [
10730 eph.substrate_is_resource(),
10731 eph.substrate_is_policy(),
10732 eph.substrate_is_telemetry(),
10733 ];
10734 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10735 assert_eq!(
10736 hits, 1,
10737 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10738 );
10739 // Authored classification.
10740 for populated in SubstrateType::ALL {
10741 let mut classification = Classification::gate_compute();
10742 classification.substrate = populated;
10743 let mut eph = empty_ephemeral();
10744 eph.classification = Some(classification);
10745 let buckets = [
10746 eph.substrate_is_resource(),
10747 eph.substrate_is_policy(),
10748 eph.substrate_is_telemetry(),
10749 ];
10750 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10751 assert_eq!(
10752 hits, 1,
10753 "authored substrate={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10754 );
10755 }
10756 }
10757
10758 // ── EphemeralSpec::calm_is_monotone pins ─────────────────────────
10759 //
10760 // Fail-before-pass-after granularity: `calm_is_monotone` did not
10761 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10762 // the "can this ephemeral spec participate in gossip-only writes?"
10763 // question went through the antisymmetric
10764 // `!self.calm_requires_coordination()` or through
10765 // `.resolved_classification().calm.is_monotone()`. Post-lift the
10766 // TWELFTH derived-nullary-boolean peer on the ephemeral surface
10767 // (SECOND on the calm axis, closing that axis into a binary XOR
10768 // partition on this surface) routes through the SAME
10769 // [`Self::resolved_classification`] resolver + the sibling
10770 // substrate primitive
10771 // [`crate::classification::Classification::calm_is_monotone`], so
10772 // the two-surface parity contract holds by construction, AND the
10773 // two calm-axis peers on this surface CLOSE the axis into the
10774 // FULL binary XOR partition contract via
10775 // `ephemeral_calm_probes_form_binary_xor_partition_over_all`.
10776
10777 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10778 /// [`Classification`] carries a specific
10779 /// [`crate::classification::CalmClassification`] variant answers
10780 /// [`Self::calm_is_monotone`] matching the closed set's own
10781 /// [`crate::classification::CalmClassification::is_monotone`]
10782 /// truth table. Sweep
10783 /// [`crate::classification::CalmClassification::ALL`] so a
10784 /// regression that (a) hard-coded the body to a fixed answer,
10785 /// (b) inverted the projection, or (c) crossed the wires with
10786 /// the sibling
10787 /// [`crate::classification::CalmClassification::requires_coordination`]
10788 /// projection fails HERE at the substrate primitive before
10789 /// drifting through the `monotone-calm` fixed tag or the peer
10790 /// point surface.
10791 #[test]
10792 fn calm_is_monotone_returns_calm_projection_per_kind() {
10793 for populated in CalmClassification::ALL {
10794 let mut classification = Classification::gate_compute();
10795 classification.calm = populated;
10796 let mut spec = empty_ephemeral();
10797 spec.classification = Some(classification);
10798 assert_eq!(
10799 spec.calm_is_monotone(),
10800 populated.is_monotone(),
10801 "authored calm={populated:?}: calm_is_monotone() drift",
10802 );
10803 }
10804 }
10805
10806 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10807 /// with `classification: None` routes through the
10808 /// [`Self::resolved_classification`] resolver's substrate default
10809 /// [`Classification::gate_compute`], which carries
10810 /// [`crate::classification::CalmClassification::default = Monotone`]
10811 /// via `#[default]`, and
10812 /// [`crate::classification::CalmClassification::Monotone::is_monotone`]
10813 /// projects `true`, so [`Self::calm_is_monotone`] returns
10814 /// `true`. Pins the resolver's default-arm short-circuit through
10815 /// TWO layers of `Default` ([`Classification::gate_compute`] →
10816 /// [`crate::classification::CalmClassification::default`])
10817 /// reaching this derived-nullary predicate. Mirror-inverted from
10818 /// the sibling
10819 /// `calm_requires_coordination_probes_false_on_absent_classification`
10820 /// (both walk the SAME defaulted `calm` field, so
10821 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
10822 /// closed set's disjoint XOR partition). Guarantees every
10823 /// unadorned `(defephemeral …)` reads as gossip-eligible under
10824 /// the positive CALM framing.
10825 #[test]
10826 fn calm_is_monotone_probes_true_on_absent_classification() {
10827 let spec = empty_ephemeral();
10828 assert!(spec.classification.is_none());
10829 assert!(
10830 spec.calm_is_monotone(),
10831 "absent classification (defaults to gate_compute, calm=Monotone → is_monotone=true)",
10832 );
10833 }
10834
10835 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10836 /// identically through [`Self::calm_is_monotone`] AND through
10837 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_is_monotone()`
10838 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10839 /// classification, `Some(_)` classification on every
10840 /// [`crate::classification::CalmClassification::ALL`] variant) so
10841 /// a future regression on either side of the resolver fails HERE
10842 /// at the parity boundary. Byte-for-byte peer of
10843 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
10844 /// on the SAME closed-set axis via the antisymmetric projection.
10845 #[test]
10846 fn calm_is_monotone_matches_point_peer_through_lowered_classification() {
10847 // Absent classification.
10848 let eph = empty_ephemeral();
10849 let lowered: ProcessSpec = eph.clone().into();
10850 assert_eq!(
10851 eph.calm_is_monotone(),
10852 lowered.classification.calm_is_monotone(),
10853 "None-classification parity drift",
10854 );
10855 // Authored classification.
10856 for populated in CalmClassification::ALL {
10857 let mut classification = Classification::gate_compute();
10858 classification.calm = populated;
10859 let mut eph = empty_ephemeral();
10860 eph.classification = Some(classification);
10861 let lowered: ProcessSpec = eph.clone().into();
10862 assert_eq!(
10863 eph.calm_is_monotone(),
10864 lowered.classification.calm_is_monotone(),
10865 "authored calm={populated:?}: parity drift",
10866 );
10867 }
10868 }
10869
10870 /// MUTEX pin — [`Self::calm_requires_coordination`] AND
10871 /// [`Self::calm_is_monotone`] are NEVER simultaneously true for
10872 /// ANY [`EphemeralSpec`] (authored or defaulted). FIRST
10873 /// ephemeral-surface `calm`-axis corner-peer MUTEX pin — the
10874 /// calm axis's counterpart to the sibling substrate-axis
10875 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
10876 /// on a binary (rather than ternary) closed set.
10877 #[test]
10878 fn ephemeral_calm_requires_coordination_and_calm_is_monotone_are_mutex_over_all() {
10879 // Absent classification.
10880 let eph = empty_ephemeral();
10881 assert!(
10882 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
10883 "None-classification: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
10884 );
10885 // Authored classification.
10886 for populated in CalmClassification::ALL {
10887 let mut classification = Classification::gate_compute();
10888 classification.calm = populated;
10889 let mut eph = empty_ephemeral();
10890 eph.classification = Some(classification);
10891 assert!(
10892 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
10893 "authored calm={populated:?}: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
10894 );
10895 }
10896 }
10897
10898 /// BINARY XOR PARTITION pin — for the absent-classification
10899 /// baseline AND every
10900 /// [`crate::classification::CalmClassification::ALL`] variant,
10901 /// EXACTLY ONE of [`Self::calm_is_monotone`] and
10902 /// [`Self::calm_requires_coordination`] returns `true`. CLOSES
10903 /// the calm-axis MUTEX pin
10904 /// (`calm_requires_coordination ⇒ ¬calm_is_monotone`) into the
10905 /// FULL binary XOR partition contract on the ephemeral surface
10906 /// — the resolver-hop peer of the parent-composed
10907 /// `classification_calm_probes_form_binary_xor_partition_over_all`
10908 /// test. Binary counterpart of the ternary XOR partitions sealed
10909 /// on the sibling `point_type` and `substrate` axes by
10910 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10911 /// and
10912 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
10913 /// Guarantees the absent-classification case lands in the
10914 /// monotone bucket (`gate_compute` → CalmClassification::Monotone
10915 /// → is_monotone = true), so every unadorned `(defephemeral …)`
10916 /// audits under a definite non-empty CALM bucket.
10917 #[test]
10918 fn ephemeral_calm_probes_form_binary_xor_partition_over_all() {
10919 // Absent classification.
10920 let eph = empty_ephemeral();
10921 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
10922 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10923 assert_eq!(
10924 hits, 1,
10925 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10926 );
10927 // Authored classification.
10928 for populated in CalmClassification::ALL {
10929 let mut classification = Classification::gate_compute();
10930 classification.calm = populated;
10931 let mut eph = empty_ephemeral();
10932 eph.classification = Some(classification);
10933 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
10934 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10935 assert_eq!(
10936 hits, 1,
10937 "authored calm={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10938 );
10939 }
10940 }
10941
10942 // ── EphemeralSpec::data_is_public pins ───────────────────────────
10943 //
10944 // Fail-before-pass-after granularity: `data_is_public` did not
10945 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10946 // the "is this ephemeral spec's dataset publicly distributable?"
10947 // question went through the antisymmetric
10948 // `!self.data_is_restricted()` or through
10949 // `.resolved_classification().data_classification.is_public()`.
10950 // Post-lift the THIRTEENTH derived-nullary-boolean peer on the
10951 // ephemeral surface (THIRD on the data axis, closing that axis
10952 // into a binary XOR partition on this surface) routes through the
10953 // SAME [`Self::resolved_classification`] resolver + the sibling
10954 // substrate primitive
10955 // [`crate::classification::Classification::data_is_public`], so
10956 // the two-surface parity contract holds by construction, AND the
10957 // two-way public/restricted split on this surface CLOSES the
10958 // data axis into the FULL binary XOR partition contract via
10959 // `ephemeral_data_probes_form_binary_xor_partition_over_all`.
10960
10961 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10962 /// [`Classification`] carries a specific
10963 /// [`crate::classification::DataClassification`] variant answers
10964 /// [`Self::data_is_public`] matching the closed set's own
10965 /// [`crate::classification::DataClassification::is_public`] truth
10966 /// table. Sweep
10967 /// [`crate::classification::DataClassification::ALL`] so a
10968 /// regression that (a) hard-coded the body to a fixed answer,
10969 /// (b) inverted the projection, or (c) crossed the wires with
10970 /// the sibling
10971 /// [`crate::classification::DataClassification::is_restricted`]
10972 /// projection fails HERE at the substrate primitive before
10973 /// drifting through the `public-data` fixed tag or the peer
10974 /// point surface.
10975 #[test]
10976 fn data_is_public_returns_data_projection_per_kind() {
10977 for populated in DataClassification::ALL {
10978 let mut classification = Classification::gate_compute();
10979 classification.data_classification = populated;
10980 let mut spec = empty_ephemeral();
10981 spec.classification = Some(classification);
10982 assert_eq!(
10983 spec.data_is_public(),
10984 populated.is_public(),
10985 "authored data_classification={populated:?}: data_is_public() drift",
10986 );
10987 }
10988 }
10989
10990 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10991 /// with `classification: None` routes through the
10992 /// [`Self::resolved_classification`] resolver's substrate default
10993 /// [`Classification::gate_compute`], which carries
10994 /// [`crate::classification::DataClassification::default = Internal`]
10995 /// via `#[default]`, and
10996 /// [`crate::classification::DataClassification::Internal::is_public`]
10997 /// projects `false`, so [`Self::data_is_public`] returns `false`.
10998 /// Pins the resolver's default-arm short-circuit through TWO
10999 /// layers of `Default` ([`Classification::gate_compute`] →
11000 /// [`crate::classification::DataClassification::default`])
11001 /// reaching this derived-nullary predicate. Mirror-inverted from
11002 /// the sibling
11003 /// `data_is_restricted_probes_true_on_absent_classification`
11004 /// (both walk the SAME defaulted `data_classification` field, so
11005 /// `is_restricted = true` ⇒ `is_public = false` on the closed
11006 /// set's disjoint XOR partition). Guarantees every unadorned
11007 /// `(defephemeral …)` audits under the access-controlled default
11008 /// rather than silently promoting an unadorned dataset onto the
11009 /// freely-distributable path.
11010 #[test]
11011 fn data_is_public_probes_false_on_absent_classification() {
11012 let spec = empty_ephemeral();
11013 assert!(spec.classification.is_none());
11014 assert!(
11015 !spec.data_is_public(),
11016 "absent classification (defaults to gate_compute, data_classification=Internal → is_public=false)",
11017 );
11018 }
11019
11020 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11021 /// identically through [`Self::data_is_public`] AND through
11022 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_public()`
11023 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11024 /// classification, `Some(_)` classification on every
11025 /// [`crate::classification::DataClassification::ALL`] variant) so
11026 /// a future regression on either side of the resolver fails HERE
11027 /// at the parity boundary. Byte-for-byte peer of
11028 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
11029 /// on the SAME closed-set axis via the antisymmetric projection.
11030 #[test]
11031 fn data_is_public_matches_point_peer_through_lowered_classification() {
11032 // Absent classification.
11033 let eph = empty_ephemeral();
11034 let lowered: ProcessSpec = eph.clone().into();
11035 assert_eq!(
11036 eph.data_is_public(),
11037 lowered.classification.data_is_public(),
11038 "None-classification parity drift",
11039 );
11040 // Authored classification.
11041 for populated in DataClassification::ALL {
11042 let mut classification = Classification::gate_compute();
11043 classification.data_classification = populated;
11044 let mut eph = empty_ephemeral();
11045 eph.classification = Some(classification);
11046 let lowered: ProcessSpec = eph.clone().into();
11047 assert_eq!(
11048 eph.data_is_public(),
11049 lowered.classification.data_is_public(),
11050 "authored data_classification={populated:?}: parity drift",
11051 );
11052 }
11053 }
11054
11055 /// MUTEX pin — [`Self::data_is_regulated`] AND
11056 /// [`Self::data_is_public`] are NEVER simultaneously true for ANY
11057 /// [`EphemeralSpec`] (authored or defaulted). FIRST ephemeral-
11058 /// surface data-axis antisymmetric MUTEX pin against the
11059 /// positive-distribution framing: sealed on the closed set by
11060 /// `data_classification_regulated_implies_not_public` and lifted
11061 /// through the resolver hop as a substrate-wide contract on this
11062 /// surface.
11063 #[test]
11064 fn ephemeral_data_is_regulated_and_data_is_public_are_mutex_over_all() {
11065 // Absent classification.
11066 let eph = empty_ephemeral();
11067 assert!(
11068 !(eph.data_is_regulated() && eph.data_is_public()),
11069 "None-classification: data_is_regulated AND data_is_public both true (mutex violated)",
11070 );
11071 // Authored classification.
11072 for populated in DataClassification::ALL {
11073 let mut classification = Classification::gate_compute();
11074 classification.data_classification = populated;
11075 let mut eph = empty_ephemeral();
11076 eph.classification = Some(classification);
11077 assert!(
11078 !(eph.data_is_regulated() && eph.data_is_public()),
11079 "authored data_classification={populated:?}: data_is_regulated AND data_is_public both true (mutex violated)",
11080 );
11081 }
11082 }
11083
11084 /// BINARY XOR PARTITION pin — for the absent-classification
11085 /// baseline AND every
11086 /// [`crate::classification::DataClassification::ALL`] variant,
11087 /// EXACTLY ONE of [`Self::data_is_public`] and
11088 /// [`Self::data_is_restricted`] returns `true`. CLOSES the data-
11089 /// axis MUTEX pin (`data_is_regulated ⇒ ¬data_is_public`) into
11090 /// the FULL binary XOR partition contract on the ephemeral
11091 /// surface — the resolver-hop peer of the parent-composed
11092 /// `classification_data_probes_form_binary_xor_partition_over_all`
11093 /// test. Binary counterpart of the ternary XOR partitions sealed
11094 /// on the sibling `point_type` and `substrate` axes by
11095 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11096 /// and
11097 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
11098 /// Guarantees the absent-classification case lands in the
11099 /// access-controlled bucket (`gate_compute` →
11100 /// DataClassification::Internal → is_public = false,
11101 /// is_restricted = true), so every unadorned `(defephemeral …)`
11102 /// audits under a definite non-empty distribution bucket.
11103 #[test]
11104 fn ephemeral_data_probes_form_binary_xor_partition_over_all() {
11105 // Absent classification.
11106 let eph = empty_ephemeral();
11107 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
11108 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11109 assert_eq!(
11110 hits, 1,
11111 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11112 );
11113 // Authored classification.
11114 for populated in DataClassification::ALL {
11115 let mut classification = Classification::gate_compute();
11116 classification.data_classification = populated;
11117 let mut eph = empty_ephemeral();
11118 eph.classification = Some(classification);
11119 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
11120 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11121 assert_eq!(
11122 hits, 1,
11123 "authored data_classification={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11124 );
11125 }
11126 }
11127
11128 // ── EphemeralSpec::direction_prefers_lower pins ─────────────────
11129 //
11130 // Fail-before-pass-after granularity: `direction_prefers_lower`
11131 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
11132 // walking the "does this ephemeral spec's rate-window evaluator
11133 // treat decreasing values as improvement?" question went through
11134 // `.resolved_classification().horizon.direction.unwrap_or_default().prefers_lower()`.
11135 // Post-lift the FOURTEENTH derived-nullary-boolean peer on the
11136 // ephemeral surface (FIRST on the optimization-direction axis,
11137 // opening the SIXTH classification axis into the fixed-tag algebra)
11138 // routes through the SAME [`Self::resolved_classification`] resolver
11139 // + the sibling substrate primitive
11140 // [`crate::classification::Classification::direction_prefers_lower`],
11141 // so the two-surface parity contract holds by construction.
11142
11143 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11144 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
11145 /// answers [`Self::direction_prefers_lower`] matching the closed
11146 /// set's own
11147 /// [`crate::classification::OptimizationDirection::prefers_lower`]
11148 /// truth table. Sweep
11149 /// [`crate::classification::OptimizationDirection::ALL`] so a
11150 /// regression that (a) hard-coded the body to a fixed answer,
11151 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
11152 /// hop, or (d) crossed the wires with a sibling classification-axis
11153 /// probe fails HERE at the substrate primitive before drifting
11154 /// through the `prefers-lower-direction` fixed tag or the peer
11155 /// point surface.
11156 #[test]
11157 fn direction_prefers_lower_returns_direction_projection_per_kind() {
11158 for populated in OptimizationDirection::ALL {
11159 let mut classification = Classification::gate_compute();
11160 classification.horizon.direction = Some(populated);
11161 let mut spec = empty_ephemeral();
11162 spec.classification = Some(classification);
11163 assert_eq!(
11164 spec.direction_prefers_lower(),
11165 populated.prefers_lower(),
11166 "authored horizon.direction={populated:?}: direction_prefers_lower() drift",
11167 );
11168 }
11169 }
11170
11171 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11172 /// with `classification: None` routes through the
11173 /// [`Self::resolved_classification`] resolver's substrate default
11174 /// [`Classification::gate_compute`], which carries
11175 /// `horizon: Horizon::default()` whose `direction` field is `None`,
11176 /// so `unwrap_or_default()` defaults to
11177 /// [`crate::classification::OptimizationDirection::Minimize`] via
11178 /// `#[default]`, and `Minimize.prefers_lower()` projects `true`,
11179 /// so [`Self::direction_prefers_lower`] returns `true`. Pins the
11180 /// resolver's default-arm short-circuit through THREE layers of
11181 /// `Default` ([`Classification::gate_compute`] →
11182 /// [`crate::classification::Horizon::default`] with `direction: None`
11183 /// → [`crate::classification::OptimizationDirection::default =
11184 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
11185 /// every unadorned `(defephemeral …)` reads under the lower-is-
11186 /// better polarity default (safe under the asymptotic-health
11187 /// rate-window evaluator convention: an operator must deliberately
11188 /// opt into Maximize polarity).
11189 #[test]
11190 fn direction_prefers_lower_probes_true_on_absent_classification() {
11191 let spec = empty_ephemeral();
11192 assert!(spec.classification.is_none());
11193 assert!(
11194 spec.direction_prefers_lower(),
11195 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_lower=true)",
11196 );
11197 }
11198
11199 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11200 /// identically through [`Self::direction_prefers_lower`] AND through
11201 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_lower()`
11202 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11203 /// classification, `Some(_)` classification on every
11204 /// [`crate::classification::OptimizationDirection::ALL`] variant) so
11205 /// a future regression on either side of the resolver fails HERE
11206 /// at the parity boundary. Byte-for-byte peer of
11207 /// `calm_is_monotone_matches_point_peer_through_lowered_classification`
11208 /// on the analog closed-set axis via the same resolver-hop shape.
11209 #[test]
11210 fn direction_prefers_lower_matches_point_peer_through_lowered_classification() {
11211 // Absent classification.
11212 let eph = empty_ephemeral();
11213 let lowered: ProcessSpec = eph.clone().into();
11214 assert_eq!(
11215 eph.direction_prefers_lower(),
11216 lowered.classification.direction_prefers_lower(),
11217 "None-classification parity drift",
11218 );
11219 // Authored classification.
11220 for populated in OptimizationDirection::ALL {
11221 let mut classification = Classification::gate_compute();
11222 classification.horizon.direction = Some(populated);
11223 let mut eph = empty_ephemeral();
11224 eph.classification = Some(classification);
11225 let lowered: ProcessSpec = eph.clone().into();
11226 assert_eq!(
11227 eph.direction_prefers_lower(),
11228 lowered.classification.direction_prefers_lower(),
11229 "authored horizon.direction={populated:?}: parity drift",
11230 );
11231 }
11232 }
11233
11234 // ── EphemeralSpec::direction_prefers_higher pins ────────────────
11235 //
11236 // Fail-before-pass-after granularity: `direction_prefers_higher`
11237 // did not exist pre-lift on `impl EphemeralSpec` — the positive
11238 // higher-is-better framing peer of
11239 // [`Self::direction_prefers_lower`] had no ephemeral-surface
11240 // substrate owner. Post-lift the FIFTEENTH derived-nullary-boolean
11241 // peer on the ephemeral surface (SECOND on the optimization-
11242 // direction axis, CLOSING the SIXTH classification axis into a
11243 // binary XOR partition on this surface) routes through the SAME
11244 // [`Self::resolved_classification`] resolver + the sibling
11245 // substrate primitive
11246 // [`crate::classification::Classification::direction_prefers_higher`],
11247 // so the two-surface parity contract holds by construction, AND
11248 // the two-way lower/higher split on this surface CLOSES the
11249 // optimization-direction axis into the FULL binary XOR partition
11250 // contract via
11251 // `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
11252
11253 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11254 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
11255 /// answers [`Self::direction_prefers_higher`] matching the closed
11256 /// set's own
11257 /// [`crate::classification::OptimizationDirection::prefers_higher`]
11258 /// truth table. Sweep
11259 /// [`crate::classification::OptimizationDirection::ALL`] so a
11260 /// regression that (a) hard-coded the body to a fixed answer,
11261 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
11262 /// hop, or (d) crossed the wires with a sibling classification-
11263 /// axis probe fails HERE at the substrate primitive before
11264 /// drifting through the `prefers-higher-direction` fixed tag or
11265 /// the peer point surface.
11266 #[test]
11267 fn direction_prefers_higher_returns_direction_projection_per_kind() {
11268 for populated in OptimizationDirection::ALL {
11269 let mut classification = Classification::gate_compute();
11270 classification.horizon.direction = Some(populated);
11271 let mut spec = empty_ephemeral();
11272 spec.classification = Some(classification);
11273 assert_eq!(
11274 spec.direction_prefers_higher(),
11275 populated.prefers_higher(),
11276 "authored horizon.direction={populated:?}: direction_prefers_higher() drift",
11277 );
11278 }
11279 }
11280
11281 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11282 /// with `classification: None` routes through the
11283 /// [`Self::resolved_classification`] resolver's substrate default
11284 /// [`Classification::gate_compute`], which carries
11285 /// `horizon: Horizon::default()` whose `direction` field is `None`,
11286 /// so `unwrap_or_default()` defaults to
11287 /// [`crate::classification::OptimizationDirection::Minimize`] via
11288 /// `#[default]`, and `Minimize.prefers_higher()` projects `false`,
11289 /// so [`Self::direction_prefers_higher`] returns `false`. Pins
11290 /// the resolver's default-arm short-circuit through THREE layers
11291 /// of `Default` ([`Classification::gate_compute`] →
11292 /// [`crate::classification::Horizon::default`] with `direction:
11293 /// None` → [`crate::classification::OptimizationDirection::default =
11294 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
11295 /// every unadorned `(defephemeral …)` reads UNDER the lower-is-
11296 /// better polarity default (safe under the asymptotic-health
11297 /// rate-window evaluator convention: an operator must
11298 /// deliberately opt into Maximize polarity). Mirror-inverted from
11299 /// the sibling `direction_prefers_lower_probes_true_on_absent_classification`
11300 /// baseline on the same resolver walk.
11301 #[test]
11302 fn direction_prefers_higher_probes_false_on_absent_classification() {
11303 let spec = empty_ephemeral();
11304 assert!(spec.classification.is_none());
11305 assert!(
11306 !spec.direction_prefers_higher(),
11307 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_higher=false)",
11308 );
11309 }
11310
11311 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11312 /// identically through [`Self::direction_prefers_higher`] AND
11313 /// through
11314 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_higher()`
11315 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11316 /// classification, `Some(_)` classification on every
11317 /// [`crate::classification::OptimizationDirection::ALL`] variant)
11318 /// so a future regression on either side of the resolver fails
11319 /// HERE at the parity boundary. Byte-for-byte peer of
11320 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
11321 /// on the antisymmetric closed-set arm via the same resolver-hop
11322 /// shape.
11323 #[test]
11324 fn direction_prefers_higher_matches_point_peer_through_lowered_classification() {
11325 // Absent classification.
11326 let eph = empty_ephemeral();
11327 let lowered: ProcessSpec = eph.clone().into();
11328 assert_eq!(
11329 eph.direction_prefers_higher(),
11330 lowered.classification.direction_prefers_higher(),
11331 "None-classification parity drift",
11332 );
11333 // Authored classification.
11334 for populated in OptimizationDirection::ALL {
11335 let mut classification = Classification::gate_compute();
11336 classification.horizon.direction = Some(populated);
11337 let mut eph = empty_ephemeral();
11338 eph.classification = Some(classification);
11339 let lowered: ProcessSpec = eph.clone().into();
11340 assert_eq!(
11341 eph.direction_prefers_higher(),
11342 lowered.classification.direction_prefers_higher(),
11343 "authored horizon.direction={populated:?}: parity drift",
11344 );
11345 }
11346 }
11347
11348 /// BINARY XOR PARTITION pin — for the absent-classification
11349 /// baseline AND every
11350 /// [`crate::classification::OptimizationDirection::ALL`] variant,
11351 /// EXACTLY ONE of [`Self::direction_prefers_lower`] and
11352 /// [`Self::direction_prefers_higher`] returns `true`. CLOSES the
11353 /// optimization-direction axis into the FULL binary XOR partition
11354 /// contract on the ephemeral surface — the resolver-hop peer of
11355 /// the parent-composed
11356 /// `classification_direction_probes_form_binary_xor_partition_over_all`
11357 /// test. Binary counterpart of the ternary XOR partitions sealed
11358 /// on the sibling `point_type` and `substrate` axes by
11359 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11360 /// and
11361 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11362 /// structural twin of the calm/data binary partitions
11363 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all` and
11364 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11365 /// This pin is the SIXTH (and final) classification axis to reach
11366 /// the closed XOR partition landmark on the ephemeral resolver-
11367 /// hop surface — ALL SIX classification axes (horizon, calm,
11368 /// data, point, substrate, optimization-direction) now have
11369 /// their partitions closed on the ephemeral surface at this
11370 /// corner. Guarantees the absent-classification case lands in
11371 /// the definite lower-is-better bucket (`gate_compute` →
11372 /// Horizon::default → direction: None →
11373 /// OptimizationDirection::default = Minimize → prefers_lower =
11374 /// true, prefers_higher = false), so every unadorned
11375 /// `(defephemeral …)` audits under a definite non-empty polarity
11376 /// bucket.
11377 #[test]
11378 fn ephemeral_direction_probes_form_binary_xor_partition_over_all() {
11379 // Absent classification.
11380 let eph = empty_ephemeral();
11381 let buckets = [
11382 eph.direction_prefers_lower(),
11383 eph.direction_prefers_higher(),
11384 ];
11385 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11386 assert_eq!(
11387 hits, 1,
11388 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11389 );
11390 // Authored classification.
11391 for populated in OptimizationDirection::ALL {
11392 let mut classification = Classification::gate_compute();
11393 classification.horizon.direction = Some(populated);
11394 let mut eph = empty_ephemeral();
11395 eph.classification = Some(classification);
11396 let buckets = [
11397 eph.direction_prefers_lower(),
11398 eph.direction_prefers_higher(),
11399 ];
11400 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11401 assert_eq!(
11402 hits, 1,
11403 "authored horizon.direction={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11404 );
11405 }
11406 }
11407
11408 // ── EphemeralSpec::input_arity_is_one pins ──────────────────────
11409 //
11410 // Fail-before-pass-after granularity: `input_arity_is_one` did not
11411 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11412 // the "does this ephemeral spec's DAG-composition input port
11413 // accept a single upstream edge?" question went through
11414 // `.resolved_classification().point_type.input_arity().is_one()`.
11415 // Post-lift the SIXTEENTH derived-nullary-boolean peer on the
11416 // ephemeral surface (FIRST on the input-arity axis, opening the
11417 // SEVENTH classification axis into the fixed-tag algebra + the
11418 // derived-typed-projection stratum on this surface for the first
11419 // time) routes through the SAME [`Self::resolved_classification`]
11420 // resolver + the sibling substrate primitive
11421 // [`crate::classification::Classification::input_arity_is_one`],
11422 // so the two-surface parity contract holds by construction.
11423
11424 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11425 /// [`Classification`] carries `point_type: kind` answers
11426 /// [`Self::input_arity_is_one`] matching the closed set's own
11427 /// [`crate::classification::ConvergencePointType::input_arity`]
11428 /// truth table projected through [`Arity::is_one`]. Sweep
11429 /// [`crate::classification::ConvergencePointType::ALL`] so a
11430 /// regression that (a) hard-coded the body to a fixed answer,
11431 /// (b) inverted the projection, (c) dropped the resolver hop, or
11432 /// (d) crossed the wires with the sibling `output_arity`
11433 /// projection (which disagrees on six of eight variants) fails
11434 /// HERE at the substrate primitive before drifting through the
11435 /// future `single-input-arity` fixed tag or the peer point
11436 /// surface.
11437 #[test]
11438 fn input_arity_is_one_returns_input_arity_projection_per_kind() {
11439 for populated in ConvergencePointType::ALL {
11440 let mut classification = Classification::gate_compute();
11441 classification.point_type = populated;
11442 let mut spec = empty_ephemeral();
11443 spec.classification = Some(classification);
11444 assert_eq!(
11445 spec.input_arity_is_one(),
11446 populated.input_arity().is_one(),
11447 "authored point_type={populated:?}: input_arity_is_one() drift",
11448 );
11449 }
11450 }
11451
11452 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11453 /// with `classification: None` routes through the
11454 /// [`Self::resolved_classification`] resolver's substrate default
11455 /// [`Classification::gate_compute`], which carries `point_type:
11456 /// Gate` and `Gate.input_arity() = Many`, so
11457 /// [`Self::input_arity_is_one`] returns `false`. Pins the
11458 /// resolver's default-arm short-circuit reaching this derived-
11459 /// nullary predicate — every unadorned `(defephemeral …)` lands
11460 /// in the multi-input bucket under the substrate default. Mirror-
11461 /// inverted from the sibling `input_arity_is_many` baseline on
11462 /// the same resolver walk (the XOR partition forces exactly one
11463 /// bucket per baseline).
11464 #[test]
11465 fn input_arity_is_one_probes_false_on_absent_classification() {
11466 let spec = empty_ephemeral();
11467 assert!(spec.classification.is_none());
11468 assert!(
11469 !spec.input_arity_is_one(),
11470 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_one=false)",
11471 );
11472 }
11473
11474 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11475 /// identically through [`Self::input_arity_is_one`] AND through
11476 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_one()`
11477 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11478 /// classification, `Some(_)` classification on every
11479 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11480 /// so a future regression on either side of the resolver fails
11481 /// HERE at the parity boundary. Byte-for-byte peer of
11482 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
11483 /// on the same resolver-hop shape.
11484 #[test]
11485 fn input_arity_is_one_matches_point_peer_through_lowered_classification() {
11486 // Absent classification.
11487 let eph = empty_ephemeral();
11488 let lowered: ProcessSpec = eph.clone().into();
11489 assert_eq!(
11490 eph.input_arity_is_one(),
11491 lowered.classification.input_arity_is_one(),
11492 "None-classification parity drift",
11493 );
11494 // Authored classification.
11495 for populated in ConvergencePointType::ALL {
11496 let mut classification = Classification::gate_compute();
11497 classification.point_type = populated;
11498 let mut eph = empty_ephemeral();
11499 eph.classification = Some(classification);
11500 let lowered: ProcessSpec = eph.clone().into();
11501 assert_eq!(
11502 eph.input_arity_is_one(),
11503 lowered.classification.input_arity_is_one(),
11504 "authored point_type={populated:?}: parity drift",
11505 );
11506 }
11507 }
11508
11509 // ── EphemeralSpec::input_arity_is_many pins ─────────────────────
11510 //
11511 // Fail-before-pass-after granularity: `input_arity_is_many` did
11512 // not exist pre-lift on `impl EphemeralSpec` — the multi-input
11513 // framing peer of [`Self::input_arity_is_one`] had no ephemeral-
11514 // surface substrate owner. Post-lift the SEVENTEENTH derived-
11515 // nullary-boolean peer on the ephemeral surface (SECOND on the
11516 // input-arity axis, CLOSING the SEVENTH classification axis into
11517 // a binary XOR partition on this surface) routes through the SAME
11518 // [`Self::resolved_classification`] resolver + the sibling
11519 // substrate primitive
11520 // [`crate::classification::Classification::input_arity_is_many`],
11521 // so the two-surface parity contract holds by construction, AND
11522 // the two-way single/many split on this surface CLOSES the
11523 // input-arity axis into the FULL binary XOR partition contract
11524 // via `ephemeral_input_arity_probes_form_binary_xor_partition_over_all`.
11525
11526 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11527 /// [`Classification`] carries `point_type: kind` answers
11528 /// [`Self::input_arity_is_many`] matching the closed set's own
11529 /// [`crate::classification::ConvergencePointType::input_arity`]
11530 /// truth table projected through [`Arity::is_many`]. Sweep
11531 /// [`crate::classification::ConvergencePointType::ALL`] so a
11532 /// regression that (a) hard-coded the body to a fixed answer,
11533 /// (b) inverted the projection, (c) dropped the resolver hop, or
11534 /// (d) crossed the wires with the sibling `output_arity`
11535 /// projection fails HERE at the substrate primitive before
11536 /// drifting through the future `multi-input-arity` fixed tag or
11537 /// the peer point surface.
11538 #[test]
11539 fn input_arity_is_many_returns_input_arity_projection_per_kind() {
11540 for populated in ConvergencePointType::ALL {
11541 let mut classification = Classification::gate_compute();
11542 classification.point_type = populated;
11543 let mut spec = empty_ephemeral();
11544 spec.classification = Some(classification);
11545 assert_eq!(
11546 spec.input_arity_is_many(),
11547 populated.input_arity().is_many(),
11548 "authored point_type={populated:?}: input_arity_is_many() drift",
11549 );
11550 }
11551 }
11552
11553 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11554 /// with `classification: None` routes through the
11555 /// [`Self::resolved_classification`] resolver's substrate default
11556 /// [`Classification::gate_compute`], which carries `point_type:
11557 /// Gate` and `Gate.input_arity() = Many`, so
11558 /// [`Self::input_arity_is_many`] returns `true`. Pins the
11559 /// resolver's default-arm short-circuit reaching this derived-
11560 /// nullary predicate — every unadorned `(defephemeral …)` lands
11561 /// in the multi-input bucket under the substrate default. Mirror-
11562 /// inverted from the sibling `input_arity_is_one` baseline on
11563 /// the same resolver walk (the XOR partition forces exactly one
11564 /// bucket per baseline).
11565 #[test]
11566 fn input_arity_is_many_probes_true_on_absent_classification() {
11567 let spec = empty_ephemeral();
11568 assert!(spec.classification.is_none());
11569 assert!(
11570 spec.input_arity_is_many(),
11571 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_many=true)",
11572 );
11573 }
11574
11575 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11576 /// identically through [`Self::input_arity_is_many`] AND through
11577 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_many()`
11578 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11579 /// classification, `Some(_)` classification on every
11580 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11581 /// so a future regression on either side of the resolver fails
11582 /// HERE at the parity boundary. Byte-for-byte peer of
11583 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
11584 /// on the antisymmetric closed-set arm via the same resolver-hop
11585 /// shape.
11586 #[test]
11587 fn input_arity_is_many_matches_point_peer_through_lowered_classification() {
11588 // Absent classification.
11589 let eph = empty_ephemeral();
11590 let lowered: ProcessSpec = eph.clone().into();
11591 assert_eq!(
11592 eph.input_arity_is_many(),
11593 lowered.classification.input_arity_is_many(),
11594 "None-classification parity drift",
11595 );
11596 // Authored classification.
11597 for populated in ConvergencePointType::ALL {
11598 let mut classification = Classification::gate_compute();
11599 classification.point_type = populated;
11600 let mut eph = empty_ephemeral();
11601 eph.classification = Some(classification);
11602 let lowered: ProcessSpec = eph.clone().into();
11603 assert_eq!(
11604 eph.input_arity_is_many(),
11605 lowered.classification.input_arity_is_many(),
11606 "authored point_type={populated:?}: parity drift",
11607 );
11608 }
11609 }
11610
11611 /// BINARY XOR PARTITION pin — for the absent-classification
11612 /// baseline AND every
11613 /// [`crate::classification::ConvergencePointType::ALL`] variant,
11614 /// EXACTLY ONE of [`Self::input_arity_is_one`] and
11615 /// [`Self::input_arity_is_many`] returns `true`. CLOSES the
11616 /// input-arity axis into the FULL binary XOR partition contract
11617 /// on the ephemeral surface — the resolver-hop peer of the
11618 /// parent-composed
11619 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`
11620 /// test. Binary counterpart of the ternary XOR partitions sealed
11621 /// on the sibling `point_type` and `substrate` axes by
11622 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11623 /// and
11624 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11625 /// structural twin of the calm/data/direction binary partitions
11626 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
11627 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`,
11628 /// and
11629 /// `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
11630 /// This pin is the SEVENTH classification axis to reach the
11631 /// closed XOR partition landmark on the ephemeral resolver-hop
11632 /// surface — the FIRST closed axis on the derived-typed-
11633 /// projection stratum of this surface, opening the stratum beyond
11634 /// the six stored classification slots. Guarantees the absent-
11635 /// classification case lands in the definite multi-input bucket
11636 /// (`gate_compute` → point_type=Gate → input_arity=Many →
11637 /// is_one=false, is_many=true), so every unadorned
11638 /// `(defephemeral …)` audits under a definite non-empty input-
11639 /// arity bucket.
11640 #[test]
11641 fn ephemeral_input_arity_probes_form_binary_xor_partition_over_all() {
11642 // Absent classification.
11643 let eph = empty_ephemeral();
11644 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
11645 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11646 assert_eq!(
11647 hits, 1,
11648 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11649 );
11650 // Authored classification.
11651 for populated in ConvergencePointType::ALL {
11652 let mut classification = Classification::gate_compute();
11653 classification.point_type = populated;
11654 let mut eph = empty_ephemeral();
11655 eph.classification = Some(classification);
11656 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
11657 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11658 assert_eq!(
11659 hits, 1,
11660 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11661 );
11662 }
11663 }
11664
11665 // ── EphemeralSpec::output_arity_is_one pins ─────────────────────
11666 //
11667 // Fail-before-pass-after granularity: `output_arity_is_one` did not
11668 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11669 // the "does this ephemeral spec's DAG-composition output port emit
11670 // to a single downstream edge?" question went through
11671 // `.resolved_classification().point_type.output_arity().is_one()`.
11672 // Post-lift the EIGHTEENTH derived-nullary-boolean peer on the
11673 // ephemeral surface (FIRST on the output-arity axis, opening the
11674 // EIGHTH classification axis into the fixed-tag algebra + the
11675 // SECOND peer on the derived-typed-projection stratum after
11676 // [`Self::input_arity_is_one`]) routes through the SAME
11677 // [`Self::resolved_classification`] resolver + the sibling
11678 // substrate primitive
11679 // [`crate::classification::Classification::output_arity_is_one`],
11680 // so the two-surface parity contract holds by construction.
11681
11682 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11683 /// [`Classification`] carries `point_type: kind` answers
11684 /// [`Self::output_arity_is_one`] matching the closed set's own
11685 /// [`crate::classification::ConvergencePointType::output_arity`]
11686 /// truth table projected through [`Arity::is_one`]. Sweep
11687 /// [`crate::classification::ConvergencePointType::ALL`] so a
11688 /// regression that (a) hard-coded the body to a fixed answer,
11689 /// (b) inverted the projection, (c) dropped the resolver hop, or
11690 /// (d) crossed the wires with the sibling `input_arity`
11691 /// projection (which disagrees on six of eight variants) fails
11692 /// HERE at the substrate primitive before drifting through the
11693 /// future `single-output-arity` fixed tag or the peer point
11694 /// surface.
11695 #[test]
11696 fn output_arity_is_one_returns_output_arity_projection_per_kind() {
11697 for populated in ConvergencePointType::ALL {
11698 let mut classification = Classification::gate_compute();
11699 classification.point_type = populated;
11700 let mut spec = empty_ephemeral();
11701 spec.classification = Some(classification);
11702 assert_eq!(
11703 spec.output_arity_is_one(),
11704 populated.output_arity().is_one(),
11705 "authored point_type={populated:?}: output_arity_is_one() drift",
11706 );
11707 }
11708 }
11709
11710 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11711 /// with `classification: None` routes through the
11712 /// [`Self::resolved_classification`] resolver's substrate default
11713 /// [`Classification::gate_compute`], which carries `point_type:
11714 /// Gate` and `Gate.output_arity() = One`, so
11715 /// [`Self::output_arity_is_one`] returns `true`. Pins the
11716 /// resolver's default-arm short-circuit reaching this derived-
11717 /// nullary predicate — every unadorned `(defephemeral …)` lands
11718 /// in the single-output bucket under the substrate default.
11719 /// Mirror-inverted from the sibling `output_arity_is_many`
11720 /// baseline on the same resolver walk (the XOR partition forces
11721 /// exactly one bucket per baseline). Note the workspace-baseline
11722 /// answer FLIPS between the input-arity and output-arity axes on
11723 /// the exact same absent-classification baseline: the input-arity
11724 /// sibling `input_arity_is_one` answers `false`, but this
11725 /// output-arity peer answers `true` — direct evidence at the
11726 /// resolver-hop layer that the two axes carve the closed set
11727 /// into structurally different partitions.
11728 #[test]
11729 fn output_arity_is_one_probes_true_on_absent_classification() {
11730 let spec = empty_ephemeral();
11731 assert!(spec.classification.is_none());
11732 assert!(
11733 spec.output_arity_is_one(),
11734 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_one=true)",
11735 );
11736 }
11737
11738 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11739 /// identically through [`Self::output_arity_is_one`] AND through
11740 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_one()`
11741 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11742 /// classification, `Some(_)` classification on every
11743 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11744 /// so a future regression on either side of the resolver fails
11745 /// HERE at the parity boundary. Byte-for-byte peer of
11746 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
11747 /// on the sibling output-arity projection via the same
11748 /// resolver-hop shape.
11749 #[test]
11750 fn output_arity_is_one_matches_point_peer_through_lowered_classification() {
11751 // Absent classification.
11752 let eph = empty_ephemeral();
11753 let lowered: ProcessSpec = eph.clone().into();
11754 assert_eq!(
11755 eph.output_arity_is_one(),
11756 lowered.classification.output_arity_is_one(),
11757 "None-classification parity drift",
11758 );
11759 // Authored classification.
11760 for populated in ConvergencePointType::ALL {
11761 let mut classification = Classification::gate_compute();
11762 classification.point_type = populated;
11763 let mut eph = empty_ephemeral();
11764 eph.classification = Some(classification);
11765 let lowered: ProcessSpec = eph.clone().into();
11766 assert_eq!(
11767 eph.output_arity_is_one(),
11768 lowered.classification.output_arity_is_one(),
11769 "authored point_type={populated:?}: parity drift",
11770 );
11771 }
11772 }
11773
11774 // ── EphemeralSpec::output_arity_is_many pins ────────────────────
11775 //
11776 // Fail-before-pass-after granularity: `output_arity_is_many` did
11777 // not exist pre-lift on `impl EphemeralSpec` — the multi-output
11778 // framing peer of [`Self::output_arity_is_one`] had no ephemeral-
11779 // surface substrate owner. Post-lift the NINETEENTH derived-
11780 // nullary-boolean peer on the ephemeral surface (SECOND on the
11781 // output-arity axis, CLOSING the EIGHTH classification axis into
11782 // a binary XOR partition on this surface) routes through the SAME
11783 // [`Self::resolved_classification`] resolver + the sibling
11784 // substrate primitive
11785 // [`crate::classification::Classification::output_arity_is_many`],
11786 // so the two-surface parity contract holds by construction, AND
11787 // the two-way single/many split on this surface CLOSES the
11788 // output-arity axis into the FULL binary XOR partition contract
11789 // via `ephemeral_output_arity_probes_form_binary_xor_partition_over_all`,
11790 // completing the DAG-composition arity PAIR on the ephemeral
11791 // derived-typed-projection stratum.
11792
11793 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11794 /// [`Classification`] carries `point_type: kind` answers
11795 /// [`Self::output_arity_is_many`] matching the closed set's own
11796 /// [`crate::classification::ConvergencePointType::output_arity`]
11797 /// truth table projected through [`Arity::is_many`]. Sweep
11798 /// [`crate::classification::ConvergencePointType::ALL`] so a
11799 /// regression that (a) hard-coded the body to a fixed answer,
11800 /// (b) inverted the projection, (c) dropped the resolver hop, or
11801 /// (d) crossed the wires with the sibling `input_arity`
11802 /// projection fails HERE at the substrate primitive before
11803 /// drifting through the future `multi-output-arity` fixed tag or
11804 /// the peer point surface.
11805 #[test]
11806 fn output_arity_is_many_returns_output_arity_projection_per_kind() {
11807 for populated in ConvergencePointType::ALL {
11808 let mut classification = Classification::gate_compute();
11809 classification.point_type = populated;
11810 let mut spec = empty_ephemeral();
11811 spec.classification = Some(classification);
11812 assert_eq!(
11813 spec.output_arity_is_many(),
11814 populated.output_arity().is_many(),
11815 "authored point_type={populated:?}: output_arity_is_many() drift",
11816 );
11817 }
11818 }
11819
11820 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11821 /// with `classification: None` routes through the
11822 /// [`Self::resolved_classification`] resolver's substrate default
11823 /// [`Classification::gate_compute`], which carries `point_type:
11824 /// Gate` and `Gate.output_arity() = One`, so
11825 /// [`Self::output_arity_is_many`] returns `false`. Pins the
11826 /// resolver's default-arm short-circuit reaching this derived-
11827 /// nullary predicate — every unadorned `(defephemeral …)` lands
11828 /// in the single-output bucket under the substrate default.
11829 /// Mirror-inverted from the sibling `output_arity_is_one`
11830 /// baseline on the same resolver walk (the XOR partition forces
11831 /// exactly one bucket per baseline).
11832 #[test]
11833 fn output_arity_is_many_probes_false_on_absent_classification() {
11834 let spec = empty_ephemeral();
11835 assert!(spec.classification.is_none());
11836 assert!(
11837 !spec.output_arity_is_many(),
11838 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_many=false)",
11839 );
11840 }
11841
11842 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11843 /// identically through [`Self::output_arity_is_many`] AND through
11844 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_many()`
11845 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11846 /// classification, `Some(_)` classification on every
11847 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11848 /// so a future regression on either side of the resolver fails
11849 /// HERE at the parity boundary. Byte-for-byte peer of
11850 /// `output_arity_is_one_matches_point_peer_through_lowered_classification`
11851 /// on the antisymmetric closed-set arm via the same resolver-hop
11852 /// shape.
11853 #[test]
11854 fn output_arity_is_many_matches_point_peer_through_lowered_classification() {
11855 // Absent classification.
11856 let eph = empty_ephemeral();
11857 let lowered: ProcessSpec = eph.clone().into();
11858 assert_eq!(
11859 eph.output_arity_is_many(),
11860 lowered.classification.output_arity_is_many(),
11861 "None-classification parity drift",
11862 );
11863 // Authored classification.
11864 for populated in ConvergencePointType::ALL {
11865 let mut classification = Classification::gate_compute();
11866 classification.point_type = populated;
11867 let mut eph = empty_ephemeral();
11868 eph.classification = Some(classification);
11869 let lowered: ProcessSpec = eph.clone().into();
11870 assert_eq!(
11871 eph.output_arity_is_many(),
11872 lowered.classification.output_arity_is_many(),
11873 "authored point_type={populated:?}: parity drift",
11874 );
11875 }
11876 }
11877
11878 /// BINARY XOR PARTITION pin — for the absent-classification
11879 /// baseline AND every
11880 /// [`crate::classification::ConvergencePointType::ALL`] variant,
11881 /// EXACTLY ONE of [`Self::output_arity_is_one`] and
11882 /// [`Self::output_arity_is_many`] returns `true`. CLOSES the
11883 /// output-arity axis into the FULL binary XOR partition contract
11884 /// on the ephemeral surface — the resolver-hop peer of the
11885 /// parent-composed
11886 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`
11887 /// test. Binary counterpart of the ternary XOR partitions sealed
11888 /// on the sibling `point_type` and `substrate` axes by
11889 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11890 /// and
11891 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11892 /// structural twin of the calm/data/direction/input-arity binary
11893 /// partitions on this surface. This pin is the EIGHTH
11894 /// classification axis to reach the closed XOR partition landmark
11895 /// on the ephemeral resolver-hop surface — the SECOND closed axis
11896 /// on the derived-typed-projection stratum of this surface,
11897 /// completing the DAG-composition arity PAIR on the ephemeral
11898 /// stratum after the input-arity closure. Guarantees the absent-
11899 /// classification case lands in the definite single-output bucket
11900 /// (`gate_compute` → point_type=Gate → output_arity=One →
11901 /// is_one=true, is_many=false), so every unadorned
11902 /// `(defephemeral …)` audits under a definite non-empty
11903 /// output-arity bucket.
11904 #[test]
11905 fn ephemeral_output_arity_probes_form_binary_xor_partition_over_all() {
11906 // Absent classification.
11907 let eph = empty_ephemeral();
11908 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
11909 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11910 assert_eq!(
11911 hits, 1,
11912 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11913 );
11914 // Authored classification.
11915 for populated in ConvergencePointType::ALL {
11916 let mut classification = Classification::gate_compute();
11917 classification.point_type = populated;
11918 let mut eph = empty_ephemeral();
11919 eph.classification = Some(classification);
11920 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
11921 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11922 assert_eq!(
11923 hits, 1,
11924 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11925 );
11926 }
11927 }
11928
11929 /// BINARY XOR PARTITION pin — for the absent-classification
11930 /// baseline AND every
11931 /// [`crate::classification::HorizonKind::ALL`] variant, EXACTLY
11932 /// ONE of [`Self::horizon_terminates`] and
11933 /// [`Self::horizon_requires_metric_axes`] returns `true`. CLOSES
11934 /// the horizon axis into the FULL binary XOR partition contract
11935 /// on the ephemeral surface — the resolver-hop peer of the
11936 /// parent-composed
11937 /// `classification_horizon_probes_form_binary_xor_partition_over_all`
11938 /// test. Binary counterpart of the ternary XOR partitions sealed
11939 /// on the sibling `point_type` and `substrate` axes by
11940 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11941 /// and
11942 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11943 /// structural twin of the calm/data binary partitions
11944 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`
11945 /// and
11946 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11947 /// This pin is the FIFTH (and final) classification axis to reach
11948 /// the closed XOR partition landmark on the ephemeral resolver-
11949 /// hop surface, sealing every classification axis under the
11950 /// SAME `hits == 1` bucket-array contract. Guarantees the absent-
11951 /// classification case lands in the definite terminating bucket
11952 /// (`gate_compute` → HorizonKind::Bounded → terminates = true,
11953 /// requires_metric_axes = false), so every unadorned
11954 /// `(defephemeral …)` audits under a definite non-empty horizon
11955 /// bucket. Rewritten from the earlier binary-XOR-only form
11956 /// (walked as `a ^ b`) into the canonical bucket-array shape
11957 /// shared with the calm/data partitions.
11958 #[test]
11959 fn ephemeral_horizon_probes_form_binary_xor_partition_over_all() {
11960 // Absent classification.
11961 let eph = empty_ephemeral();
11962 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
11963 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11964 assert_eq!(
11965 hits, 1,
11966 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11967 );
11968 // Authored classification.
11969 for populated in HorizonKind::ALL {
11970 let classification = Classification::gate_compute_with_axis(populated);
11971 let mut eph = empty_ephemeral();
11972 eph.classification = Some(classification);
11973 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
11974 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11975 assert_eq!(
11976 hits, 1,
11977 "authored horizon.kind={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11978 );
11979 }
11980 }
11981
11982 // ── EphemeralSpec::has_routing_form pins ─────────────────────────
11983 //
11984 // Fail-before-pass-after granularity: `has_routing_form` did not
11985 // exist pre-lift on `impl EphemeralSpec` — the point-surface
11986 // `routing-form-<kind>` prefix family in tatara-check routed
11987 // through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`
11988 // inline, so the ephemeral surface had no matching primitive to
11989 // publish the SAME `routing-form-<kind>` prefix family through
11990 // the `strip_and_classify_prefixed_kind` substrate. Post-lift the
11991 // Option-gated derived-scalar-child probe body lives at ONE
11992 // inherent site on [`EphemeralSpec`] and every consumer (this
11993 // module's peer-symmetry tests, tatara-check's ephemeral
11994 // require-tag classifier, any future audit dispatcher walking
11995 // [`RoutingForm::ALL`] over the ephemeral surface) binds through
11996 // the SAME `has_routing_form(kind)` shape.
11997
11998 fn routing_spec(is_stable: bool) -> RoutingSpec {
11999 use crate::routing::{RoutingBackend, RoutingHostname};
12000 RoutingSpec {
12001 hostnames: vec![RoutingHostname::content_hashed("api")],
12002 backend: RoutingBackend::plain("svc", 80),
12003 stable_name_claim: is_stable,
12004 priority: 0,
12005 }
12006 }
12007
12008 /// POPULATED-slot pin — a populated `routing` slot answers `true`
12009 /// exactly for the [`RoutingForm`] variant its
12010 /// [`RoutingSpec::has_form`] derived-scalar arm agrees with, and
12011 /// `false` for every other variant. Sweep the two-boolean × ALL
12012 /// cross so a regression that (a) hard-coded the arm to a single
12013 /// variant, (b) dropped the Option-parent gate (silently reading
12014 /// through `.unwrap_or_default()` on an absent routing slot), or
12015 /// (c) crossed the wires from
12016 /// [`RoutingForm::from_is_stable`] to a fixed variant fails
12017 /// HERE before landing at the operator-facing checks.lisp
12018 /// surface.
12019 #[test]
12020 fn has_routing_form_returns_true_iff_populated_routing_derives_form_per_kind() {
12021 for is_stable in [true, false] {
12022 let populated = RoutingForm::from_is_stable(is_stable);
12023 let mut spec = empty_ephemeral();
12024 spec.routing = Some(routing_spec(is_stable));
12025 for query in RoutingForm::ALL {
12026 let expected = query == populated;
12027 assert_eq!(
12028 spec.has_routing_form(query),
12029 expected,
12030 "ephemeral routing.stable_name_claim={is_stable} (derives {populated:?}): query {query:?} drifted",
12031 );
12032 }
12033 }
12034 }
12035
12036 /// OPTION-PARENT SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
12037 /// `routing` slot is `None` returns `false` for every
12038 /// [`RoutingForm`] variant, INCLUDING the closed set's
12039 /// derived-default [`RoutingForm::Instance`]. Locks the
12040 /// Option-parent silencing contract so a regression that dropped
12041 /// the `spec.routing.as_ref()` gate (silently probing an absent
12042 /// routing slot as if it carried the defaulted `Instance` form)
12043 /// fails HERE. Peer to
12044 /// [`evaluate_point_require_tag_returns_false_on_absent_routing_for_every_routing_form_kind`]
12045 /// on the point surface — the two-surface symmetry means both
12046 /// classifiers publish the SAME Option-parent silencing at ONE
12047 /// substrate site per surface.
12048 #[test]
12049 fn has_routing_form_returns_false_on_absent_routing_for_every_kind() {
12050 let spec = empty_ephemeral();
12051 assert!(spec.routing.is_none());
12052 for kind in RoutingForm::ALL {
12053 assert!(
12054 !spec.has_routing_form(kind),
12055 "absent ephemeral routing must return false for {kind:?}",
12056 );
12057 }
12058 }
12059
12060 /// DEFAULT-ARM SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
12061 /// `routing` slot is a [`RoutingSpec`] with `stable_name_claim`
12062 /// at its `#[serde(default)]` (bool default = `false`) answers
12063 /// `true` on [`RoutingForm::Instance`] and `false` on every other
12064 /// variant WITHOUT the operator naming the routing-form axis on
12065 /// the routing spec. Peer to
12066 /// [`evaluate_point_require_tag_returns_true_on_default_routing_form_for_instance_only`]
12067 /// on the point surface — both surfaces read the derived-child
12068 /// arm through the ONE substrate composer
12069 /// [`RoutingForm::from_is_stable`], so a future normalization at
12070 /// the derivation lands at ONE site and every downstream
12071 /// (routing-form require-tag families on both surfaces,
12072 /// closed-set audit dispatchers) picks it up mechanically.
12073 #[test]
12074 fn has_routing_form_probes_instance_only_on_default_populated_routing() {
12075 let mut spec = empty_ephemeral();
12076 spec.routing = Some(routing_spec(bool::default()));
12077 for kind in RoutingForm::ALL {
12078 let expected = kind == RoutingForm::Instance;
12079 assert_eq!(
12080 spec.has_routing_form(kind),
12081 expected,
12082 "default-populated ephemeral routing (stable_name_claim=false → Instance) baseline: query {kind:?} must be {expected}",
12083 );
12084 }
12085 }
12086
12087 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
12088 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
12089 /// answer identically on every [`RoutingForm`] × `is_stable`
12090 /// combination. Locks the byte-for-byte parity between
12091 /// [`EphemeralSpec::has_routing_form`] (this new primitive) and
12092 /// the point surface's `spec.routing.as_ref().is_some_and(|r|
12093 /// r.has_form(k))` inline projection at the tatara-check dispatch
12094 /// site. A regression that (a) diverged the ephemeral probe from
12095 /// the lowered point probe (e.g., dropped the Option-parent gate
12096 /// on ONE side, crossed the derived-child arm on the OTHER), or
12097 /// (b) diverged the `From<EphemeralSpec>` lowering's
12098 /// `routing: e.routing` copy from byte-for-byte forwarding, fails
12099 /// HERE at the two-surface boundary.
12100 #[test]
12101 fn has_routing_form_matches_point_peer_through_lowered_routing() {
12102 for is_stable in [true, false] {
12103 let mut authored = empty_ephemeral();
12104 authored.routing = Some(routing_spec(is_stable));
12105 let lowered: ProcessSpec = authored.clone().into();
12106 for kind in RoutingForm::ALL {
12107 let ephemeral_answer = authored.has_routing_form(kind);
12108 let point_answer = lowered.routing.as_ref().is_some_and(|r| r.has_form(kind));
12109 assert_eq!(
12110 ephemeral_answer, point_answer,
12111 "two-surface routing-form parity drift: stable_name_claim={is_stable}, kind={kind:?}",
12112 );
12113 }
12114 }
12115 }
12116
12117 // ── EphemeralSpec::has_applicable_exports_at substrate pins ───────
12118 //
12119 // Fail-before-pass-after granularity: `has_applicable_exports_at`
12120 // did not exist pre-lift on `impl EphemeralSpec` — the peer
12121 // `EphemeralLifetime::has_applicable_exports` on the lowered
12122 // `ProcessSpec` surface routed through the compound
12123 // `.iter().any(|e| e.when.fires_on(phase))` chain inline, so the
12124 // sugar surface had no matching primitive to publish an
12125 // `exports-fire-on-<phase>` prefix family through the
12126 // `strip_and_classify_prefixed_kind` substrate. Post-lift the
12127 // compound-`(when, phase) → fires_on(phase)` probe body lives at
12128 // ONE slice-level substrate site (`ExportSpecSliceExt::has_applicable_at`),
12129 // this ephemeral surface routes through it directly, and the
12130 // point surface reaches the same primitive through
12131 // `spec.lifetime.resolved_ephemeral().is_some_and(|e|
12132 // e.exports.has_applicable_at(phase))`.
12133
12134 fn export_at(when: crate::export::ExportTrigger) -> ExportSpec {
12135 use crate::export::{ArtifactSource, ReceiptsSource, StdoutChannel, VectorChannel};
12136 ExportSpec {
12137 source: ArtifactSource {
12138 receipts: Some(ReceiptsSource::default()),
12139 ..ArtifactSource::default()
12140 },
12141 channel: VectorChannel {
12142 stdout: Some(StdoutChannel::default()),
12143 ..VectorChannel::default()
12144 },
12145 when,
12146 experiment_id_override: None,
12147 }
12148 }
12149
12150 /// EMPTY-EXPORTS pin — an ephemeral spec with an empty `exports`
12151 /// vec returns `false` for EVERY [`ProcessPhase`]. Sweep
12152 /// [`ProcessPhase::ALL`] so a new variant added without a matching
12153 /// arm in [`crate::export::ExportTrigger::fires_on`] surfaces at
12154 /// rustc's exhaustiveness gate on the `ALL` literal (arity forced
12155 /// by `[Self; 11]`) rather than as a silent false-positive at
12156 /// every downstream `exports-fire-on-<phase>` ephemeral require-tag
12157 /// callsite.
12158 #[test]
12159 fn has_applicable_exports_at_returns_false_on_empty_exports_for_every_phase() {
12160 let spec = empty_ephemeral();
12161 assert!(spec.exports.is_empty());
12162 for phase in ProcessPhase::ALL {
12163 assert!(
12164 !spec.has_applicable_exports_at(phase),
12165 "empty-exports ephemeral must return false for {phase:?}",
12166 );
12167 }
12168 }
12169
12170 /// PER-TRIGGER × PER-PHASE pin — an ephemeral spec with a single
12171 /// export answers `has_applicable_exports_at` identically to the
12172 /// [`crate::export::ExportTrigger::fires_on`] truth table on that
12173 /// (trigger, phase) pair, for every combination. Sweep the
12174 /// [`crate::export::ExportTrigger::ALL`] × [`ProcessPhase::ALL`]
12175 /// cross so a regression that (a) short-circuited to raw `when ==
12176 /// kind` equality, (b) missed `Always`'s dual-phase coverage, or
12177 /// (c) inverted a non-terminal phase to return `true` fails HERE
12178 /// at the substrate primitive rather than at each downstream
12179 /// `exports-fire-on-<phase>` classifier callsite.
12180 #[test]
12181 fn has_applicable_exports_at_matches_fires_on_truth_table_per_pair() {
12182 for trigger in crate::export::ExportTrigger::ALL {
12183 let mut spec = empty_ephemeral();
12184 spec.exports = vec![export_at(trigger)];
12185 for phase in ProcessPhase::ALL {
12186 let expected = trigger.fires_on(phase);
12187 assert_eq!(
12188 spec.has_applicable_exports_at(phase),
12189 expected,
12190 "ephemeral trigger={trigger:?} phase={phase:?} drifted from fires_on",
12191 );
12192 }
12193 }
12194 }
12195
12196 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
12197 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
12198 /// answer identically on every [`ProcessPhase`] × trigger
12199 /// combination. Locks the byte-for-byte parity between
12200 /// [`EphemeralSpec::has_applicable_exports_at`] (this new primitive)
12201 /// and the point surface's `spec.lifetime.resolved_ephemeral()
12202 /// .is_some_and(|e| e.exports.has_applicable_at(phase))` projection
12203 /// at the tatara-check dispatch site. A regression that (a)
12204 /// diverged the ephemeral probe from the lowered-lifetime probe,
12205 /// (b) diverged the `From<EphemeralSpec>` lowering's
12206 /// `exports: e.exports` copy from byte-for-byte forwarding, fails
12207 /// HERE at the two-surface boundary.
12208 #[test]
12209 fn has_applicable_exports_at_matches_point_peer_through_lowered_exports() {
12210 for trigger in crate::export::ExportTrigger::ALL {
12211 let mut authored = empty_ephemeral();
12212 authored.exports = vec![export_at(trigger)];
12213 let lowered: ProcessSpec = authored.clone().into();
12214 for phase in ProcessPhase::ALL {
12215 let ephemeral_answer = authored.has_applicable_exports_at(phase);
12216 let point_answer = lowered
12217 .lifetime
12218 .resolved_ephemeral()
12219 .is_some_and(|e| e.exports.has_applicable_at(phase));
12220 assert_eq!(
12221 ephemeral_answer, point_answer,
12222 "two-surface exports-fire-on parity drift: trigger={trigger:?}, phase={phase:?}",
12223 );
12224 }
12225 }
12226 }
12227
12228 /// SUBSTRATE-DELEGATION pin (EphemeralSpec saturation-predicate
12229 /// triad) — the three `is_*_kind_saturated` methods on
12230 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
12231 /// [`ConditionSliceExt::is_kind_saturated`] over the two
12232 /// `Vec<Condition>` slots (precondition + postcondition) and
12233 /// compose the union via `ConditionKind::ALL.iter().all(|k|
12234 /// has_condition_kind(*k))`. Two-surface parity pin against
12235 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on the
12236 /// point-domain [`ProcessSpec`] surface — the two struct-level
12237 /// saturation callers compose against the SAME slice-level
12238 /// substrate primitive so a regression at the per-slice `all`
12239 /// short-circuit fails at that primitive's tests rather than as
12240 /// silent drift at either sugar-surface arm.
12241 #[test]
12242 fn is_condition_kind_saturated_triad_delegates_to_slice_is_kind_saturated() {
12243 // Empty ephemeral spec — every arm returns false.
12244 let spec = empty_ephemeral();
12245 assert!(
12246 !spec.is_precondition_kind_saturated(),
12247 "empty ephemeral must return false on is_precondition_kind_saturated",
12248 );
12249 assert!(
12250 !spec.is_postcondition_kind_saturated(),
12251 "empty ephemeral must return false on is_postcondition_kind_saturated",
12252 );
12253 assert!(
12254 !spec.is_condition_kind_saturated(),
12255 "empty ephemeral must return false on is_condition_kind_saturated",
12256 );
12257 assert_eq!(
12258 spec.is_condition_kind_saturated(),
12259 spec.missing_condition_kinds().is_empty(),
12260 "empty is_condition_kind_saturated must equal missing_condition_kinds().is_empty()",
12261 );
12262
12263 // Single-populated per side — sweep ALL × ALL.
12264 for pre_kind in ConditionKind::ALL {
12265 for post_kind in ConditionKind::ALL {
12266 let mut spec = empty_ephemeral();
12267 spec.preconditions.push(cond(pre_kind));
12268 spec.postconditions.push(cond(post_kind));
12269 assert_eq!(
12270 spec.is_precondition_kind_saturated(),
12271 spec.preconditions.is_kind_saturated(),
12272 "EphemeralSpec::is_precondition_kind_saturated must delegate verbatim to \
12273 preconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
12274 );
12275 assert_eq!(
12276 spec.is_postcondition_kind_saturated(),
12277 spec.postconditions.is_kind_saturated(),
12278 "EphemeralSpec::is_postcondition_kind_saturated must delegate verbatim to \
12279 postconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
12280 );
12281 let expected_union = ConditionKind::ALL
12282 .iter()
12283 .all(|k| pre_kind == *k || post_kind == *k);
12284 assert_eq!(
12285 spec.is_condition_kind_saturated(),
12286 expected_union,
12287 "EphemeralSpec::is_condition_kind_saturated must equal all-ALL-covered-by-either-slice \
12288 for pre={pre_kind:?} post={post_kind:?}",
12289 );
12290
12291 // Two-surface parity: lowered ProcessSpec's Boundary
12292 // must agree bit-for-bit with the ephemeral sugar
12293 // triad on every arm.
12294 let lowered: ProcessSpec = spec.clone().into();
12295 assert_eq!(
12296 spec.is_precondition_kind_saturated(),
12297 lowered.boundary.is_precondition_kind_saturated(),
12298 "two-surface is_precondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12299 );
12300 assert_eq!(
12301 spec.is_postcondition_kind_saturated(),
12302 lowered.boundary.is_postcondition_kind_saturated(),
12303 "two-surface is_postcondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12304 );
12305 assert_eq!(
12306 spec.is_condition_kind_saturated(),
12307 lowered.boundary.is_condition_kind_saturated(),
12308 "two-surface is_condition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12309 );
12310 }
12311 }
12312
12313 // Saturated ephemeral — both slices carry every ConditionKind,
12314 // every arm returns true.
12315 let mut spec = empty_ephemeral();
12316 for k in ConditionKind::ALL {
12317 spec.preconditions.push(cond(k));
12318 spec.postconditions.push(cond(k));
12319 }
12320 assert!(
12321 spec.is_precondition_kind_saturated(),
12322 "saturated ephemeral must return true on is_precondition_kind_saturated",
12323 );
12324 assert!(
12325 spec.is_postcondition_kind_saturated(),
12326 "saturated ephemeral must return true on is_postcondition_kind_saturated",
12327 );
12328 assert!(
12329 spec.is_condition_kind_saturated(),
12330 "saturated ephemeral must return true on is_condition_kind_saturated",
12331 );
12332 }
12333
12334 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
12335 /// triad) — the three `has_any_missing_*_condition_kind` methods
12336 /// on [`EphemeralSpec`] delegate to the slice-level substrate
12337 /// primitive
12338 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
12339 /// over the two `Vec<Condition>` slots (precondition +
12340 /// postcondition) and compose the union via
12341 /// `!self.is_condition_kind_saturated()`. Two-surface parity pin
12342 /// against
12343 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
12344 /// the point-domain [`ProcessSpec`] surface — the two struct-level
12345 /// at-least-one halfspace callers compose against the SAME slice-
12346 /// level substrate primitive so a regression at the per-slice
12347 /// `all` short-circuit under negation fails at that primitive's
12348 /// tests rather than as silent drift at either sugar-surface arm.
12349 #[test]
12350 fn has_any_missing_condition_kind_triad_delegates_to_slice_has_any_missing_kind() {
12351 // Empty ephemeral spec — every arm returns true (every kind is
12352 // missing from every slice + from the union).
12353 let spec = empty_ephemeral();
12354 assert!(
12355 spec.has_any_missing_precondition_kind(),
12356 "empty ephemeral must return true on has_any_missing_precondition_kind",
12357 );
12358 assert!(
12359 spec.has_any_missing_postcondition_kind(),
12360 "empty ephemeral must return true on has_any_missing_postcondition_kind",
12361 );
12362 assert!(
12363 spec.has_any_missing_condition_kind(),
12364 "empty ephemeral must return true on has_any_missing_condition_kind",
12365 );
12366 assert_eq!(
12367 spec.has_any_missing_condition_kind(),
12368 !spec.is_condition_kind_saturated(),
12369 "empty has_any_missing_condition_kind must equal !is_condition_kind_saturated()",
12370 );
12371
12372 // Single-populated per side — sweep ALL × ALL, then pin the
12373 // (pre, post, union) triad + two-surface parity against the
12374 // lowered ProcessSpec's Boundary.
12375 for pre_kind in ConditionKind::ALL {
12376 for post_kind in ConditionKind::ALL {
12377 let mut spec = empty_ephemeral();
12378 spec.preconditions.push(cond(pre_kind));
12379 spec.postconditions.push(cond(post_kind));
12380 assert_eq!(
12381 spec.has_any_missing_precondition_kind(),
12382 spec.preconditions.has_any_missing_kind(),
12383 "EphemeralSpec::has_any_missing_precondition_kind must delegate verbatim to \
12384 preconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12385 );
12386 assert_eq!(
12387 spec.has_any_missing_postcondition_kind(),
12388 spec.postconditions.has_any_missing_kind(),
12389 "EphemeralSpec::has_any_missing_postcondition_kind must delegate verbatim to \
12390 postconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12391 );
12392 let expected_union = !ConditionKind::ALL
12393 .iter()
12394 .all(|k| pre_kind == *k || post_kind == *k);
12395 assert_eq!(
12396 spec.has_any_missing_condition_kind(),
12397 expected_union,
12398 "EphemeralSpec::has_any_missing_condition_kind must equal \
12399 !all-ALL-covered-by-either-slice \
12400 for pre={pre_kind:?} post={post_kind:?}",
12401 );
12402
12403 // Two-surface parity: lowered ProcessSpec's Boundary
12404 // must agree bit-for-bit with the ephemeral sugar
12405 // triad on every arm.
12406 let lowered: ProcessSpec = spec.clone().into();
12407 assert_eq!(
12408 spec.has_any_missing_precondition_kind(),
12409 lowered.boundary.has_any_missing_precondition_kind(),
12410 "two-surface has_any_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12411 );
12412 assert_eq!(
12413 spec.has_any_missing_postcondition_kind(),
12414 lowered.boundary.has_any_missing_postcondition_kind(),
12415 "two-surface has_any_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12416 );
12417 assert_eq!(
12418 spec.has_any_missing_condition_kind(),
12419 lowered.boundary.has_any_missing_condition_kind(),
12420 "two-surface has_any_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12421 );
12422 }
12423 }
12424
12425 // Saturated ephemeral — both slices carry every ConditionKind,
12426 // every arm returns false.
12427 let mut spec = empty_ephemeral();
12428 for k in ConditionKind::ALL {
12429 spec.preconditions.push(cond(k));
12430 spec.postconditions.push(cond(k));
12431 }
12432 assert!(
12433 !spec.has_any_missing_precondition_kind(),
12434 "saturated ephemeral must return false on has_any_missing_precondition_kind",
12435 );
12436 assert!(
12437 !spec.has_any_missing_postcondition_kind(),
12438 "saturated ephemeral must return false on has_any_missing_postcondition_kind",
12439 );
12440 assert!(
12441 !spec.has_any_missing_condition_kind(),
12442 "saturated ephemeral must return false on has_any_missing_condition_kind",
12443 );
12444 }
12445
12446 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
12447 /// triad on the closed-set-inversion axis) — the three
12448 /// `has_any_distinct_*_condition_kind` methods on
12449 /// [`EphemeralSpec`] delegate to the slice-level substrate
12450 /// primitive
12451 /// [`crate::boundary::ConditionSliceExt::has_any_distinct_kind`]
12452 /// over the two `Vec<Condition>` slots (precondition +
12453 /// postcondition) and compose the union via a SHORT-CIRCUITING
12454 /// closed-set walk over [`ConditionKind::ALL`] under
12455 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12456 /// against
12457 /// [`crate::boundary::Boundary::has_any_distinct_condition_kind`]
12458 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12459 /// level at-least-one halfspace callers compose against the SAME
12460 /// slice-level substrate primitive so a regression at the per-
12461 /// slice `any` short-circuit fails at that primitive's tests
12462 /// rather than as silent drift at either sugar-surface arm.
12463 #[test]
12464 fn has_any_distinct_condition_kind_triad_delegates_to_slice_has_any_distinct_kind() {
12465 // Empty ephemeral spec — every arm returns false (no kind
12466 // present in either slice).
12467 let spec = empty_ephemeral();
12468 assert!(
12469 !spec.has_any_distinct_precondition_kind(),
12470 "empty ephemeral must return false on has_any_distinct_precondition_kind",
12471 );
12472 assert!(
12473 !spec.has_any_distinct_postcondition_kind(),
12474 "empty ephemeral must return false on has_any_distinct_postcondition_kind",
12475 );
12476 assert!(
12477 !spec.has_any_distinct_condition_kind(),
12478 "empty ephemeral must return false on has_any_distinct_condition_kind",
12479 );
12480
12481 // Single-populated per side — sweep ALL × ALL, then pin the
12482 // (pre, post, union) triad + two-surface parity against the
12483 // lowered ProcessSpec's Boundary.
12484 for pre_kind in ConditionKind::ALL {
12485 for post_kind in ConditionKind::ALL {
12486 let mut spec = empty_ephemeral();
12487 spec.preconditions.push(cond(pre_kind));
12488 spec.postconditions.push(cond(post_kind));
12489 assert_eq!(
12490 spec.has_any_distinct_precondition_kind(),
12491 spec.preconditions.has_any_distinct_kind(),
12492 "EphemeralSpec::has_any_distinct_precondition_kind must delegate verbatim to \
12493 preconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12494 );
12495 assert_eq!(
12496 spec.has_any_distinct_postcondition_kind(),
12497 spec.postconditions.has_any_distinct_kind(),
12498 "EphemeralSpec::has_any_distinct_postcondition_kind must delegate verbatim to \
12499 postconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12500 );
12501 assert!(
12502 spec.has_any_distinct_precondition_kind(),
12503 "single-populated preconditions must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
12504 );
12505 assert!(
12506 spec.has_any_distinct_postcondition_kind(),
12507 "single-populated postconditions must return true on has_any_distinct_postcondition_kind for post={post_kind:?}",
12508 );
12509 assert!(
12510 spec.has_any_distinct_condition_kind(),
12511 "single-populated-per-side must return true on has_any_distinct_condition_kind for pre={pre_kind:?} post={post_kind:?}",
12512 );
12513
12514 // Two-surface parity: lowered ProcessSpec's Boundary
12515 // must agree bit-for-bit with the ephemeral sugar
12516 // triad on every arm.
12517 let lowered: ProcessSpec = spec.clone().into();
12518 assert_eq!(
12519 spec.has_any_distinct_precondition_kind(),
12520 lowered.boundary.has_any_distinct_precondition_kind(),
12521 "two-surface has_any_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12522 );
12523 assert_eq!(
12524 spec.has_any_distinct_postcondition_kind(),
12525 lowered.boundary.has_any_distinct_postcondition_kind(),
12526 "two-surface has_any_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12527 );
12528 assert_eq!(
12529 spec.has_any_distinct_condition_kind(),
12530 lowered.boundary.has_any_distinct_condition_kind(),
12531 "two-surface has_any_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12532 );
12533 }
12534 }
12535
12536 // Single-populated precondition only — precondition arm true,
12537 // postcondition arm false, union true.
12538 for pre_kind in ConditionKind::ALL {
12539 let mut spec = empty_ephemeral();
12540 spec.preconditions.push(cond(pre_kind));
12541 assert!(
12542 spec.has_any_distinct_precondition_kind(),
12543 "pre-only ephemeral must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
12544 );
12545 assert!(
12546 !spec.has_any_distinct_postcondition_kind(),
12547 "pre-only ephemeral must return false on has_any_distinct_postcondition_kind for pre={pre_kind:?}",
12548 );
12549 assert!(
12550 spec.has_any_distinct_condition_kind(),
12551 "pre-only ephemeral must return true on has_any_distinct_condition_kind for pre={pre_kind:?}",
12552 );
12553 }
12554
12555 // Saturated ephemeral — both slices carry every ConditionKind,
12556 // every arm returns true.
12557 let mut spec = empty_ephemeral();
12558 for k in ConditionKind::ALL {
12559 spec.preconditions.push(cond(k));
12560 spec.postconditions.push(cond(k));
12561 }
12562 assert!(
12563 spec.has_any_distinct_precondition_kind(),
12564 "saturated ephemeral must return true on has_any_distinct_precondition_kind",
12565 );
12566 assert!(
12567 spec.has_any_distinct_postcondition_kind(),
12568 "saturated ephemeral must return true on has_any_distinct_postcondition_kind",
12569 );
12570 assert!(
12571 spec.has_any_distinct_condition_kind(),
12572 "saturated ephemeral must return true on has_any_distinct_condition_kind",
12573 );
12574 }
12575
12576 /// SUBSTRATE-DELEGATION pin (EphemeralSpec singleton-coverage
12577 /// triad on the closed-set-inversion axis) — the three
12578 /// `has_unique_distinct_*_condition_kind` methods on
12579 /// [`EphemeralSpec`] delegate to the slice-level substrate
12580 /// primitive
12581 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
12582 /// over the two `Vec<Condition>` slots (precondition +
12583 /// postcondition) and compose the union via a two-step-short-
12584 /// circuit walk over [`ConditionKind::ALL`] under
12585 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12586 /// against
12587 /// [`crate::boundary::Boundary::has_unique_distinct_condition_kind`]
12588 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12589 /// level singleton-coverage callers compose against the SAME
12590 /// slice-level substrate primitive so a regression at the per-
12591 /// slice two-step short-circuit walk fails at that primitive's
12592 /// tests rather than as silent drift at either sugar-surface arm.
12593 #[test]
12594 fn has_unique_distinct_condition_kind_triad_delegates_to_slice_has_unique_distinct_kind() {
12595 // Empty ephemeral spec — every arm returns false (0 distinct,
12596 // not exactly 1).
12597 let spec = empty_ephemeral();
12598 assert!(
12599 !spec.has_unique_distinct_precondition_kind(),
12600 "empty ephemeral must return false on has_unique_distinct_precondition_kind",
12601 );
12602 assert!(
12603 !spec.has_unique_distinct_postcondition_kind(),
12604 "empty ephemeral must return false on has_unique_distinct_postcondition_kind",
12605 );
12606 assert!(
12607 !spec.has_unique_distinct_condition_kind(),
12608 "empty ephemeral must return false on has_unique_distinct_condition_kind",
12609 );
12610 assert_eq!(
12611 spec.has_unique_distinct_condition_kind(),
12612 spec.distinct_condition_kind_count() == 1,
12613 "empty has_unique_distinct_condition_kind must equal (distinct_condition_kind_count() == 1)",
12614 );
12615
12616 // Single-populated per side — sweep ALL × ALL. Every per-
12617 // slice arm returns true; the union returns true iff the two
12618 // populated kinds coincide (union covers exactly one kind).
12619 for pre_kind in ConditionKind::ALL {
12620 for post_kind in ConditionKind::ALL {
12621 let mut spec = empty_ephemeral();
12622 spec.preconditions.push(cond(pre_kind));
12623 spec.postconditions.push(cond(post_kind));
12624 assert_eq!(
12625 spec.has_unique_distinct_precondition_kind(),
12626 spec.preconditions.has_unique_distinct_kind(),
12627 "EphemeralSpec::has_unique_distinct_precondition_kind must delegate verbatim to \
12628 preconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12629 );
12630 assert_eq!(
12631 spec.has_unique_distinct_postcondition_kind(),
12632 spec.postconditions.has_unique_distinct_kind(),
12633 "EphemeralSpec::has_unique_distinct_postcondition_kind must delegate verbatim to \
12634 postconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12635 );
12636 let covered_count = ConditionKind::ALL
12637 .into_iter()
12638 .filter(|k| *k == pre_kind || *k == post_kind)
12639 .count();
12640 let expected_union = covered_count == 1;
12641 assert_eq!(
12642 spec.has_unique_distinct_condition_kind(),
12643 expected_union,
12644 "EphemeralSpec::has_unique_distinct_condition_kind must equal \
12645 (covered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
12646 );
12647
12648 // Two-surface parity: lowered ProcessSpec's Boundary
12649 // must agree bit-for-bit with the ephemeral sugar
12650 // triad on every arm.
12651 let lowered: ProcessSpec = spec.clone().into();
12652 assert_eq!(
12653 spec.has_unique_distinct_precondition_kind(),
12654 lowered.boundary.has_unique_distinct_precondition_kind(),
12655 "two-surface has_unique_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12656 );
12657 assert_eq!(
12658 spec.has_unique_distinct_postcondition_kind(),
12659 lowered.boundary.has_unique_distinct_postcondition_kind(),
12660 "two-surface has_unique_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12661 );
12662 assert_eq!(
12663 spec.has_unique_distinct_condition_kind(),
12664 lowered.boundary.has_unique_distinct_condition_kind(),
12665 "two-surface has_unique_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12666 );
12667 }
12668 }
12669
12670 // Saturated ephemeral — every arm returns false on N ≥ 2 (N
12671 // distinct, not exactly 1).
12672 if ConditionKind::ALL.len() >= 2 {
12673 let mut spec = empty_ephemeral();
12674 for k in ConditionKind::ALL {
12675 spec.preconditions.push(cond(k));
12676 spec.postconditions.push(cond(k));
12677 }
12678 assert!(
12679 !spec.has_unique_distinct_precondition_kind(),
12680 "saturated ephemeral must return false on has_unique_distinct_precondition_kind",
12681 );
12682 assert!(
12683 !spec.has_unique_distinct_postcondition_kind(),
12684 "saturated ephemeral must return false on has_unique_distinct_postcondition_kind",
12685 );
12686 assert!(
12687 !spec.has_unique_distinct_condition_kind(),
12688 "saturated ephemeral must return false on has_unique_distinct_condition_kind",
12689 );
12690 }
12691 }
12692
12693 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
12694 /// triad on the closed-set-inversion axis) — the three
12695 /// `has_multiple_distinct_*_condition_kind` methods on
12696 /// [`EphemeralSpec`] delegate to the slice-level substrate
12697 /// primitive
12698 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
12699 /// over the two `Vec<Condition>` slots (precondition +
12700 /// postcondition) and compose the union via a two-step-short-
12701 /// circuit walk over [`ConditionKind::ALL`] under
12702 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12703 /// against
12704 /// [`crate::boundary::Boundary::has_multiple_distinct_condition_kind`]
12705 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12706 /// level many-distinct callers compose against the SAME slice-
12707 /// level substrate primitive so a regression at the per-slice
12708 /// two-step short-circuit walk fails at that primitive's tests
12709 /// rather than as silent drift at either sugar-surface arm.
12710 #[test]
12711 fn has_multiple_distinct_condition_kind_triad_delegates_to_slice_has_multiple_distinct_kinds() {
12712 // Empty ephemeral spec — every arm returns false (0 distinct,
12713 // not ≥ 2).
12714 let spec = empty_ephemeral();
12715 assert!(
12716 !spec.has_multiple_distinct_precondition_kind(),
12717 "empty ephemeral must return false on has_multiple_distinct_precondition_kind",
12718 );
12719 assert!(
12720 !spec.has_multiple_distinct_postcondition_kind(),
12721 "empty ephemeral must return false on has_multiple_distinct_postcondition_kind",
12722 );
12723 assert!(
12724 !spec.has_multiple_distinct_condition_kind(),
12725 "empty ephemeral must return false on has_multiple_distinct_condition_kind",
12726 );
12727 assert_eq!(
12728 spec.has_multiple_distinct_condition_kind(),
12729 spec.distinct_condition_kind_count() >= 2,
12730 "empty has_multiple_distinct_condition_kind must equal (distinct_condition_kind_count() >= 2)",
12731 );
12732
12733 // Single-populated per side — sweep ALL × ALL. Every per-slice
12734 // arm returns false (1 distinct per slice, not ≥ 2); the
12735 // union returns true iff the two kinds DIFFER (union covers 2
12736 // distinct kinds).
12737 assert!(
12738 ConditionKind::ALL.len() >= 2,
12739 "test assumes ConditionKind::ALL has ≥ 2 variants",
12740 );
12741 for pre_kind in ConditionKind::ALL {
12742 for post_kind in ConditionKind::ALL {
12743 let mut spec = empty_ephemeral();
12744 spec.preconditions.push(cond(pre_kind));
12745 spec.postconditions.push(cond(post_kind));
12746 assert_eq!(
12747 spec.has_multiple_distinct_precondition_kind(),
12748 spec.preconditions.has_multiple_distinct_kinds(),
12749 "EphemeralSpec::has_multiple_distinct_precondition_kind must delegate verbatim to \
12750 preconditions.has_multiple_distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
12751 );
12752 assert_eq!(
12753 spec.has_multiple_distinct_postcondition_kind(),
12754 spec.postconditions.has_multiple_distinct_kinds(),
12755 "EphemeralSpec::has_multiple_distinct_postcondition_kind must delegate verbatim to \
12756 postconditions.has_multiple_distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
12757 );
12758 let covered_count = ConditionKind::ALL
12759 .into_iter()
12760 .filter(|k| *k == pre_kind || *k == post_kind)
12761 .count();
12762 let expected_union = covered_count >= 2;
12763 assert_eq!(
12764 spec.has_multiple_distinct_condition_kind(),
12765 expected_union,
12766 "EphemeralSpec::has_multiple_distinct_condition_kind must equal \
12767 (covered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
12768 );
12769
12770 // Two-surface parity: lowered ProcessSpec's Boundary
12771 // must agree bit-for-bit with the ephemeral sugar
12772 // triad on every arm.
12773 let lowered: ProcessSpec = spec.clone().into();
12774 assert_eq!(
12775 spec.has_multiple_distinct_precondition_kind(),
12776 lowered.boundary.has_multiple_distinct_precondition_kind(),
12777 "two-surface has_multiple_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12778 );
12779 assert_eq!(
12780 spec.has_multiple_distinct_postcondition_kind(),
12781 lowered.boundary.has_multiple_distinct_postcondition_kind(),
12782 "two-surface has_multiple_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12783 );
12784 assert_eq!(
12785 spec.has_multiple_distinct_condition_kind(),
12786 lowered.boundary.has_multiple_distinct_condition_kind(),
12787 "two-surface has_multiple_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12788 );
12789 }
12790 }
12791
12792 // Saturated ephemeral — every arm returns true on N ≥ 2 (N
12793 // distinct, ≥ 2).
12794 let mut spec = empty_ephemeral();
12795 for k in ConditionKind::ALL {
12796 spec.preconditions.push(cond(k));
12797 spec.postconditions.push(cond(k));
12798 }
12799 assert!(
12800 spec.has_multiple_distinct_precondition_kind(),
12801 "saturated ephemeral must return true on has_multiple_distinct_precondition_kind",
12802 );
12803 assert!(
12804 spec.has_multiple_distinct_postcondition_kind(),
12805 "saturated ephemeral must return true on has_multiple_distinct_postcondition_kind",
12806 );
12807 assert!(
12808 spec.has_multiple_distinct_condition_kind(),
12809 "saturated ephemeral must return true on has_multiple_distinct_condition_kind",
12810 );
12811 }
12812
12813 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1" triad
12814 /// on the closed-set-inversion axis) — the three
12815 /// `has_at_most_one_distinct_*_condition_kind` methods on
12816 /// [`EphemeralSpec`] delegate to the slice-level substrate
12817 /// primitive
12818 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
12819 /// over the two `Vec<Condition>` slots (precondition +
12820 /// postcondition) and compose the union via a definitional
12821 /// negation of the many-arm two-step-short-circuit walk over
12822 /// [`ConditionKind::ALL`] under
12823 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12824 /// against
12825 /// [`crate::boundary::Boundary::has_at_most_one_distinct_condition_kind`]
12826 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12827 /// level empty-or-singleton callers compose against the SAME
12828 /// slice-level substrate primitive so a regression at the per-
12829 /// slice "≤ 1" negation fails at that primitive's tests rather
12830 /// than as silent drift at either sugar-surface arm.
12831 #[test]
12832 fn has_at_most_one_distinct_condition_kind_triad_delegates_to_slice_has_at_most_one_distinct_kind(
12833 ) {
12834 // Empty ephemeral spec — every arm returns true (0 distinct,
12835 // ≤ 1).
12836 let spec = empty_ephemeral();
12837 assert!(
12838 spec.has_at_most_one_distinct_precondition_kind(),
12839 "empty ephemeral must return true on has_at_most_one_distinct_precondition_kind",
12840 );
12841 assert!(
12842 spec.has_at_most_one_distinct_postcondition_kind(),
12843 "empty ephemeral must return true on has_at_most_one_distinct_postcondition_kind",
12844 );
12845 assert!(
12846 spec.has_at_most_one_distinct_condition_kind(),
12847 "empty ephemeral must return true on has_at_most_one_distinct_condition_kind",
12848 );
12849 assert_eq!(
12850 spec.has_at_most_one_distinct_condition_kind(),
12851 spec.distinct_condition_kind_count() <= 1,
12852 "empty has_at_most_one_distinct_condition_kind must equal (distinct_condition_kind_count() <= 1)",
12853 );
12854
12855 // Single-populated per side — sweep ALL × ALL. Every per-slice
12856 // arm returns true (1 distinct per slice, ≤ 1); the union
12857 // returns true iff the two kinds COINCIDE (union has 1
12858 // distinct), otherwise the union has 2 distinct and drops to
12859 // false.
12860 assert!(
12861 ConditionKind::ALL.len() >= 2,
12862 "test assumes ConditionKind::ALL has ≥ 2 variants",
12863 );
12864 for pre_kind in ConditionKind::ALL {
12865 for post_kind in ConditionKind::ALL {
12866 let mut spec = empty_ephemeral();
12867 spec.preconditions.push(cond(pre_kind));
12868 spec.postconditions.push(cond(post_kind));
12869 assert_eq!(
12870 spec.has_at_most_one_distinct_precondition_kind(),
12871 spec.preconditions.has_at_most_one_distinct_kind(),
12872 "EphemeralSpec::has_at_most_one_distinct_precondition_kind must delegate verbatim to \
12873 preconditions.has_at_most_one_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12874 );
12875 assert_eq!(
12876 spec.has_at_most_one_distinct_postcondition_kind(),
12877 spec.postconditions.has_at_most_one_distinct_kind(),
12878 "EphemeralSpec::has_at_most_one_distinct_postcondition_kind must delegate verbatim to \
12879 postconditions.has_at_most_one_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12880 );
12881 let covered_count = ConditionKind::ALL
12882 .into_iter()
12883 .filter(|k| *k == pre_kind || *k == post_kind)
12884 .count();
12885 let expected_union = covered_count <= 1;
12886 assert_eq!(
12887 spec.has_at_most_one_distinct_condition_kind(),
12888 expected_union,
12889 "EphemeralSpec::has_at_most_one_distinct_condition_kind must equal \
12890 (covered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
12891 );
12892
12893 // Two-surface parity: lowered ProcessSpec's Boundary
12894 // must agree bit-for-bit with the ephemeral sugar
12895 // triad on every arm.
12896 let lowered: ProcessSpec = spec.clone().into();
12897 assert_eq!(
12898 spec.has_at_most_one_distinct_precondition_kind(),
12899 lowered.boundary.has_at_most_one_distinct_precondition_kind(),
12900 "two-surface has_at_most_one_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12901 );
12902 assert_eq!(
12903 spec.has_at_most_one_distinct_postcondition_kind(),
12904 lowered.boundary.has_at_most_one_distinct_postcondition_kind(),
12905 "two-surface has_at_most_one_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12906 );
12907 assert_eq!(
12908 spec.has_at_most_one_distinct_condition_kind(),
12909 lowered.boundary.has_at_most_one_distinct_condition_kind(),
12910 "two-surface has_at_most_one_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12911 );
12912 }
12913 }
12914
12915 // Saturated ephemeral — every arm returns false on N ≥ 2 (N
12916 // distinct, not ≤ 1).
12917 let mut spec = empty_ephemeral();
12918 for k in ConditionKind::ALL {
12919 spec.preconditions.push(cond(k));
12920 spec.postconditions.push(cond(k));
12921 }
12922 assert!(
12923 !spec.has_at_most_one_distinct_precondition_kind(),
12924 "saturated ephemeral must return false on has_at_most_one_distinct_precondition_kind",
12925 );
12926 assert!(
12927 !spec.has_at_most_one_distinct_postcondition_kind(),
12928 "saturated ephemeral must return false on has_at_most_one_distinct_postcondition_kind",
12929 );
12930 assert!(
12931 !spec.has_at_most_one_distinct_condition_kind(),
12932 "saturated ephemeral must return false on has_at_most_one_distinct_condition_kind",
12933 );
12934 }
12935
12936 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality zero-
12937 /// endpoint triad) — the three `is_*_condition_kind_empty` methods
12938 /// on [`EphemeralSpec`] delegate to the slice-level substrate
12939 /// primitive
12940 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] over the
12941 /// two `Vec<Condition>` slots (precondition + postcondition) and
12942 /// compose the union via a definitional negation of the at-least-
12943 /// one halfspace primitive
12944 /// [`EphemeralSpec::has_any_distinct_condition_kind`]. Two-surface
12945 /// parity pin against
12946 /// [`crate::boundary::Boundary::is_condition_kind_empty`] on the
12947 /// point-domain [`ProcessSpec`] surface — the two struct-level
12948 /// zero-endpoint callers compose against the SAME slice-level
12949 /// substrate primitive so a regression at the per-slice zero-
12950 /// endpoint short-circuit fails at that primitive's tests rather
12951 /// than as silent drift at either sugar-surface arm.
12952 #[test]
12953 fn is_condition_kind_empty_triad_delegates_to_slice_is_kind_empty() {
12954 // Empty ephemeral spec — every arm returns true (0 distinct,
12955 // = 0).
12956 let spec = empty_ephemeral();
12957 assert!(
12958 spec.is_precondition_kind_empty(),
12959 "empty ephemeral must return true on is_precondition_kind_empty",
12960 );
12961 assert!(
12962 spec.is_postcondition_kind_empty(),
12963 "empty ephemeral must return true on is_postcondition_kind_empty",
12964 );
12965 assert!(
12966 spec.is_condition_kind_empty(),
12967 "empty ephemeral must return true on is_condition_kind_empty",
12968 );
12969
12970 // Two-surface parity: EphemeralSpec's three arms are byte-for-
12971 // byte equal to the lowered ProcessSpec's Boundary arms across
12972 // every sweep arm.
12973 let lowered: ProcessSpec = spec.clone().into();
12974 assert_eq!(
12975 spec.is_precondition_kind_empty(),
12976 lowered.boundary.is_precondition_kind_empty(),
12977 "empty ephemeral is_precondition_kind_empty must equal lowered Boundary is_precondition_kind_empty",
12978 );
12979 assert_eq!(
12980 spec.is_postcondition_kind_empty(),
12981 lowered.boundary.is_postcondition_kind_empty(),
12982 "empty ephemeral is_postcondition_kind_empty must equal lowered Boundary is_postcondition_kind_empty",
12983 );
12984 assert_eq!(
12985 spec.is_condition_kind_empty(),
12986 lowered.boundary.is_condition_kind_empty(),
12987 "empty ephemeral is_condition_kind_empty must equal lowered Boundary is_condition_kind_empty",
12988 );
12989
12990 // Single-populated per side — every per-slice arm returns
12991 // false; the union always returns false.
12992 assert!(
12993 !ConditionKind::ALL.is_empty(),
12994 "test assumes ConditionKind::ALL has ≥ 1 variants",
12995 );
12996 for pre_kind in ConditionKind::ALL {
12997 for post_kind in ConditionKind::ALL {
12998 let mut spec = empty_ephemeral();
12999 spec.preconditions.push(cond(pre_kind));
13000 spec.postconditions.push(cond(post_kind));
13001 assert_eq!(
13002 spec.is_precondition_kind_empty(),
13003 spec.preconditions.is_kind_empty(),
13004 "EphemeralSpec::is_precondition_kind_empty must delegate verbatim to \
13005 preconditions.is_kind_empty() for pre={pre_kind:?} post={post_kind:?}",
13006 );
13007 assert_eq!(
13008 spec.is_postcondition_kind_empty(),
13009 spec.postconditions.is_kind_empty(),
13010 "EphemeralSpec::is_postcondition_kind_empty must delegate verbatim to \
13011 postconditions.is_kind_empty() for pre={pre_kind:?} post={post_kind:?}",
13012 );
13013 assert!(
13014 !spec.is_precondition_kind_empty(),
13015 "single-populated preconditions must return false on is_precondition_kind_empty for pre={pre_kind:?}",
13016 );
13017 assert!(
13018 !spec.is_postcondition_kind_empty(),
13019 "single-populated postconditions must return false on is_postcondition_kind_empty for post={post_kind:?}",
13020 );
13021 assert!(
13022 !spec.is_condition_kind_empty(),
13023 "single-populated union must return false on is_condition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13024 );
13025 assert_eq!(
13026 spec.is_condition_kind_empty(),
13027 !spec.has_any_distinct_condition_kind(),
13028 "EphemeralSpec::is_condition_kind_empty must equal !has_any_distinct_condition_kind() for pre={pre_kind:?} post={post_kind:?}",
13029 );
13030 // Two-surface parity with lowered Boundary.
13031 let lowered: ProcessSpec = spec.clone().into();
13032 assert_eq!(
13033 spec.is_precondition_kind_empty(),
13034 lowered.boundary.is_precondition_kind_empty(),
13035 "EphemeralSpec::is_precondition_kind_empty must equal lowered Boundary::is_precondition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13036 );
13037 assert_eq!(
13038 spec.is_postcondition_kind_empty(),
13039 lowered.boundary.is_postcondition_kind_empty(),
13040 "EphemeralSpec::is_postcondition_kind_empty must equal lowered Boundary::is_postcondition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13041 );
13042 assert_eq!(
13043 spec.is_condition_kind_empty(),
13044 lowered.boundary.is_condition_kind_empty(),
13045 "EphemeralSpec::is_condition_kind_empty must equal lowered Boundary::is_condition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13046 );
13047 }
13048 }
13049
13050 // Saturated ephemeral spec — every arm returns false on N ≥ 1
13051 // (every kind PRESENT across the union, not = 0).
13052 let mut spec = empty_ephemeral();
13053 for k in ConditionKind::ALL {
13054 spec.preconditions.push(cond(k));
13055 spec.postconditions.push(cond(k));
13056 }
13057 assert!(
13058 !spec.is_precondition_kind_empty(),
13059 "saturated ephemeral must return false on is_precondition_kind_empty",
13060 );
13061 assert!(
13062 !spec.is_postcondition_kind_empty(),
13063 "saturated ephemeral must return false on is_postcondition_kind_empty",
13064 );
13065 assert!(
13066 !spec.is_condition_kind_empty(),
13067 "saturated ephemeral must return false on is_condition_kind_empty",
13068 );
13069 }
13070
13071 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-mid-endpoint
13072 /// triad) — the three `has_unique_missing_*_condition_kind`
13073 /// methods on [`EphemeralSpec`] delegate to the slice-level
13074 /// substrate primitive
13075 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
13076 /// over the two `Vec<Condition>` slots (precondition +
13077 /// postcondition) and compose the union via a two-step-short-
13078 /// circuit walk over [`ConditionKind::ALL`] under negated
13079 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13080 /// against
13081 /// [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
13082 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13083 /// level near-saturation-endpoint callers compose against the
13084 /// SAME slice-level substrate primitive so a regression at the
13085 /// per-slice two-step short-circuit walk under negation fails at
13086 /// that primitive's tests rather than as silent drift at either
13087 /// sugar-surface arm.
13088 #[test]
13089 fn has_unique_missing_condition_kind_triad_delegates_to_slice_has_unique_missing_kind() {
13090 // Empty ephemeral spec — every arm returns false (all N
13091 // missing, not exactly 1) on any N ≥ 2 closed set.
13092 assert!(
13093 ConditionKind::ALL.len() >= 2,
13094 "test assumes ConditionKind::ALL has ≥ 2 variants",
13095 );
13096 let spec = empty_ephemeral();
13097 assert!(
13098 !spec.has_unique_missing_precondition_kind(),
13099 "empty ephemeral must return false on has_unique_missing_precondition_kind",
13100 );
13101 assert!(
13102 !spec.has_unique_missing_postcondition_kind(),
13103 "empty ephemeral must return false on has_unique_missing_postcondition_kind",
13104 );
13105 assert!(
13106 !spec.has_unique_missing_condition_kind(),
13107 "empty ephemeral must return false on has_unique_missing_condition_kind",
13108 );
13109 assert_eq!(
13110 spec.has_unique_missing_condition_kind(),
13111 spec.missing_condition_kind_count() == 1,
13112 "empty has_unique_missing_condition_kind must equal (missing_condition_kind_count() == 1)",
13113 );
13114
13115 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
13116 // sets. Every per-slice arm returns false; the union returns
13117 // true iff exactly one ALL variant is uncovered.
13118 if ConditionKind::ALL.len() >= 3 {
13119 for pre_kind in ConditionKind::ALL {
13120 for post_kind in ConditionKind::ALL {
13121 let mut spec = empty_ephemeral();
13122 spec.preconditions.push(cond(pre_kind));
13123 spec.postconditions.push(cond(post_kind));
13124 assert_eq!(
13125 spec.has_unique_missing_precondition_kind(),
13126 spec.preconditions.has_unique_missing_kind(),
13127 "EphemeralSpec::has_unique_missing_precondition_kind must delegate verbatim to \
13128 preconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13129 );
13130 assert_eq!(
13131 spec.has_unique_missing_postcondition_kind(),
13132 spec.postconditions.has_unique_missing_kind(),
13133 "EphemeralSpec::has_unique_missing_postcondition_kind must delegate verbatim to \
13134 postconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13135 );
13136 let uncovered = ConditionKind::ALL
13137 .into_iter()
13138 .filter(|k| *k != pre_kind && *k != post_kind)
13139 .count();
13140 let expected_union = uncovered == 1;
13141 assert_eq!(
13142 spec.has_unique_missing_condition_kind(),
13143 expected_union,
13144 "EphemeralSpec::has_unique_missing_condition_kind must equal \
13145 (uncovered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
13146 );
13147
13148 // Two-surface parity: lowered ProcessSpec's
13149 // Boundary must agree bit-for-bit with the
13150 // ephemeral sugar triad on every arm.
13151 let lowered: ProcessSpec = spec.clone().into();
13152 assert_eq!(
13153 spec.has_unique_missing_precondition_kind(),
13154 lowered.boundary.has_unique_missing_precondition_kind(),
13155 "two-surface has_unique_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13156 );
13157 assert_eq!(
13158 spec.has_unique_missing_postcondition_kind(),
13159 lowered.boundary.has_unique_missing_postcondition_kind(),
13160 "two-surface has_unique_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13161 );
13162 assert_eq!(
13163 spec.has_unique_missing_condition_kind(),
13164 lowered.boundary.has_unique_missing_condition_kind(),
13165 "two-surface has_unique_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13166 );
13167 }
13168 }
13169 }
13170
13171 // Near-saturation-endpoint per side — each slice carries
13172 // every ConditionKind except one. Every per-slice arm returns
13173 // true; the union returns true iff BOTH slices omit the SAME
13174 // kind.
13175 for pre_omit in ConditionKind::ALL {
13176 for post_omit in ConditionKind::ALL {
13177 let mut spec = empty_ephemeral();
13178 for k in ConditionKind::ALL {
13179 if k != pre_omit {
13180 spec.preconditions.push(cond(k));
13181 }
13182 if k != post_omit {
13183 spec.postconditions.push(cond(k));
13184 }
13185 }
13186 assert!(
13187 spec.has_unique_missing_precondition_kind(),
13188 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_unique_missing_precondition_kind",
13189 );
13190 assert!(
13191 spec.has_unique_missing_postcondition_kind(),
13192 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_unique_missing_postcondition_kind",
13193 );
13194 let expected_union = pre_omit == post_omit;
13195 assert_eq!(
13196 spec.has_unique_missing_condition_kind(),
13197 expected_union,
13198 "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:?}",
13199 );
13200
13201 // Two-surface parity for near-saturation arm.
13202 let lowered: ProcessSpec = spec.clone().into();
13203 assert_eq!(
13204 spec.has_unique_missing_precondition_kind(),
13205 lowered.boundary.has_unique_missing_precondition_kind(),
13206 "two-surface has_unique_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13207 );
13208 assert_eq!(
13209 spec.has_unique_missing_postcondition_kind(),
13210 lowered.boundary.has_unique_missing_postcondition_kind(),
13211 "two-surface has_unique_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13212 );
13213 assert_eq!(
13214 spec.has_unique_missing_condition_kind(),
13215 lowered.boundary.has_unique_missing_condition_kind(),
13216 "two-surface has_unique_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13217 );
13218 }
13219 }
13220
13221 // Saturated ephemeral — every arm returns false (0 missing,
13222 // not exactly 1).
13223 let mut spec = empty_ephemeral();
13224 for k in ConditionKind::ALL {
13225 spec.preconditions.push(cond(k));
13226 spec.postconditions.push(cond(k));
13227 }
13228 assert!(
13229 !spec.has_unique_missing_precondition_kind(),
13230 "saturated ephemeral must return false on has_unique_missing_precondition_kind",
13231 );
13232 assert!(
13233 !spec.has_unique_missing_postcondition_kind(),
13234 "saturated ephemeral must return false on has_unique_missing_postcondition_kind",
13235 );
13236 assert!(
13237 !spec.has_unique_missing_condition_kind(),
13238 "saturated ephemeral must return false on has_unique_missing_condition_kind",
13239 );
13240 }
13241
13242 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
13243 /// triad) — the three `has_multiple_missing_*_condition_kind`
13244 /// methods on [`EphemeralSpec`] delegate to the slice-level
13245 /// substrate primitive
13246 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
13247 /// over the two `Vec<Condition>` slots (precondition +
13248 /// postcondition) and compose the union via a two-step-short-
13249 /// circuit walk over [`ConditionKind::ALL`] under negated
13250 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13251 /// against
13252 /// [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
13253 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13254 /// level cardinality-many-arm callers compose against the SAME
13255 /// slice-level substrate primitive so a regression at the per-
13256 /// slice two-step short-circuit walk under negation fails at that
13257 /// primitive's tests rather than as silent drift at either sugar-
13258 /// surface arm.
13259 #[test]
13260 fn has_multiple_missing_condition_kind_triad_delegates_to_slice_has_multiple_missing_kinds() {
13261 // Empty ephemeral spec — every arm returns true (all N
13262 // missing, ≥ 2) on any N ≥ 2 closed set.
13263 assert!(
13264 ConditionKind::ALL.len() >= 2,
13265 "test assumes ConditionKind::ALL has ≥ 2 variants",
13266 );
13267 let spec = empty_ephemeral();
13268 assert!(
13269 spec.has_multiple_missing_precondition_kind(),
13270 "empty ephemeral must return true on has_multiple_missing_precondition_kind",
13271 );
13272 assert!(
13273 spec.has_multiple_missing_postcondition_kind(),
13274 "empty ephemeral must return true on has_multiple_missing_postcondition_kind",
13275 );
13276 assert!(
13277 spec.has_multiple_missing_condition_kind(),
13278 "empty ephemeral must return true on has_multiple_missing_condition_kind",
13279 );
13280 assert_eq!(
13281 spec.has_multiple_missing_condition_kind(),
13282 spec.missing_condition_kind_count() >= 2,
13283 "empty has_multiple_missing_condition_kind must equal (missing_condition_kind_count() >= 2)",
13284 );
13285
13286 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
13287 // sets. Every per-slice arm returns true; the union returns
13288 // true iff ≥ 2 ALL variants are uncovered.
13289 if ConditionKind::ALL.len() >= 3 {
13290 for pre_kind in ConditionKind::ALL {
13291 for post_kind in ConditionKind::ALL {
13292 let mut spec = empty_ephemeral();
13293 spec.preconditions.push(cond(pre_kind));
13294 spec.postconditions.push(cond(post_kind));
13295 assert_eq!(
13296 spec.has_multiple_missing_precondition_kind(),
13297 spec.preconditions.has_multiple_missing_kinds(),
13298 "EphemeralSpec::has_multiple_missing_precondition_kind must delegate verbatim to \
13299 preconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
13300 );
13301 assert_eq!(
13302 spec.has_multiple_missing_postcondition_kind(),
13303 spec.postconditions.has_multiple_missing_kinds(),
13304 "EphemeralSpec::has_multiple_missing_postcondition_kind must delegate verbatim to \
13305 postconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
13306 );
13307 let uncovered = ConditionKind::ALL
13308 .into_iter()
13309 .filter(|k| *k != pre_kind && *k != post_kind)
13310 .count();
13311 let expected_union = uncovered >= 2;
13312 assert_eq!(
13313 spec.has_multiple_missing_condition_kind(),
13314 expected_union,
13315 "EphemeralSpec::has_multiple_missing_condition_kind must equal \
13316 (uncovered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
13317 );
13318
13319 // Two-surface parity: lowered ProcessSpec's
13320 // Boundary must agree bit-for-bit with the
13321 // ephemeral sugar triad on every arm.
13322 let lowered: ProcessSpec = spec.clone().into();
13323 assert_eq!(
13324 spec.has_multiple_missing_precondition_kind(),
13325 lowered.boundary.has_multiple_missing_precondition_kind(),
13326 "two-surface has_multiple_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13327 );
13328 assert_eq!(
13329 spec.has_multiple_missing_postcondition_kind(),
13330 lowered.boundary.has_multiple_missing_postcondition_kind(),
13331 "two-surface has_multiple_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13332 );
13333 assert_eq!(
13334 spec.has_multiple_missing_condition_kind(),
13335 lowered.boundary.has_multiple_missing_condition_kind(),
13336 "two-surface has_multiple_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13337 );
13338 }
13339 }
13340 }
13341
13342 // Near-saturation-endpoint per side — each slice carries
13343 // every ConditionKind except one. Every per-slice arm returns
13344 // false (exactly 1 missing per slice, not ≥ 2). The union
13345 // has at most 1 missing (pre and post's omissions either
13346 // coincide → 1 missing, or differ → 0 missing), so the union
13347 // is always false on this arm.
13348 for pre_omit in ConditionKind::ALL {
13349 for post_omit in ConditionKind::ALL {
13350 let mut spec = empty_ephemeral();
13351 for k in ConditionKind::ALL {
13352 if k != pre_omit {
13353 spec.preconditions.push(cond(k));
13354 }
13355 if k != post_omit {
13356 spec.postconditions.push(cond(k));
13357 }
13358 }
13359 assert!(
13360 !spec.has_multiple_missing_precondition_kind(),
13361 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return false on has_multiple_missing_precondition_kind",
13362 );
13363 assert!(
13364 !spec.has_multiple_missing_postcondition_kind(),
13365 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return false on has_multiple_missing_postcondition_kind",
13366 );
13367 assert!(
13368 !spec.has_multiple_missing_condition_kind(),
13369 "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:?}",
13370 );
13371
13372 // Two-surface parity for near-saturation arm.
13373 let lowered: ProcessSpec = spec.clone().into();
13374 assert_eq!(
13375 spec.has_multiple_missing_precondition_kind(),
13376 lowered.boundary.has_multiple_missing_precondition_kind(),
13377 "two-surface has_multiple_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13378 );
13379 assert_eq!(
13380 spec.has_multiple_missing_postcondition_kind(),
13381 lowered.boundary.has_multiple_missing_postcondition_kind(),
13382 "two-surface has_multiple_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13383 );
13384 assert_eq!(
13385 spec.has_multiple_missing_condition_kind(),
13386 lowered.boundary.has_multiple_missing_condition_kind(),
13387 "two-surface has_multiple_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13388 );
13389 }
13390 }
13391
13392 // Saturated ephemeral — every arm returns false (0 missing,
13393 // not ≥ 2).
13394 let mut spec = empty_ephemeral();
13395 for k in ConditionKind::ALL {
13396 spec.preconditions.push(cond(k));
13397 spec.postconditions.push(cond(k));
13398 }
13399 assert!(
13400 !spec.has_multiple_missing_precondition_kind(),
13401 "saturated ephemeral must return false on has_multiple_missing_precondition_kind",
13402 );
13403 assert!(
13404 !spec.has_multiple_missing_postcondition_kind(),
13405 "saturated ephemeral must return false on has_multiple_missing_postcondition_kind",
13406 );
13407 assert!(
13408 !spec.has_multiple_missing_condition_kind(),
13409 "saturated ephemeral must return false on has_multiple_missing_condition_kind",
13410 );
13411 }
13412
13413 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1"
13414 /// triad) — the three `has_at_most_one_missing_*_condition_kind`
13415 /// methods on [`EphemeralSpec`] delegate to the slice-level
13416 /// substrate primitive
13417 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
13418 /// over the two `Vec<Condition>` slots (precondition +
13419 /// postcondition) and compose the union via
13420 /// `!self.has_multiple_missing_condition_kind()` — a definitional
13421 /// negation of the many-arm union primitive. Two-surface parity
13422 /// pin against
13423 /// [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
13424 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13425 /// level cardinality "≤ 1" callers compose against the SAME
13426 /// slice-level substrate primitive so a regression at the per-
13427 /// slice "≤ 1" negation fails at that primitive's tests rather
13428 /// than as silent drift at either sugar-surface arm.
13429 #[test]
13430 fn has_at_most_one_missing_condition_kind_triad_delegates_to_slice_has_at_most_one_missing_kind(
13431 ) {
13432 // Empty ephemeral spec — every arm returns false (all N
13433 // missing, not ≤ 1) on any N ≥ 2 closed set.
13434 assert!(
13435 ConditionKind::ALL.len() >= 2,
13436 "test assumes ConditionKind::ALL has ≥ 2 variants",
13437 );
13438 let spec = empty_ephemeral();
13439 assert!(
13440 !spec.has_at_most_one_missing_precondition_kind(),
13441 "empty ephemeral must return false on has_at_most_one_missing_precondition_kind",
13442 );
13443 assert!(
13444 !spec.has_at_most_one_missing_postcondition_kind(),
13445 "empty ephemeral must return false on has_at_most_one_missing_postcondition_kind",
13446 );
13447 assert!(
13448 !spec.has_at_most_one_missing_condition_kind(),
13449 "empty ephemeral must return false on has_at_most_one_missing_condition_kind",
13450 );
13451 assert_eq!(
13452 spec.has_at_most_one_missing_condition_kind(),
13453 spec.missing_condition_kind_count() <= 1,
13454 "empty has_at_most_one_missing_condition_kind must equal (missing_condition_kind_count() <= 1)",
13455 );
13456
13457 // Single-populated per side — sweep ALL × ALL on N ≥ 3
13458 // closed sets. Every per-slice arm returns false; the union
13459 // returns true iff ≤ 1 ALL variant is uncovered.
13460 if ConditionKind::ALL.len() >= 3 {
13461 for pre_kind in ConditionKind::ALL {
13462 for post_kind in ConditionKind::ALL {
13463 let mut spec = empty_ephemeral();
13464 spec.preconditions.push(cond(pre_kind));
13465 spec.postconditions.push(cond(post_kind));
13466 assert_eq!(
13467 spec.has_at_most_one_missing_precondition_kind(),
13468 spec.preconditions.has_at_most_one_missing_kind(),
13469 "EphemeralSpec::has_at_most_one_missing_precondition_kind must delegate verbatim to \
13470 preconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13471 );
13472 assert_eq!(
13473 spec.has_at_most_one_missing_postcondition_kind(),
13474 spec.postconditions.has_at_most_one_missing_kind(),
13475 "EphemeralSpec::has_at_most_one_missing_postcondition_kind must delegate verbatim to \
13476 postconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13477 );
13478 let uncovered = ConditionKind::ALL
13479 .into_iter()
13480 .filter(|k| *k != pre_kind && *k != post_kind)
13481 .count();
13482 let expected_union = uncovered <= 1;
13483 assert_eq!(
13484 spec.has_at_most_one_missing_condition_kind(),
13485 expected_union,
13486 "EphemeralSpec::has_at_most_one_missing_condition_kind must equal \
13487 (uncovered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
13488 );
13489
13490 // Two-surface parity: lowered ProcessSpec's
13491 // Boundary must agree bit-for-bit with the
13492 // ephemeral sugar triad on every arm.
13493 let lowered: ProcessSpec = spec.clone().into();
13494 assert_eq!(
13495 spec.has_at_most_one_missing_precondition_kind(),
13496 lowered.boundary.has_at_most_one_missing_precondition_kind(),
13497 "two-surface has_at_most_one_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13498 );
13499 assert_eq!(
13500 spec.has_at_most_one_missing_postcondition_kind(),
13501 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
13502 "two-surface has_at_most_one_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13503 );
13504 assert_eq!(
13505 spec.has_at_most_one_missing_condition_kind(),
13506 lowered.boundary.has_at_most_one_missing_condition_kind(),
13507 "two-surface has_at_most_one_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13508 );
13509 }
13510 }
13511 }
13512
13513 // Near-saturation-endpoint per side — each slice carries
13514 // every ConditionKind except one. Every per-slice arm returns
13515 // true (exactly 1 missing per slice, ≤ 1). The union has ≤ 1
13516 // missing (pre and post's omissions either coincide → 1
13517 // missing, or differ → 0 missing), so the union is always
13518 // true on this arm.
13519 for pre_omit in ConditionKind::ALL {
13520 for post_omit in ConditionKind::ALL {
13521 let mut spec = empty_ephemeral();
13522 for k in ConditionKind::ALL {
13523 if k != pre_omit {
13524 spec.preconditions.push(cond(k));
13525 }
13526 if k != post_omit {
13527 spec.postconditions.push(cond(k));
13528 }
13529 }
13530 assert!(
13531 spec.has_at_most_one_missing_precondition_kind(),
13532 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_at_most_one_missing_precondition_kind",
13533 );
13534 assert!(
13535 spec.has_at_most_one_missing_postcondition_kind(),
13536 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_at_most_one_missing_postcondition_kind",
13537 );
13538 assert!(
13539 spec.has_at_most_one_missing_condition_kind(),
13540 "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:?}",
13541 );
13542
13543 // Two-surface parity for near-saturation arm.
13544 let lowered: ProcessSpec = spec.clone().into();
13545 assert_eq!(
13546 spec.has_at_most_one_missing_precondition_kind(),
13547 lowered.boundary.has_at_most_one_missing_precondition_kind(),
13548 "two-surface has_at_most_one_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13549 );
13550 assert_eq!(
13551 spec.has_at_most_one_missing_postcondition_kind(),
13552 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
13553 "two-surface has_at_most_one_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13554 );
13555 assert_eq!(
13556 spec.has_at_most_one_missing_condition_kind(),
13557 lowered.boundary.has_at_most_one_missing_condition_kind(),
13558 "two-surface has_at_most_one_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13559 );
13560 }
13561 }
13562
13563 // Saturated ephemeral — every arm returns true (0 missing,
13564 // ≤ 1).
13565 let mut spec = empty_ephemeral();
13566 for k in ConditionKind::ALL {
13567 spec.preconditions.push(cond(k));
13568 spec.postconditions.push(cond(k));
13569 }
13570 assert!(
13571 spec.has_at_most_one_missing_precondition_kind(),
13572 "saturated ephemeral must return true on has_at_most_one_missing_precondition_kind",
13573 );
13574 assert!(
13575 spec.has_at_most_one_missing_postcondition_kind(),
13576 "saturated ephemeral must return true on has_at_most_one_missing_postcondition_kind",
13577 );
13578 assert!(
13579 spec.has_at_most_one_missing_condition_kind(),
13580 "saturated ephemeral must return true on has_at_most_one_missing_condition_kind",
13581 );
13582 }
13583
13584 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind-complement
13585 /// triad) — the three `lacks_*_condition_kind` methods on
13586 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
13587 /// [`ConditionSliceExt::lacks_kind`] over the two `Vec<Condition>`
13588 /// slots (precondition + postcondition) and compose the union via
13589 /// `!self.has_condition_kind(kind)`. Two-surface parity pin against
13590 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
13591 /// point-domain [`ProcessSpec`] surface — the two struct-level
13592 /// per-kind-complement callers compose against the SAME slice-level
13593 /// substrate primitive so a regression at the per-slice negation
13594 /// fails at that primitive's tests rather than as silent drift at
13595 /// either sugar-surface arm. Also pins the composition laws
13596 /// `lacks_*_condition_kind(k) == !has_*_condition_kind(k)` at each
13597 /// arm AND `lacks_condition_kind(k) == lacks_precondition_kind(k) &&
13598 /// lacks_postcondition_kind(k)` (the union AND-composition dual of
13599 /// `has`'s OR-composition).
13600 #[test]
13601 fn lacks_condition_kind_triad_delegates_to_slice_lacks_kind() {
13602 // Empty ephemeral spec — every arm returns true on every kind.
13603 let spec = empty_ephemeral();
13604 for kind in ConditionKind::ALL {
13605 assert!(
13606 spec.lacks_precondition_kind(kind),
13607 "empty ephemeral must return true on lacks_precondition_kind for {kind:?}",
13608 );
13609 assert!(
13610 spec.lacks_postcondition_kind(kind),
13611 "empty ephemeral must return true on lacks_postcondition_kind for {kind:?}",
13612 );
13613 assert!(
13614 spec.lacks_condition_kind(kind),
13615 "empty ephemeral must return true on lacks_condition_kind for {kind:?}",
13616 );
13617 assert_eq!(
13618 spec.lacks_condition_kind(kind),
13619 !spec.has_condition_kind(kind),
13620 "empty lacks_condition_kind must equal !has_condition_kind for {kind:?}",
13621 );
13622 }
13623
13624 // Single-populated per side — sweep ALL × ALL, then probe every
13625 // ConditionKind on the (pre, post, union) triad + two-surface
13626 // parity against the lowered ProcessSpec's Boundary.
13627 for pre_kind in ConditionKind::ALL {
13628 for post_kind in ConditionKind::ALL {
13629 let mut spec = empty_ephemeral();
13630 spec.preconditions.push(cond(pre_kind));
13631 spec.postconditions.push(cond(post_kind));
13632 let lowered: ProcessSpec = spec.clone().into();
13633 for probe in ConditionKind::ALL {
13634 assert_eq!(
13635 spec.lacks_precondition_kind(probe),
13636 spec.preconditions.lacks_kind(probe),
13637 "EphemeralSpec::lacks_precondition_kind must delegate verbatim to preconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13638 );
13639 assert_eq!(
13640 spec.lacks_postcondition_kind(probe),
13641 spec.postconditions.lacks_kind(probe),
13642 "EphemeralSpec::lacks_postcondition_kind must delegate verbatim to postconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13643 );
13644 let expected_union = pre_kind != probe && post_kind != probe;
13645 assert_eq!(
13646 spec.lacks_condition_kind(probe),
13647 expected_union,
13648 "EphemeralSpec::lacks_condition_kind must equal all-ALL-absent-in-both-slices for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13649 );
13650 assert_eq!(
13651 spec.lacks_condition_kind(probe),
13652 !spec.has_condition_kind(probe),
13653 "EphemeralSpec::lacks_condition_kind must equal !has_condition_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13654 );
13655 assert_eq!(
13656 spec.lacks_condition_kind(probe),
13657 spec.lacks_precondition_kind(probe)
13658 && spec.lacks_postcondition_kind(probe),
13659 "EphemeralSpec::lacks_condition_kind must equal AND-of-half-slice-arms for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13660 );
13661
13662 // Two-surface parity: lowered ProcessSpec's Boundary
13663 // must agree bit-for-bit with the ephemeral sugar
13664 // triad on every arm.
13665 assert_eq!(
13666 spec.lacks_precondition_kind(probe),
13667 lowered.boundary.lacks_precondition_kind(probe),
13668 "two-surface lacks_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13669 );
13670 assert_eq!(
13671 spec.lacks_postcondition_kind(probe),
13672 lowered.boundary.lacks_postcondition_kind(probe),
13673 "two-surface lacks_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13674 );
13675 assert_eq!(
13676 spec.lacks_condition_kind(probe),
13677 lowered.boundary.lacks_condition_kind(probe),
13678 "two-surface lacks_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13679 );
13680 }
13681 }
13682 }
13683
13684 // Saturated ephemeral — both slices carry every ConditionKind,
13685 // every arm returns false on every kind.
13686 let mut spec = empty_ephemeral();
13687 for k in ConditionKind::ALL {
13688 spec.preconditions.push(cond(k));
13689 spec.postconditions.push(cond(k));
13690 }
13691 for kind in ConditionKind::ALL {
13692 assert!(
13693 !spec.lacks_precondition_kind(kind),
13694 "saturated ephemeral must return false on lacks_precondition_kind for {kind:?}",
13695 );
13696 assert!(
13697 !spec.lacks_postcondition_kind(kind),
13698 "saturated ephemeral must return false on lacks_postcondition_kind for {kind:?}",
13699 );
13700 assert!(
13701 !spec.lacks_condition_kind(kind),
13702 "saturated ephemeral must return false on lacks_condition_kind for {kind:?}",
13703 );
13704 }
13705 }
13706
13707 /// TRIAD delegation pin — the (precondition, postcondition,
13708 /// condition-union) kind-scoped strict-refinement triad on
13709 /// [`EphemeralSpec`] agrees byte-for-byte with the slice-level
13710 /// substrate primitive
13711 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] on every
13712 /// authored arrangement AND with the lowered
13713 /// [`ProcessSpec::boundary`]'s kind-scoped strict-refinement
13714 /// triad through the `From<EphemeralSpec>` bridge — the two-
13715 /// surface parity contract at the well-formed-diagonal arm.
13716 ///
13717 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
13718 /// single-populated-per-side arrangements (the well-formed
13719 /// diagonal), probing every [`ConditionKind`] at the union arm
13720 /// against the DERIVED oracle `pre_kind == probe && post_kind ==
13721 /// probe`. Also sweeps the single-side-only-populated arms (the
13722 /// union carries a singleton distinct set — pins the union arm
13723 /// reaches the union primitive, not the (pre AND post) AND-
13724 /// composition). A regression at the union arm's fused walk or
13725 /// at the `From<EphemeralSpec>` bridge surfaces HERE.
13726 #[test]
13727 fn has_only_condition_kind_triad_delegates_to_slice_has_only_kind() {
13728 // Empty ephemeral spec — every arm returns false on every
13729 // kind (no kind is populated, so no kind is "only").
13730 let spec = empty_ephemeral();
13731 for kind in ConditionKind::ALL {
13732 assert!(
13733 !spec.has_only_precondition_kind(kind),
13734 "empty ephemeral must return false on has_only_precondition_kind for {kind:?}",
13735 );
13736 assert!(
13737 !spec.has_only_postcondition_kind(kind),
13738 "empty ephemeral must return false on has_only_postcondition_kind for {kind:?}",
13739 );
13740 assert!(
13741 !spec.has_only_condition_kind(kind),
13742 "empty ephemeral must return false on has_only_condition_kind for {kind:?}",
13743 );
13744 }
13745
13746 // Single-populated per side — sweep ALL × ALL, then probe
13747 // every ConditionKind on the (pre, post, union) triad + two-
13748 // surface parity against the lowered ProcessSpec's Boundary.
13749 for pre_kind in ConditionKind::ALL {
13750 for post_kind in ConditionKind::ALL {
13751 let mut spec = empty_ephemeral();
13752 spec.preconditions.push(cond(pre_kind));
13753 spec.postconditions.push(cond(post_kind));
13754 let lowered: ProcessSpec = spec.clone().into();
13755 for probe in ConditionKind::ALL {
13756 assert_eq!(
13757 spec.has_only_precondition_kind(probe),
13758 spec.preconditions.has_only_kind(probe),
13759 "EphemeralSpec::has_only_precondition_kind must delegate verbatim to preconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13760 );
13761 assert_eq!(
13762 spec.has_only_postcondition_kind(probe),
13763 spec.postconditions.has_only_kind(probe),
13764 "EphemeralSpec::has_only_postcondition_kind must delegate verbatim to postconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13765 );
13766 let expected_union = pre_kind == probe && post_kind == probe;
13767 assert_eq!(
13768 spec.has_only_condition_kind(probe),
13769 expected_union,
13770 "EphemeralSpec::has_only_condition_kind must equal (pre_kind == probe && post_kind == probe) for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13771 );
13772
13773 // Two-surface parity: lowered ProcessSpec's
13774 // Boundary must agree bit-for-bit with the
13775 // ephemeral sugar triad on every arm.
13776 assert_eq!(
13777 spec.has_only_precondition_kind(probe),
13778 lowered.boundary.has_only_precondition_kind(probe),
13779 "two-surface has_only_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13780 );
13781 assert_eq!(
13782 spec.has_only_postcondition_kind(probe),
13783 lowered.boundary.has_only_postcondition_kind(probe),
13784 "two-surface has_only_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13785 );
13786 assert_eq!(
13787 spec.has_only_condition_kind(probe),
13788 lowered.boundary.has_only_condition_kind(probe),
13789 "two-surface has_only_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13790 );
13791 }
13792 }
13793 }
13794
13795 // Single-side-only populated — the union carries a singleton
13796 // distinct set; the union arm returns `true` for the populated
13797 // kind and `false` for every other kind, DESPITE the empty
13798 // side's `has_only_kind` returning `false`. Pins that the
13799 // union arm reaches the union primitive
13800 // [`Self::has_condition_kind`], not the (pre AND post) AND-
13801 // composition of the per-slice arms. Also pins two-surface
13802 // parity on the single-side arrangement.
13803 for populated in ConditionKind::ALL {
13804 let mut spec = empty_ephemeral();
13805 spec.preconditions.push(cond(populated));
13806 let lowered: ProcessSpec = spec.clone().into();
13807 for probe in ConditionKind::ALL {
13808 let expected = probe == populated;
13809 assert_eq!(
13810 spec.has_only_condition_kind(probe),
13811 expected,
13812 "pre-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
13813 );
13814 assert_eq!(
13815 spec.has_only_condition_kind(probe),
13816 lowered.boundary.has_only_condition_kind(probe),
13817 "two-surface pre-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
13818 );
13819 }
13820
13821 let mut spec = empty_ephemeral();
13822 spec.postconditions.push(cond(populated));
13823 let lowered: ProcessSpec = spec.clone().into();
13824 for probe in ConditionKind::ALL {
13825 let expected = probe == populated;
13826 assert_eq!(
13827 spec.has_only_condition_kind(probe),
13828 expected,
13829 "post-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
13830 );
13831 assert_eq!(
13832 spec.has_only_condition_kind(probe),
13833 lowered.boundary.has_only_condition_kind(probe),
13834 "two-surface post-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
13835 );
13836 }
13837 }
13838
13839 // Saturated ephemeral — both slices carry every ConditionKind,
13840 // every arm returns false on every kind (N distinct kinds, no
13841 // kind is "only").
13842 let mut spec = empty_ephemeral();
13843 for k in ConditionKind::ALL {
13844 spec.preconditions.push(cond(k));
13845 spec.postconditions.push(cond(k));
13846 }
13847 for kind in ConditionKind::ALL {
13848 assert!(
13849 !spec.has_only_precondition_kind(kind),
13850 "saturated ephemeral must return false on has_only_precondition_kind for {kind:?}",
13851 );
13852 assert!(
13853 !spec.has_only_postcondition_kind(kind),
13854 "saturated ephemeral must return false on has_only_postcondition_kind for {kind:?}",
13855 );
13856 assert!(
13857 !spec.has_only_condition_kind(kind),
13858 "saturated ephemeral must return false on has_only_condition_kind for {kind:?}",
13859 );
13860 }
13861 }
13862
13863 /// TRIAD delegation pin — the (precondition, postcondition,
13864 /// condition-union) kind-scoped strict-refinement-on-missing triad
13865 /// on [`EphemeralSpec`] agrees byte-for-byte with the slice-level
13866 /// substrate primitive
13867 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] on every
13868 /// authored arrangement, AND agrees bit-for-bit with the lowered
13869 /// [`ProcessSpec::boundary`]'s triad via the [`From`] bridge.
13870 ///
13871 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
13872 /// single-populated-per-side arrangements + near-saturation-per-
13873 /// side arrangements + single-side-only near-saturation
13874 /// arrangements. The union arm is probed against the DERIVED
13875 /// oracle `spec.missing_condition_kinds() == vec![probe]`, and
13876 /// the per-slice arms delegate to the slice substrate primitive
13877 /// verbatim. Two-surface parity ensures a regression at the
13878 /// `From<EphemeralSpec>` bridge (a re-ordered condition Vec, a
13879 /// dropped ClosedLoopAuth default) surfaces HERE at the union arm.
13880 #[test]
13881 fn lacks_only_condition_kind_triad_delegates_to_slice_lacks_only_kind() {
13882 // Empty ephemeral spec — every kind is missing on N ≥ 2, so
13883 // no kind is "only" missing on any arm.
13884 let spec = empty_ephemeral();
13885 let lowered: ProcessSpec = spec.clone().into();
13886 for kind in ConditionKind::ALL {
13887 assert_eq!(
13888 spec.lacks_only_precondition_kind(kind),
13889 spec.preconditions.lacks_only_kind(kind),
13890 "empty ephemeral lacks_only_precondition_kind must delegate to preconditions.lacks_only_kind for {kind:?}",
13891 );
13892 assert_eq!(
13893 spec.lacks_only_postcondition_kind(kind),
13894 spec.postconditions.lacks_only_kind(kind),
13895 "empty ephemeral lacks_only_postcondition_kind must delegate to postconditions.lacks_only_kind for {kind:?}",
13896 );
13897 assert_eq!(
13898 spec.lacks_only_condition_kind(kind),
13899 lowered.boundary.lacks_only_condition_kind(kind),
13900 "two-surface empty lacks_only_condition_kind parity drift for {kind:?}",
13901 );
13902 }
13903
13904 // Near-saturation per side — build an ephemeral spec whose both
13905 // sides carry every kind except one; sweep every omitted kind
13906 // and probe every ConditionKind on the (pre, post, union) triad.
13907 for omitted in ConditionKind::ALL {
13908 let mut spec = empty_ephemeral();
13909 for k in ConditionKind::ALL {
13910 if k != omitted {
13911 spec.preconditions.push(cond(k));
13912 spec.postconditions.push(cond(k));
13913 }
13914 }
13915 let lowered: ProcessSpec = spec.clone().into();
13916 for probe in ConditionKind::ALL {
13917 let expected = probe == omitted;
13918 assert_eq!(
13919 spec.lacks_only_precondition_kind(probe),
13920 expected,
13921 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_precondition_kind({probe:?})",
13922 );
13923 assert_eq!(
13924 spec.lacks_only_postcondition_kind(probe),
13925 expected,
13926 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_postcondition_kind({probe:?})",
13927 );
13928 assert_eq!(
13929 spec.lacks_only_condition_kind(probe),
13930 expected,
13931 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
13932 );
13933 assert_eq!(
13934 spec.lacks_only_condition_kind(probe),
13935 spec.missing_condition_kinds() == vec![probe],
13936 "near-saturation ephemeral omitted={omitted:?} must agree with missing_condition_kinds() == vec![{probe:?}]",
13937 );
13938
13939 // Two-surface parity via lowered ProcessSpec.
13940 assert_eq!(
13941 spec.lacks_only_precondition_kind(probe),
13942 lowered.boundary.lacks_only_precondition_kind(probe),
13943 "two-surface lacks_only_precondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13944 );
13945 assert_eq!(
13946 spec.lacks_only_postcondition_kind(probe),
13947 lowered.boundary.lacks_only_postcondition_kind(probe),
13948 "two-surface lacks_only_postcondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13949 );
13950 assert_eq!(
13951 spec.lacks_only_condition_kind(probe),
13952 lowered.boundary.lacks_only_condition_kind(probe),
13953 "two-surface lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13954 );
13955 }
13956 }
13957
13958 // Single-side-only near-saturation — the populated side covers
13959 // every kind except one; the OTHER side is empty. The union
13960 // still has missing set `{omitted}` (the populated side's hole
13961 // wins), so the union arm returns `true` for `omitted` and
13962 // `false` for every other kind, DESPITE the empty side's
13963 // `lacks_only_kind` returning `false` on every kind for N ≥ 2.
13964 // Pins that the union arm reaches the union primitive, not the
13965 // (pre AND post) AND-composition.
13966 for omitted in ConditionKind::ALL {
13967 let mut spec = empty_ephemeral();
13968 for k in ConditionKind::ALL {
13969 if k != omitted {
13970 spec.preconditions.push(cond(k));
13971 }
13972 }
13973 let lowered: ProcessSpec = spec.clone().into();
13974 for probe in ConditionKind::ALL {
13975 let expected = probe == omitted;
13976 assert_eq!(
13977 spec.lacks_only_condition_kind(probe),
13978 expected,
13979 "pre-only near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
13980 );
13981 assert_eq!(
13982 spec.lacks_only_condition_kind(probe),
13983 lowered.boundary.lacks_only_condition_kind(probe),
13984 "two-surface pre-only near-saturation lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13985 );
13986 }
13987 }
13988
13989 // Saturated ephemeral — every kind populated, no kind missing,
13990 // every arm returns false on every kind.
13991 let mut spec = empty_ephemeral();
13992 for k in ConditionKind::ALL {
13993 spec.preconditions.push(cond(k));
13994 spec.postconditions.push(cond(k));
13995 }
13996 for kind in ConditionKind::ALL {
13997 assert!(
13998 !spec.lacks_only_precondition_kind(kind),
13999 "saturated ephemeral must return false on lacks_only_precondition_kind for {kind:?}",
14000 );
14001 assert!(
14002 !spec.lacks_only_postcondition_kind(kind),
14003 "saturated ephemeral must return false on lacks_only_postcondition_kind for {kind:?}",
14004 );
14005 assert!(
14006 !spec.lacks_only_condition_kind(kind),
14007 "saturated ephemeral must return false on lacks_only_condition_kind for {kind:?}",
14008 );
14009 }
14010 }
14011}