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` is MISSING EXACTLY
1708 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
1709 /// (precondition, postcondition, condition-union) cardinality-
1710 /// mid-endpoint triad on [`EphemeralSpec`] closing the near-
1711 /// saturation-endpoint on the union of the two condition slots.
1712 /// The Boolean cardinality-mid-endpoint fast-path peer of
1713 /// [`Self::is_condition_kind_saturated`]: where the saturation-
1714 /// endpoint predicate answers "is the union covered by every ALL
1715 /// variant?", `has_unique_missing_condition_kind` answers "is the
1716 /// union one kind away from covered?".
1717 ///
1718 /// Composed body: constructs a two-step-short-circuit walk over
1719 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
1720 /// union primitive negated — the first missing union arm surfaces,
1721 /// then the walk short-circuits at the second. Byte-for-byte peer
1722 /// of
1723 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
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_unique_missing_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_unique_missing_kind`]
1735 /// via the two-slice union — a regression at the per-slice
1736 /// near-saturation-endpoint walk fails at that primitive's tests
1737 /// rather than as silent drift at either struct-level near-
1738 /// saturation caller.
1739 ///
1740 /// # Sibling to [`Self::missing_condition_kinds`] /
1741 /// [`Self::missing_condition_kind_count`]
1742 ///
1743 /// Cardinality-mid-endpoint Boolean projection of the widened +
1744 /// scalar closed-set-complement primitives on the ephemeral-union
1745 /// surface — where those primitives return the FULL missing SET
1746 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
1747 /// in `0..=ConditionKind::ALL.len()`),
1748 /// `has_unique_missing_condition_kind` collapses either the
1749 /// widened primitive to its unit-length Boolean or the scalar to
1750 /// its `== 1` cardinality-mid-endpoint Boolean. Strictly cheaper
1751 /// than either widened primitive on every arm with `≥ 2` missing
1752 /// kinds because the negation short-circuits at the second
1753 /// missing kind rather than allocating the closed-set-complement
1754 /// scan or walking every slot to build the scalar cardinality.
1755 ///
1756 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1757 /// preserves proofs — the cardinality-mid-endpoint projection on
1758 /// the missing axis composes the SAME two-step short-circuit walk
1759 /// under a two-slice union negation on both this ephemeral
1760 /// surface and the point-domain
1761 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
1762 /// (generation over composition — a new [`ConditionKind`]
1763 /// variant reaches both surfaces' cardinality-mid-endpoint triads
1764 /// mechanically through the delegated union primitive).
1765 #[must_use]
1766 pub fn has_unique_missing_condition_kind(&self) -> bool {
1767 let mut it = ConditionKind::ALL
1768 .iter()
1769 .copied()
1770 .filter(|k| !self.has_condition_kind(*k));
1771 it.next().is_some() && it.next().is_none()
1772 }
1773
1774 /// `true` iff [`Self::preconditions`] is MISSING EXACTLY ONE
1775 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1776 /// the (precondition, postcondition, condition-union)
1777 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
1778 /// typed delegate to
1779 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
1780 /// over [`Self::preconditions`].
1781 ///
1782 /// Peer of
1783 /// [`crate::boundary::Boundary::has_unique_missing_precondition_kind`]
1784 /// on the point-domain surface — both peers compose against the
1785 /// SAME slice-level substrate primitive so a regression at the
1786 /// per-slice two-step short-circuit walk under negation fails at
1787 /// that primitive's tests rather than as silent drift at either
1788 /// struct-level arm.
1789 #[must_use]
1790 pub fn has_unique_missing_precondition_kind(&self) -> bool {
1791 self.preconditions.has_unique_missing_kind()
1792 }
1793
1794 /// `true` iff [`Self::postconditions`] is MISSING EXACTLY ONE
1795 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1796 /// the (precondition, postcondition, condition-union)
1797 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
1798 /// typed delegate to
1799 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
1800 /// over [`Self::postconditions`].
1801 ///
1802 /// Peer of
1803 /// [`crate::boundary::Boundary::has_unique_missing_postcondition_kind`]
1804 /// on the point-domain surface. See
1805 /// [`Self::has_unique_missing_precondition_kind`] for the full
1806 /// rationale — the two methods share ONE lift motivation, ONE
1807 /// fail-before-pass-after composition-law pin, and ONE two-surface
1808 /// parity contract with the point-domain
1809 /// [`crate::boundary::Boundary`] cardinality-mid-endpoint peer
1810 /// methods.
1811 #[must_use]
1812 pub fn has_unique_missing_postcondition_kind(&self) -> bool {
1813 self.postconditions.has_unique_missing_kind()
1814 }
1815
1816 /// `true` iff `preconditions ∪ postconditions` is MISSING AT
1817 /// LEAST TWO [`ConditionKind::ALL`] variants — the union arm of
1818 /// the (precondition, postcondition, condition-union) cardinality-
1819 /// many-arm triad on [`EphemeralSpec`] closing the "≥ 2 holes
1820 /// remaining" arm on the union of the two condition slots. The
1821 /// Boolean cardinality many-arm fast-path peer of
1822 /// [`Self::has_unique_missing_condition_kind`] (=1 arm) and
1823 /// [`Self::is_condition_kind_saturated`] (=0 arm): closes the
1824 /// {0, 1, ≥2} trichotomy on the missing axis at the ephemeral
1825 /// union struct layer.
1826 ///
1827 /// Composed body: constructs a two-step-short-circuit walk over
1828 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
1829 /// union primitive negated — pulls up to two hits off the
1830 /// filtered iterator; the primitive returns `true` iff BOTH the
1831 /// first and the second are [`Some`]. Byte-for-byte peer of
1832 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1833 /// one slice-layer down, lifted to compose against
1834 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1835 /// against a single slice's `has_kind`.
1836 ///
1837 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
1838 ///
1839 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1840 /// two-step short-circuit body composed against the point-domain
1841 /// surface's own union primitive. Both methods compose against
1842 /// the SAME slice-level substrate primitive
1843 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1844 /// via the two-slice union — a regression at the per-slice many-
1845 /// arm walk fails at that primitive's tests rather than as silent
1846 /// drift at either struct-level many-missing caller.
1847 ///
1848 /// # Sibling to [`Self::missing_condition_kinds`] /
1849 /// [`Self::missing_condition_kind_count`]
1850 ///
1851 /// Cardinality-many-arm Boolean projection of the widened +
1852 /// scalar closed-set-complement primitives on the ephemeral-union
1853 /// surface — where those primitives return the FULL missing SET
1854 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
1855 /// in `0..=ConditionKind::ALL.len()`),
1856 /// `has_multiple_missing_condition_kind` collapses either the
1857 /// widened primitive to its ≥ 2-length Boolean or the scalar to
1858 /// its `>= 2` cardinality-many-arm Boolean. Strictly cheaper than
1859 /// either widened primitive on every arm with `≥ 2` missing kinds
1860 /// because the negation short-circuits at the second missing kind
1861 /// rather than allocating the closed-set-complement scan or
1862 /// walking every slot to build the scalar cardinality.
1863 ///
1864 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1865 /// preserves proofs — the cardinality-many-arm projection on the
1866 /// missing axis composes the SAME two-step short-circuit walk
1867 /// under a two-slice union negation on both this ephemeral
1868 /// surface and the point-domain
1869 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
1870 /// (generation over composition — a new [`ConditionKind`]
1871 /// variant reaches both surfaces' cardinality-many-arm triads
1872 /// mechanically through the delegated union primitive).
1873 #[must_use]
1874 pub fn has_multiple_missing_condition_kind(&self) -> bool {
1875 let mut it = ConditionKind::ALL
1876 .iter()
1877 .copied()
1878 .filter(|k| !self.has_condition_kind(*k));
1879 it.next().is_some() && it.next().is_some()
1880 }
1881
1882 /// `true` iff [`Self::preconditions`] is MISSING AT LEAST TWO
1883 /// [`ConditionKind::ALL`] variants — the precondition-side arm of
1884 /// the (precondition, postcondition, condition-union) cardinality-
1885 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
1886 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1887 /// over [`Self::preconditions`].
1888 ///
1889 /// Peer of
1890 /// [`crate::boundary::Boundary::has_multiple_missing_precondition_kind`]
1891 /// on the point-domain surface — both peers compose against the
1892 /// SAME slice-level substrate primitive so a regression at the
1893 /// per-slice two-step short-circuit walk under negation fails at
1894 /// that primitive's tests rather than as silent drift at either
1895 /// struct-level arm.
1896 #[must_use]
1897 pub fn has_multiple_missing_precondition_kind(&self) -> bool {
1898 self.preconditions.has_multiple_missing_kinds()
1899 }
1900
1901 /// `true` iff [`Self::postconditions`] is MISSING AT LEAST TWO
1902 /// [`ConditionKind::ALL`] variants — the postcondition-side arm of
1903 /// the (precondition, postcondition, condition-union) cardinality-
1904 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
1905 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1906 /// over [`Self::postconditions`].
1907 ///
1908 /// Peer of
1909 /// [`crate::boundary::Boundary::has_multiple_missing_postcondition_kind`]
1910 /// on the point-domain surface. See
1911 /// [`Self::has_multiple_missing_precondition_kind`] for the full
1912 /// rationale — the two methods share ONE lift motivation, ONE
1913 /// fail-before-pass-after composition-law pin, and ONE two-surface
1914 /// parity contract with the point-domain
1915 /// [`crate::boundary::Boundary`] cardinality-many-arm peer
1916 /// methods.
1917 #[must_use]
1918 pub fn has_multiple_missing_postcondition_kind(&self) -> bool {
1919 self.postconditions.has_multiple_missing_kinds()
1920 }
1921
1922 /// `true` iff `preconditions ∪ postconditions` is MISSING AT MOST
1923 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
1924 /// (precondition, postcondition, condition-union) cardinality
1925 /// "≤ 1" triad on [`EphemeralSpec`] closing the "at most one hole
1926 /// remaining" arm on the union of the two condition slots. The
1927 /// Boolean cardinality "≤ 1" negation peer of
1928 /// [`Self::has_multiple_missing_condition_kind`] (≥ 2 many-arm)
1929 /// under the definitional negation
1930 /// `!has_multiple_missing_condition_kind`, and the trichotomy-
1931 /// union peer of [`Self::is_condition_kind_saturated`] (=0
1932 /// zero-arm) OR [`Self::has_unique_missing_condition_kind`] (=1
1933 /// mid-endpoint) — names the arrangement space where the
1934 /// ephemeral spec is SATURATED-OR-NEAR-SATURATED on the union
1935 /// (zero or exactly one kind missing across the union of the two
1936 /// slices).
1937 ///
1938 /// Composed body: `!self.has_multiple_missing_condition_kind()`
1939 /// — a definitional negation of the many-arm union primitive.
1940 /// Short-circuits transitively through
1941 /// [`Self::has_multiple_missing_condition_kind`]'s two-step short-
1942 /// circuit walk over [`ConditionKind::ALL`] under negated
1943 /// [`Self::has_condition_kind`]. Byte-for-byte peer of
1944 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
1945 /// one slice-layer down, lifted to compose against
1946 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1947 /// against a single slice's `has_kind`.
1948 ///
1949 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
1950 ///
1951 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1952 /// definitional-negation body composed against the point-domain
1953 /// surface's own many-arm union primitive. Both methods compose
1954 /// against the SAME slice-level substrate primitive
1955 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
1956 /// via the two-slice union — a regression at the per-slice "≤ 1"
1957 /// negation fails at that primitive's tests rather than as silent
1958 /// drift at either struct-level near-saturation-or-saturated
1959 /// caller.
1960 ///
1961 /// # Sibling to [`Self::missing_condition_kinds`] /
1962 /// [`Self::missing_condition_kind_count`]
1963 ///
1964 /// Cardinality "≤ 1" Boolean projection of the widened + scalar
1965 /// closed-set-complement primitives on the ephemeral-union
1966 /// surface — where those primitives return the FULL missing SET
1967 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
1968 /// in `0..=ConditionKind::ALL.len()`),
1969 /// `has_at_most_one_missing_condition_kind` collapses either the
1970 /// widened primitive to its `≤ 1`-length Boolean or the scalar
1971 /// to its `<= 1` cardinality-negation Boolean. Strictly cheaper
1972 /// than either widened primitive on every arm because the
1973 /// underlying many-arm walk short-circuits at the second missing
1974 /// kind — a subsequent bit-flip surfaces at ONE substrate call
1975 /// with no allocation.
1976 ///
1977 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1978 /// preserves proofs — the cardinality "≤ 1" projection on the
1979 /// missing axis composes the SAME definitional negation of the
1980 /// many-arm two-step short-circuit walk on both this ephemeral
1981 /// surface and the point-domain [`crate::boundary::Boundary`]
1982 /// surface). THEORY.md §VI.1 (generation over composition — a
1983 /// new [`ConditionKind`] variant reaches both surfaces'
1984 /// cardinality "≤ 1" triads mechanically through the delegated
1985 /// union primitive).
1986 #[must_use]
1987 pub fn has_at_most_one_missing_condition_kind(&self) -> bool {
1988 !self.has_multiple_missing_condition_kind()
1989 }
1990
1991 /// `true` iff [`Self::preconditions`] is MISSING AT MOST ONE
1992 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1993 /// the (precondition, postcondition, condition-union) cardinality
1994 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
1995 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
1996 /// over [`Self::preconditions`].
1997 ///
1998 /// Peer of
1999 /// [`crate::boundary::Boundary::has_at_most_one_missing_precondition_kind`]
2000 /// on the point-domain surface — both peers compose against the
2001 /// SAME slice-level substrate primitive so a regression at the
2002 /// per-slice "≤ 1" negation fails at that primitive's tests
2003 /// rather than as silent drift at either struct-level arm.
2004 #[must_use]
2005 pub fn has_at_most_one_missing_precondition_kind(&self) -> bool {
2006 self.preconditions.has_at_most_one_missing_kind()
2007 }
2008
2009 /// `true` iff [`Self::postconditions`] is MISSING AT MOST ONE
2010 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
2011 /// the (precondition, postcondition, condition-union) cardinality
2012 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
2013 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2014 /// over [`Self::postconditions`].
2015 ///
2016 /// Peer of
2017 /// [`crate::boundary::Boundary::has_at_most_one_missing_postcondition_kind`]
2018 /// on the point-domain surface. See
2019 /// [`Self::has_at_most_one_missing_precondition_kind`] for the
2020 /// full rationale — the two methods share ONE lift motivation,
2021 /// ONE fail-before-pass-after composition-law pin, and ONE two-
2022 /// surface parity contract with the point-domain
2023 /// [`crate::boundary::Boundary`] cardinality "≤ 1" peer methods.
2024 #[must_use]
2025 pub fn has_at_most_one_missing_postcondition_kind(&self) -> bool {
2026 self.postconditions.has_at_most_one_missing_kind()
2027 }
2028
2029 /// `true` iff `preconditions ∪ postconditions` carries NO
2030 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2031 /// — the peer of
2032 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
2033 /// [`EphemeralSpec`] sugar surface.
2034 ///
2035 /// # Composed body — byte-identical to
2036 /// [`crate::boundary::Boundary::lacks_condition_kind`]
2037 ///
2038 /// `!self.has_condition_kind(kind)` — the definitional negation of
2039 /// the two-slice union primitive [`Self::has_condition_kind`].
2040 /// Byte-identical to the peer method on the point-domain
2041 /// [`crate::boundary::Boundary`] surface — both compose against
2042 /// the SAME slice-level substrate primitive
2043 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] via the
2044 /// two-slice union so a regression at the per-slice negation
2045 /// fails at that primitive's tests rather than as silent drift at
2046 /// either struct-level complement caller.
2047 ///
2048 /// # Sibling to [`Self::missing_condition_kinds`] /
2049 /// [`Self::missing_condition_kind_count`]
2050 ///
2051 /// Per-kind Boolean projection of the widened + scalar closed-set-
2052 /// complement primitives on the ephemeral-union surface — where
2053 /// those primitives return the FULL missing SET (a `Vec` of every
2054 /// absent kind) and its cardinality (a `usize`),
2055 /// `lacks_condition_kind` collapses the missing SET to its
2056 /// per-kind membership Boolean for ONE addressed kind. Strictly
2057 /// cheaper than reaching for the widened primitive on every
2058 /// per-kind question because the negation short-circuits through
2059 /// [`Self::has_condition_kind`] rather than allocating the
2060 /// closed-set-complement scan.
2061 ///
2062 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2063 /// preserves proofs — the per-kind closed-set-complement
2064 /// projection composes the SAME two-slice union negation on both
2065 /// this ephemeral surface and the point-domain
2066 /// [`crate::boundary::Boundary`] surface under definitional
2067 /// negation). THEORY.md §VI.1 (generation over composition — a
2068 /// future [`ConditionKind`] variant reaches both surfaces'
2069 /// per-kind-complement triads mechanically through the delegated
2070 /// union primitive).
2071 #[must_use]
2072 pub fn lacks_condition_kind(&self, kind: ConditionKind) -> bool {
2073 !self.has_condition_kind(kind)
2074 }
2075
2076 /// `true` iff [`Self::preconditions`] carries NO
2077 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2078 /// — the precondition-side arm of the (precondition, postcondition,
2079 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
2080 /// Thin typed delegate to
2081 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
2082 /// [`Self::preconditions`].
2083 ///
2084 /// Peer of
2085 /// [`crate::boundary::Boundary::lacks_precondition_kind`] on the
2086 /// point-domain surface — both peers compose against the SAME
2087 /// slice-level substrate primitive so a regression at the
2088 /// per-slice negation fails at that primitive's tests rather than
2089 /// as silent drift at either struct-level arm.
2090 #[must_use]
2091 pub fn lacks_precondition_kind(&self, kind: ConditionKind) -> bool {
2092 self.preconditions.lacks_kind(kind)
2093 }
2094
2095 /// `true` iff [`Self::postconditions`] carries NO
2096 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2097 /// — the postcondition-side arm of the (precondition, postcondition,
2098 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
2099 /// Thin typed delegate to
2100 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
2101 /// [`Self::postconditions`].
2102 ///
2103 /// Peer of
2104 /// [`crate::boundary::Boundary::lacks_postcondition_kind`] on the
2105 /// point-domain surface. See [`Self::lacks_precondition_kind`] for
2106 /// the full rationale — the two methods share ONE lift motivation,
2107 /// ONE fail-before-pass-after composition-law pin, and ONE
2108 /// two-surface parity contract with the point-domain
2109 /// [`crate::boundary::Boundary`] per-kind-complement peer methods.
2110 #[must_use]
2111 pub fn lacks_postcondition_kind(&self, kind: ConditionKind) -> bool {
2112 self.postconditions.lacks_kind(kind)
2113 }
2114
2115 /// `true` iff `preconditions ∪ postconditions` carries at least
2116 /// one [`crate::boundary::Condition`] with the given
2117 /// [`ConditionKind`] AND carries no [`crate::boundary::Condition`]
2118 /// whose kind is anything OTHER than `kind` — the union arm of
2119 /// the (precondition, postcondition, condition-union) kind-scoped
2120 /// strict-refinement triad on [`EphemeralSpec`], byte-for-byte
2121 /// peer of the point-domain
2122 /// [`crate::boundary::Boundary::has_only_condition_kind`] under
2123 /// the same fused-closed-set-walk body.
2124 ///
2125 /// # Composed body
2126 ///
2127 /// A FUSED short-circuit closed-set walk over
2128 /// [`ConditionKind::ALL`] under [`Self::has_condition_kind`] that
2129 /// returns `false` at the EARLIEST kind whose presence spans
2130 /// either slice's populated set and is NOT `kind`, and returns
2131 /// `true` iff the sweep completes with `kind` seen as the sole
2132 /// distinct populated kind. Strictly cheaper than the widened
2133 /// composition
2134 /// `self.distinct_condition_kinds() == vec![kind]` (which
2135 /// allocates the distinct-kind Vec before the equality test) or
2136 /// the (pre, post) AND-of-strict-refinement
2137 /// `self.preconditions.has_only_kind(kind)
2138 /// && self.postconditions.has_only_kind(kind)` (which is TOO
2139 /// STRICT — a single-slice-populated arrangement whose empty side
2140 /// returns `false` fails this AND but IS well-formed on the
2141 /// union).
2142 ///
2143 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_only_condition_kind`]
2144 ///
2145 /// Byte-identical signature `(&Self, ConditionKind) -> bool`,
2146 /// byte-identical fused-closed-set-walk body, on the point-domain
2147 /// surface whose pre/post condition vectors live inside a
2148 /// [`crate::boundary::Boundary`] slot. Both methods compose
2149 /// against the SAME slice-level substrate primitive
2150 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] via the
2151 /// two-slice union composed through [`Self::has_condition_kind`]
2152 /// — a regression at the per-slice fused walk fails at that
2153 /// primitive's tests rather than as silent drift at either
2154 /// struct-level kind-scoped-strict-refinement caller.
2155 ///
2156 /// # Compounding
2157 ///
2158 /// A future coherence check verifying "every ephemeral spec whose
2159 /// postconditions carry ONLY `ClosedLoopAuth` (no `JobAttested`,
2160 /// no `Cel`, ...) is a well-formed closed-loop probe" reads
2161 /// `spec.has_only_condition_kind(ConditionKind::ClosedLoopAuth)`
2162 /// at ONE call site rather than restating either widened
2163 /// composition. A `has-only-<kind>` require-tag classifier arm on
2164 /// the ephemeral surface reaches this primitive at ONE substrate
2165 /// call — byte-for-byte peer of the tagged-union
2166 /// `has-only-<kind>` classifier one struct-layer up under the
2167 /// SAME fused short-circuit walk shape.
2168 ///
2169 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2170 /// preserves proofs — the kind-scoped strict-refinement projection
2171 /// composes the SAME fused short-circuit closed-set walk under
2172 /// [`Self::has_condition_kind`] on both this ephemeral surface
2173 /// and the point-domain [`crate::boundary::Boundary`] surface).
2174 /// THEORY.md §VI.1 (generation over composition — a future
2175 /// [`ConditionKind`] variant reaches both surfaces' kind-scoped
2176 /// strict-refinement triads mechanically through the delegated
2177 /// union primitive).
2178 #[must_use]
2179 pub fn has_only_condition_kind(&self, kind: ConditionKind) -> bool {
2180 let mut saw_kind = false;
2181 for k in ConditionKind::ALL {
2182 if !self.has_condition_kind(k) {
2183 continue;
2184 }
2185 if k == kind {
2186 saw_kind = true;
2187 } else {
2188 return false;
2189 }
2190 }
2191 saw_kind
2192 }
2193
2194 /// `true` iff [`Self::preconditions`] carries at least one
2195 /// [`crate::boundary::Condition`] with the given
2196 /// [`ConditionKind`] AND carries no
2197 /// [`crate::boundary::Condition`] whose kind is anything OTHER
2198 /// than `kind` — the precondition-side arm of the (precondition,
2199 /// postcondition, condition-union) kind-scoped strict-refinement
2200 /// triad on [`EphemeralSpec`]. Thin typed delegate to
2201 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] over
2202 /// [`Self::preconditions`].
2203 ///
2204 /// Peer of
2205 /// [`crate::boundary::Boundary::has_only_precondition_kind`] on
2206 /// the point-domain surface — both peers compose against the SAME
2207 /// slice-level substrate primitive so a regression at the per-
2208 /// slice fused walk fails at that primitive's tests rather than
2209 /// as silent drift at either struct-level arm.
2210 #[must_use]
2211 pub fn has_only_precondition_kind(&self, kind: ConditionKind) -> bool {
2212 self.preconditions.has_only_kind(kind)
2213 }
2214
2215 /// `true` iff [`Self::postconditions`] carries at least one
2216 /// [`crate::boundary::Condition`] with the given
2217 /// [`ConditionKind`] AND carries no
2218 /// [`crate::boundary::Condition`] whose kind is anything OTHER
2219 /// than `kind` — the postcondition-side arm of the (precondition,
2220 /// postcondition, condition-union) kind-scoped strict-refinement
2221 /// triad on [`EphemeralSpec`]. Thin typed delegate to
2222 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] over
2223 /// [`Self::postconditions`].
2224 ///
2225 /// Peer of
2226 /// [`crate::boundary::Boundary::has_only_postcondition_kind`] on
2227 /// the point-domain surface. See [`Self::has_only_precondition_kind`]
2228 /// for the full rationale — the two methods share ONE lift
2229 /// motivation, ONE fail-before-pass-after composition-law pin,
2230 /// and ONE two-surface parity contract with the point-domain
2231 /// [`crate::boundary::Boundary`] kind-scoped-strict-refinement
2232 /// peer methods.
2233 #[must_use]
2234 pub fn has_only_postcondition_kind(&self, kind: ConditionKind) -> bool {
2235 self.postconditions.has_only_kind(kind)
2236 }
2237
2238 /// `true` iff `preconditions ∪ postconditions` carries NO
2239 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2240 /// AND carries at least one [`crate::boundary::Condition`] for
2241 /// every OTHER [`ConditionKind`] — the union arm of the
2242 /// (precondition, postcondition, condition-union) kind-scoped
2243 /// strict-refinement-on-missing triad on [`EphemeralSpec`], byte-
2244 /// for-byte peer of the point-domain
2245 /// [`crate::boundary::Boundary::lacks_only_condition_kind`] under
2246 /// the same fused-closed-set-walk body on the missing axis.
2247 ///
2248 /// # Composed body
2249 ///
2250 /// A FUSED short-circuit closed-set walk over
2251 /// [`ConditionKind::ALL`] under [`Self::has_condition_kind`] that
2252 /// skips every populated kind, returns `false` at the EARLIEST
2253 /// kind whose absence spans both slices' missing sets and is NOT
2254 /// `kind`, and returns `true` iff the sweep completes with `kind`
2255 /// seen as the sole missing kind. Strictly cheaper than the
2256 /// widened composition
2257 /// `self.missing_condition_kinds() == vec![kind]` (which allocates
2258 /// the missing-kind Vec before the equality test) or the
2259 /// (pre AND post) AND-of-strict-refinement
2260 /// `self.preconditions.lacks_only_kind(kind)
2261 /// && self.postconditions.lacks_only_kind(kind)` (which is TOO
2262 /// STRICT — a single-slice-populated arrangement whose empty side
2263 /// returns `false` fails this AND but IS well-formed on the
2264 /// union).
2265 ///
2266 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::lacks_only_condition_kind`]
2267 ///
2268 /// Byte-identical signature `(&Self, ConditionKind) -> bool`,
2269 /// byte-identical fused-closed-set-walk body under complement, on
2270 /// the point-domain surface whose pre/post condition vectors live
2271 /// inside a [`crate::boundary::Boundary`] slot. Both methods
2272 /// compose against the SAME slice-level substrate primitive
2273 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] via
2274 /// the two-slice union composed through
2275 /// [`Self::has_condition_kind`] — a regression at the per-slice
2276 /// fused walk under complement fails at that primitive's tests
2277 /// rather than as silent drift at either struct-level kind-scoped-
2278 /// strict-refinement-on-missing caller.
2279 ///
2280 /// # Compounding
2281 ///
2282 /// A future coherence check verifying "every partially-attested
2283 /// ephemeral closed-loop probe is missing ONLY the
2284 /// `ClosedLoopAuth` postcondition" reads
2285 /// `spec.lacks_only_condition_kind(ConditionKind::ClosedLoopAuth)`
2286 /// at ONE call site rather than restating either widened
2287 /// composition. A `lacks-only-<kind>` require-tag classifier arm
2288 /// on the ephemeral surface reaches this primitive at ONE
2289 /// substrate call — byte-for-byte peer of the tagged-union
2290 /// `lacks-only-<kind>` classifier one struct-layer up under the
2291 /// SAME fused short-circuit walk shape.
2292 ///
2293 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2294 /// preserves proofs — the kind-scoped strict-refinement projection
2295 /// on the missing axis composes the SAME fused short-circuit
2296 /// closed-set walk under [`Self::has_condition_kind`] on both this
2297 /// ephemeral surface and the point-domain
2298 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2299 /// (generation over composition — a future [`ConditionKind`]
2300 /// variant reaches both surfaces' kind-scoped-strict-refinement-
2301 /// on-missing triads mechanically through the delegated union
2302 /// primitive).
2303 #[must_use]
2304 pub fn lacks_only_condition_kind(&self, kind: ConditionKind) -> bool {
2305 let mut saw_kind = false;
2306 for k in ConditionKind::ALL {
2307 if self.has_condition_kind(k) {
2308 continue;
2309 }
2310 if k == kind {
2311 saw_kind = true;
2312 } else {
2313 return false;
2314 }
2315 }
2316 saw_kind
2317 }
2318
2319 /// `true` iff [`Self::preconditions`] carries NO
2320 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2321 /// AND carries at least one [`crate::boundary::Condition`] for
2322 /// every OTHER [`ConditionKind`] — the precondition-side arm of
2323 /// the (precondition, postcondition, condition-union) kind-scoped-
2324 /// strict-refinement-on-missing triad on [`EphemeralSpec`]. Thin
2325 /// typed delegate to
2326 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] over
2327 /// [`Self::preconditions`].
2328 ///
2329 /// Peer of
2330 /// [`crate::boundary::Boundary::lacks_only_precondition_kind`] on
2331 /// the point-domain surface — both peers compose against the SAME
2332 /// slice-level substrate primitive so a regression at the per-
2333 /// slice fused walk under complement fails at that primitive's
2334 /// tests rather than as silent drift at either struct-level arm.
2335 #[must_use]
2336 pub fn lacks_only_precondition_kind(&self, kind: ConditionKind) -> bool {
2337 self.preconditions.lacks_only_kind(kind)
2338 }
2339
2340 /// `true` iff [`Self::postconditions`] carries NO
2341 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2342 /// AND carries at least one [`crate::boundary::Condition`] for
2343 /// every OTHER [`ConditionKind`] — the postcondition-side arm of
2344 /// the (precondition, postcondition, condition-union) kind-scoped-
2345 /// strict-refinement-on-missing triad on [`EphemeralSpec`]. Thin
2346 /// typed delegate to
2347 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] over
2348 /// [`Self::postconditions`].
2349 ///
2350 /// Peer of
2351 /// [`crate::boundary::Boundary::lacks_only_postcondition_kind`] on
2352 /// the point-domain surface. See [`Self::lacks_only_precondition_kind`]
2353 /// for the full rationale — the two methods share ONE lift
2354 /// motivation, ONE fail-before-pass-after composition-law pin,
2355 /// and ONE two-surface parity contract with the point-domain
2356 /// [`crate::boundary::Boundary`] kind-scoped-strict-refinement-
2357 /// on-missing peer methods.
2358 #[must_use]
2359 pub fn lacks_only_postcondition_kind(&self, kind: ConditionKind) -> bool {
2360 self.postconditions.lacks_only_kind(kind)
2361 }
2362
2363 /// True iff this ephemeral spec's stored [`TeardownPolicy`] equals
2364 /// `kind` — the substrate primitive that owns the
2365 /// (`&EphemeralSpec`, [`TeardownPolicy`]) → `bool` presence-probe
2366 /// shape on the sugar-surface type.
2367 ///
2368 /// # Peer to [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
2369 ///
2370 /// [`EphemeralLifetime::has_teardown_policy`] carries the same
2371 /// `(&self, TeardownPolicy) -> bool` signature on the point-surface
2372 /// carrier ([`ProcessSpec`]'s nested [`crate::lifetime::Lifetime`]
2373 /// slot reached through
2374 /// [`crate::lifetime::Lifetime::resolved_ephemeral`]); this peer
2375 /// composes byte-identical `==` semantics on
2376 /// [`EphemeralSpec`]'s direct `teardown: TeardownPolicy` scalar
2377 /// slot, so both surfaces' `teardown-policy-<kind>` require-tag
2378 /// families ([`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
2379 /// on the point surface, this peer on the ephemeral surface) route
2380 /// through the SAME scalar `==` shape. A future normalization at
2381 /// the probe shape (a widened return carrying a `TerminatePolicy`
2382 /// disambiguator, a debug-build assertion on operator-set vs
2383 /// defaulted overrides, a fleet-wide warn on `Never` combined with
2384 /// short TTLs) lands at ONE site per surface and every downstream
2385 /// `teardown-policy-<kind>` require-tag family + closed-set audit
2386 /// dispatcher picks it up mechanically.
2387 ///
2388 /// # Semantics — VARIANT match, not POPULATED slot
2389 ///
2390 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
2391 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
2392 /// absent state to detect. `has_teardown_policy(kind)` returns
2393 /// `true` iff `self.teardown == kind`. On a hand-authored
2394 /// [`EphemeralSpec`] that omits `:teardown` from the
2395 /// `(defephemeral …)` form (or a Rust builder that reaches
2396 /// [`TeardownPolicy::default`]) the probe returns `true` for
2397 /// [`TeardownPolicy::Always`] and `false` for every other variant
2398 /// — distinct from the Option-slot axis where a default carrier
2399 /// returns `false` for EVERY kind. An operator who left
2400 /// `:teardown` at the substrate default IS configured for
2401 /// `Always`, and a `:requires (teardown-policy-Always)` check
2402 /// should pass; only an operator who deliberately overrode the
2403 /// policy to `OnAttested` / `OnFailed` / `Never` fails the tag on
2404 /// this axis.
2405 ///
2406 /// # Corner — (required-scalar-child)
2407 ///
2408 /// Fresh corner on the ephemeral surface's presence-probe algebra:
2409 /// [`EphemeralSpec`] has no Option-parent hop between the sugar
2410 /// struct and the `teardown` scalar (the point surface reaches
2411 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
2412 /// through the Option-parent `resolved_ephemeral()` gate), so the
2413 /// probe body is a bare scalar `==` on a required field. Distinct
2414 /// from [`Self::has_condition_kind`] on this same surface, which
2415 /// walks a `Vec<Condition>` slice-child.
2416 ///
2417 /// # Compounding
2418 ///
2419 /// The ephemeral require-tag classifier composes this primitive
2420 /// with the closed-set `FromStr` autoderived on [`TeardownPolicy`]
2421 /// through the `strip_and_classify_prefixed_kind` substrate to
2422 /// publish a `teardown-policy-<kind>` prefix family byte-for-byte
2423 /// symmetrical with the point surface's family via
2424 /// [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]. A
2425 /// future fifth [`TeardownPolicy`] variant added to `ALL` (a
2426 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
2427 /// reaches BOTH surfaces' `teardown-policy-<kind>` prefix families
2428 /// through the SAME closed-set walk with no per-caller edit — the
2429 /// two-surface symmetry means adding a variant on the closed set
2430 /// publishes it in lockstep across every downstream consumer.
2431 ///
2432 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2433 /// preserves proofs — the scalar-carrier presence-probe body lives
2434 /// at ONE substrate site per surface so every downstream
2435 /// (`teardown-policy-<kind>` require-tag families on both surfaces
2436 /// in tatara-check, closed-set audit dispatchers, future variant
2437 /// additions on [`TeardownPolicy`]) binds through the SAME
2438 /// `has(kind)` shape rather than restating the `<eph>.teardown ==
2439 /// kind` closure body at each call site). THEORY.md §VI.1
2440 /// (generation over composition — a future variant lands at ONE
2441 /// `ALL` entry + one `as_str` arm on the closed set and the probe
2442 /// picks it up mechanically without further per-consumer edits).
2443 #[must_use]
2444 pub fn has_teardown_policy(&self, kind: TeardownPolicy) -> bool {
2445 self.teardown == kind
2446 }
2447
2448 /// Derived-bool-predicate presence probe on the stored
2449 /// [`Self::teardown`] slot — `true` iff this ephemeral sugar's
2450 /// [`TeardownPolicy`] would auto-SIGTERM the Process on the
2451 /// queried [`ProcessPhase`] transition (as read through
2452 /// [`TeardownPolicy::should_teardown_on`]).
2453 ///
2454 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
2455 ///
2456 /// Same shape, same axis, one refinement lower: the point-surface
2457 /// peer on [`crate::lifetime::EphemeralLifetime`] composes the SAME
2458 /// [`TeardownPolicy::should_teardown_on`] predicate against the
2459 /// SAME stored `teardown_policy` slot; this method composes the
2460 /// same predicate against the sugar surface's flattened
2461 /// [`Self::teardown`] slot. Both bodies delegate to the ONE
2462 /// substrate owner [`TeardownPolicy::should_teardown_on`], so a
2463 /// regression at the (policy, phase) → bool truth table surfaces
2464 /// at THAT primitive's tests rather than as silent drift at
2465 /// either struct-level caller.
2466 ///
2467 /// # Corner — (required-scalar-parent × derived-bool-predicate-child)
2468 ///
2469 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
2470 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
2471 /// Option-parent hop between the sugar struct and the `teardown`
2472 /// scalar (the point surface reaches
2473 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
2474 /// through the Option-parent `resolved_ephemeral()` gate). The
2475 /// probe body is a bare predicate application on a required
2476 /// field. Distinct from [`Self::has_teardown_policy`] on this
2477 /// same surface, which reads the raw stored variant for equality
2478 /// (`self.teardown == kind`) rather than the derived firing-arm
2479 /// predicate against a [`ProcessPhase`] argument.
2480 ///
2481 /// # Compounding
2482 ///
2483 /// The ephemeral require-tag classifier composes this primitive
2484 /// with the closed-set [`crate::phase::ProcessPhase`]'s
2485 /// autoderived `FromStr` through the
2486 /// `strip_and_classify_prefixed_kind` substrate to publish a
2487 /// `teardown-fires-on-<phase>` prefix family byte-for-byte
2488 /// symmetrical with the point surface's family via
2489 /// [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`].
2490 /// A future fifth [`TeardownPolicy`] variant added to `ALL` (a
2491 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
2492 /// reaches BOTH surfaces' `teardown-fires-on-<phase>` prefix
2493 /// families through the SAME
2494 /// [`TeardownPolicy::should_teardown_on`] match with no per-
2495 /// caller edit — the two-surface symmetry means adding a variant
2496 /// on the closed set publishes it in lockstep across every
2497 /// downstream consumer.
2498 ///
2499 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2500 /// preserves proofs — the derived-bool-predicate presence-probe
2501 /// body lives at ONE substrate site per surface, both composing
2502 /// the SAME [`TeardownPolicy::should_teardown_on`] projection, so
2503 /// every downstream (`teardown-fires-on-<phase>` require-tag
2504 /// families on both surfaces in tatara-check, closed-set audit
2505 /// dispatchers, future variant additions on either
2506 /// [`TeardownPolicy`] or [`crate::phase::ProcessPhase`]) binds
2507 /// through the SAME `has_teardown_firing_on(phase)` shape rather
2508 /// than restating the `<eph>.teardown.should_teardown_on(phase)`
2509 /// closure body at each call site). THEORY.md §VI.1 (generation
2510 /// over composition — a future variant lands at ONE `ALL` entry +
2511 /// one `as_str` arm + one `should_teardown_on` arm on the closed
2512 /// set and the probe picks it up mechanically without further
2513 /// per-consumer edits).
2514 #[must_use]
2515 pub const fn has_teardown_firing_on(&self, phase: ProcessPhase) -> bool {
2516 self.teardown.should_teardown_on(phase)
2517 }
2518
2519 /// Resolve the operator-authored [`Self::classification`] slot to
2520 /// the concrete [`Classification`] the point surface sees, filling
2521 /// `None` through the same [`default_ephemeral_class`] baseline the
2522 /// `From<EphemeralSpec> for ProcessSpec` lowering uses when the
2523 /// operator omits `:classification` from the `(defephemeral …)`
2524 /// form. Returns [`Cow::Borrowed`] on the populated arm (zero
2525 /// allocation), else [`Cow::Owned`] with the workspace-baseline
2526 /// `(Gate, Compute, Bounded, Monotone, Internal)` value the sibling
2527 /// primitive [`Classification::gate_compute`] owns.
2528 ///
2529 /// # ONE substrate primitive for `Option<Classification>` resolution
2530 ///
2531 /// This is the ONE `EphemeralSpec`-inherent primitive that owns the
2532 /// `Option<Classification>` → resolved-[`Classification`] walk.
2533 /// Every downstream classification-axis presence probe on the
2534 /// [`EphemeralSpec`] surface ([`Self::has_point_type`],
2535 /// [`Self::has_substrate`], [`Self::has_calm`],
2536 /// [`Self::has_data_classification`], [`Self::has_horizon_kind`],
2537 /// [`Self::has_optimization_direction`], [`Self::has_input_arity`],
2538 /// [`Self::has_output_arity`]) routes through THIS
2539 /// primitive so the "`None` fills through
2540 /// [`default_ephemeral_class`]" resolution lives at ONE site rather
2541 /// than being restated in each per-axis probe body. A future
2542 /// regression on the fill-through (a shift from the `(Gate,
2543 /// Compute, …)` baseline to a different `default_ephemeral_class`
2544 /// body, a shift from the `Option`-carrier shape to a
2545 /// serde-defaulted required-field carrier, an eventual audit hook
2546 /// naming the resolved-vs-authored provenance) lands at ONE site
2547 /// and every downstream axis-probe on the ephemeral surface picks
2548 /// it up mechanically.
2549 ///
2550 /// # Sibling to the `From<EphemeralSpec>` lowering
2551 ///
2552 /// The lowering `From<EphemeralSpec> for ProcessSpec` fills
2553 /// [`ProcessSpec::classification`] through the SAME
2554 /// `.unwrap_or_else(default_ephemeral_class)` walk that this
2555 /// primitive owns on the borrow-friendly `Cow` return. Both sites
2556 /// resolve the same operator-authored slot through the same default
2557 /// so a future two-surface parity contract on the classification
2558 /// axes (`point-type-<kind>` on both surfaces, `substrate-<kind>`
2559 /// on both surfaces, …) reads identically through the sibling
2560 /// point-surface probe [`Classification::has_<axis>`] on the
2561 /// lowered `ProcessSpec` and through THIS primitive on the same
2562 /// authored [`EphemeralSpec`].
2563 ///
2564 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2565 /// preserves proofs; the `Option<Classification>` resolution body
2566 /// lives at ONE substrate primitive on the ephemeral surface so
2567 /// every downstream classification-axis probe binds through the
2568 /// SAME `resolved_classification()` shape rather than restating
2569 /// the `self.classification.as_ref().unwrap_or(&default_…)`
2570 /// closure body at each callsite. THEORY.md §VI.1 — generation
2571 /// over composition; a future classification-axis peer
2572 /// (`has_substrate`, `has_calm`, …) lands as ONE inherent method
2573 /// that delegates through the resolver's `has_<axis>(kind)` call
2574 /// on the sibling [`Classification`] closed-set primitive with no
2575 /// per-axis restatement of the fill-through logic.
2576 #[must_use]
2577 pub fn resolved_classification(&self) -> Cow<'_, Classification> {
2578 match &self.classification {
2579 Some(c) => Cow::Borrowed(c),
2580 None => Cow::Owned(default_ephemeral_class()),
2581 }
2582 }
2583
2584 /// Overlay a single [`ClassificationAxis`] variant onto this
2585 /// ephemeral spec's authored [`Self::classification`] slot, filling
2586 /// `None` through [`Classification::gate_compute`] before the
2587 /// overlay so the resulting slot carries `Some(_)` regardless of
2588 /// the pre-call state. Fluent chaining primitive: the peer of
2589 /// [`ProcessSpec::gate_compute_with_axis`] (fresh-spec × axis
2590 /// overlay) and [`Classification::with_axis`] (arbitrary-base ×
2591 /// axis overlay) on the ephemeral sugar surface.
2592 ///
2593 /// # Substrate ergonomics
2594 ///
2595 /// Pre-lift the four-line shape `let mut classification =
2596 /// Classification::gate_compute(); classification.<axis> =
2597 /// populated; let spec = EphemeralSpec { classification:
2598 /// Some(classification), ..ephemeral_fixture() };` (and its newer
2599 /// three-line peer `let classification =
2600 /// Classification::gate_compute_with_axis(populated); let spec =
2601 /// EphemeralSpec { classification: Some(classification),
2602 /// ..ephemeral_fixture() };`) recurred at THIRTY-SIX hand-authored
2603 /// callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger
2604 /// inside `tatara-reconciler::bin::tatara-check`'s
2605 /// `evaluate_ephemeral_require_tag_*` classifier-facing test
2606 /// module. Post-lift each callsite reads
2607 /// `let spec = ephemeral_fixture().with_classification_axis(populated);`
2608 /// — one line, one immutable binding, and every per-axis loop
2609 /// dispatches its per-iteration axis mutation through the SAME
2610 /// [`ClassificationAxis::overlay`] trait rather than by directly
2611 /// poking a `classification.<axis>` field or restating the
2612 /// `Some(_)` wrap.
2613 ///
2614 /// # Fluent chaining semantics
2615 ///
2616 /// * `EphemeralSpec { classification: None, .. }
2617 /// .with_classification_axis(axis)` produces
2618 /// `EphemeralSpec { classification:
2619 /// Some(Classification::gate_compute_with_axis(axis)), .. }` —
2620 /// the `None`-arm short-circuit fills through
2621 /// [`Classification::gate_compute`] identically to the sibling
2622 /// [`Self::resolved_classification`] resolver on the read side.
2623 /// * `EphemeralSpec { classification: Some(prior), .. }
2624 /// .with_classification_axis(axis)` produces
2625 /// `EphemeralSpec { classification: Some(prior.with_axis(axis)),
2626 /// .. }` — the axis overlay composes onto the existing carrier
2627 /// via [`ClassificationAxis::overlay`], preserving every other
2628 /// axis slot on `prior`. Chained calls
2629 /// `.with_classification_axis(a).with_classification_axis(b)`
2630 /// compose arbitrary N-axis conjunctions on the ephemeral
2631 /// sugar surface with the same order-independence guarantee
2632 /// [`Classification::with_axis`] carries on distinct-slot axes.
2633 ///
2634 /// # Sibling to [`ProcessSpec::gate_compute_with_axis`]
2635 ///
2636 /// Same (spec-carrier × axis) shape, one refinement lower on
2637 /// the composition-depth axis: `ProcessSpec::gate_compute_with_axis`
2638 /// owns the (fresh-`gate_compute_defaults`-spec × axis-overlay)
2639 /// construction on the point-surface carrier;
2640 /// [`Self::with_classification_axis`] owns the
2641 /// (arbitrary-`EphemeralSpec` × axis-overlay-onto-authored-classification)
2642 /// construction on the ephemeral sugar-surface carrier. Both
2643 /// primitives compose through the SAME
2644 /// [`ClassificationAxis::overlay`] trait so a regression on any
2645 /// axis's overlay surfaces at both composer owners' pin sets
2646 /// simultaneously.
2647 ///
2648 /// # Compounding
2649 ///
2650 /// A future SIXTH classification axis lands as ONE peer
2651 /// `impl ClassificationAxis` — every ephemeral-surface fixture
2652 /// that binds through this primitive picks up the sixth axis
2653 /// mechanically without a `classification.<new-axis> = value;`
2654 /// restatement per site. A future audit dispatcher walking the
2655 /// (ephemeral-surface × axis-loop) shape (per-axis matrix
2656 /// generator, closed-set-sweep sagas, per-axis-XOR-partition-
2657 /// witness synthesis on the ephemeral side) binds through the
2658 /// SAME composer regardless of which axis it targets. Directly
2659 /// benefits the P1 caixa-tatara renderer target
2660 /// (`(defaplicacao …)` → `Process` mechanical lowering test
2661 /// fixtures that construct authored classifications through the
2662 /// ephemeral sugar surface) and future ephemeral-surface XOR-
2663 /// partition landmark tests peer to the point-surface pins in
2664 /// `tatara-check.rs`.
2665 ///
2666 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2667 /// preserves proofs; the [`ClassificationAxis::overlay`] trait
2668 /// owns the axis-dispatch proof at ONE site and this primitive
2669 /// extends the ONE-site guarantee to the (ephemeral-spec ×
2670 /// authored-classification × axis-overlay) construction shape.
2671 /// THEORY.md §VI.1 — generation over composition; the 3-to-4-line
2672 /// hand-authored classification-then-wrap shape recurred at ≥ 36
2673 /// hand-authored callsites past the ★★ PRIME-DIRECTIVE ≥ 2
2674 /// duplication threshold and is lifted onto ONE substrate owner
2675 /// here.
2676 #[must_use]
2677 pub fn with_classification_axis<A: ClassificationAxis>(mut self, axis: A) -> Self {
2678 let mut c = self
2679 .classification
2680 .take()
2681 .unwrap_or_else(Classification::gate_compute);
2682 axis.overlay(&mut c);
2683 self.classification = Some(c);
2684 self
2685 }
2686
2687 /// True iff the resolved [`Classification`] carries the given
2688 /// [`ConvergencePointType`] on its `point_type` slot — byte-for-
2689 /// byte peer of [`Classification::has_point_type`] wrapped through
2690 /// the [`Self::resolved_classification`] resolver so an
2691 /// operator-omitted `:classification` slot reads as the
2692 /// [`default_ephemeral_class`] baseline the sibling
2693 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2694 ///
2695 /// # Two-surface parity contract
2696 ///
2697 /// A given [`EphemeralSpec`] classifies identically through this
2698 /// primitive AND through
2699 /// `<eph.clone().into::<ProcessSpec>>().classification.has_point_type(kind)`
2700 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2701 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2702 /// the lowering side both dereference the same
2703 /// `default_ephemeral_class()` value on `None` and the same
2704 /// authored value on `Some(_)`. This means the ephemeral-surface
2705 /// `point-type-<kind>` `:requires` family in
2706 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2707 /// truth on the SAME authored spec as the point-surface family
2708 /// on the mechanically-lowered `ProcessSpec`.
2709 ///
2710 /// # Sibling to the seven other classification axes
2711 ///
2712 /// FIRST classification-axis peer on the [`EphemeralSpec`]
2713 /// surface. Six future sibling axes on the SAME `Cow`-resolver
2714 /// carrier ([`Self::has_substrate`] opened the SECOND,
2715 /// [`Self::has_calm`] the THIRD,
2716 /// [`Self::has_data_classification`] the FOURTH,
2717 /// [`Self::has_horizon_kind`] the FIFTH,
2718 /// [`Self::has_optimization_direction`] the SIXTH; then
2719 /// `has_input_arity`, `has_output_arity`) land as one-line
2720 /// wrappers around the SAME resolver + the sibling
2721 /// [`Classification`] closed-set primitive, so a future variant
2722 /// added to [`ConvergencePointType`] (or any of the seven other
2723 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2724 /// families through the SAME closed-set walk with no per-caller
2725 /// edit.
2726 ///
2727 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2728 /// preserves proofs; the classification-axis presence-probe body
2729 /// composes ONE resolver primitive
2730 /// ([`Self::resolved_classification`]) with ONE closed-set
2731 /// primitive ([`Classification::has_point_type`]) so every
2732 /// downstream (`point-type-<kind>` require-tag families on both
2733 /// surfaces in tatara-check, closed-set audit dispatchers, future
2734 /// variant additions on [`ConvergencePointType`]) binds through
2735 /// the SAME `has(kind)` shape rather than restating either the
2736 /// resolver walk or the closed-set equality at the callsite.
2737 #[must_use]
2738 pub fn has_point_type(&self, kind: ConvergencePointType) -> bool {
2739 self.resolved_classification().has_point_type(kind)
2740 }
2741
2742 /// True iff the resolved [`Classification`] carries the given
2743 /// [`SubstrateType`] on its `substrate` slot — byte-for-byte peer
2744 /// of [`Classification::has_substrate`] wrapped through the
2745 /// [`Self::resolved_classification`] resolver so an operator-
2746 /// omitted `:classification` slot reads as the
2747 /// [`default_ephemeral_class`] baseline the sibling
2748 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2749 ///
2750 /// # Two-surface parity contract
2751 ///
2752 /// A given [`EphemeralSpec`] classifies identically through this
2753 /// primitive AND through
2754 /// `<eph.clone().into::<ProcessSpec>>().classification.has_substrate(kind)`
2755 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2756 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2757 /// the lowering side both dereference the same
2758 /// `default_ephemeral_class()` value on `None` and the same
2759 /// authored value on `Some(_)`. This means the ephemeral-surface
2760 /// `substrate-<kind>` `:requires` family in
2761 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2762 /// truth on the SAME authored spec as the point-surface family
2763 /// on the mechanically-lowered `ProcessSpec`.
2764 ///
2765 /// # SECOND classification-axis peer on the ephemeral surface
2766 ///
2767 /// Peer of [`Self::has_point_type`] — both route through the SAME
2768 /// [`Self::resolved_classification`] resolver, so the operator-
2769 /// omitted `:classification` slot's fill-through logic lives at
2770 /// ONE substrate primitive rather than being restated in each
2771 /// per-axis probe body. Five future sibling axes on the SAME
2772 /// `Cow`-resolver carrier ([`Self::has_calm`] opened the THIRD,
2773 /// [`Self::has_data_classification`] the FOURTH,
2774 /// [`Self::has_horizon_kind`] the FIFTH,
2775 /// [`Self::has_optimization_direction`] the SIXTH; then
2776 /// `has_input_arity`, `has_output_arity`) land as one-line
2777 /// wrappers around the SAME resolver + the sibling
2778 /// [`Classification`] closed-set primitive, so a future variant
2779 /// added to [`SubstrateType`] (or any of the six other closed
2780 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
2781 /// through the SAME closed-set walk with no per-caller edit.
2782 ///
2783 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2784 /// preserves proofs; the classification-axis presence-probe body
2785 /// composes ONE resolver primitive
2786 /// ([`Self::resolved_classification`]) with ONE closed-set
2787 /// primitive ([`Classification::has_substrate`]) so every
2788 /// downstream (`substrate-<kind>` require-tag families on both
2789 /// surfaces in tatara-check, closed-set audit dispatchers, future
2790 /// variant additions on [`SubstrateType`]) binds through the
2791 /// SAME `has(kind)` shape rather than restating either the
2792 /// resolver walk or the closed-set equality at the callsite.
2793 #[must_use]
2794 pub fn has_substrate(&self, kind: SubstrateType) -> bool {
2795 self.resolved_classification().has_substrate(kind)
2796 }
2797
2798 /// True iff the resolved [`Classification`] carries the given
2799 /// [`CalmClassification`] on its `calm` slot — byte-for-byte peer
2800 /// of [`Classification::has_calm`] wrapped through the
2801 /// [`Self::resolved_classification`] resolver so an operator-
2802 /// omitted `:classification` slot reads as the
2803 /// [`default_ephemeral_class`] baseline the sibling
2804 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2805 ///
2806 /// # Two-surface parity contract
2807 ///
2808 /// A given [`EphemeralSpec`] classifies identically through this
2809 /// primitive AND through
2810 /// `<eph.clone().into::<ProcessSpec>>().classification.has_calm(kind)`
2811 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2812 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2813 /// the lowering side both dereference the same
2814 /// `default_ephemeral_class()` value on `None` and the same
2815 /// authored value on `Some(_)`. This means the ephemeral-surface
2816 /// `calm-<kind>` `:requires` family in
2817 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2818 /// truth on the SAME authored spec as the point-surface family
2819 /// on the mechanically-lowered `ProcessSpec`.
2820 ///
2821 /// # THIRD classification-axis peer on the ephemeral surface
2822 ///
2823 /// Peer of [`Self::has_point_type`] and [`Self::has_substrate`] —
2824 /// all three route through the SAME
2825 /// [`Self::resolved_classification`] resolver, so the operator-
2826 /// omitted `:classification` slot's fill-through logic lives at
2827 /// ONE substrate primitive rather than being restated in each
2828 /// per-axis probe body. FIRST occupant on the (Option-parent ×
2829 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
2830 /// of the ephemeral-surface presence-probe algebra — distinct
2831 /// from the (Option-parent × NON-DEFAULT-scalar-child) corner
2832 /// the first two classification-axis peers opened, since
2833 /// [`CalmClassification`] carries `#[default] = Monotone` on the
2834 /// closed set. The default-arm short-circuit on the absent-
2835 /// classification arm reads `true` on the [`CalmClassification`]
2836 /// child's `#[default]` variant precisely because BOTH the parent
2837 /// Option's fill-through baseline (`default_ephemeral_class`) AND
2838 /// the child's own `#[default]` land on the SAME variant
2839 /// ([`CalmClassification::Monotone`]) — a two-defaults
2840 /// composition property distinct from the NON-DEFAULT-scalar
2841 /// peers, whose absent-classification arm defaults through a
2842 /// specific chosen baseline (`ConvergencePointType::Gate`,
2843 /// `SubstrateType::Compute`) rather than through the child's own
2844 /// `#[default]`. Four future sibling axes on the SAME
2845 /// `Cow`-resolver carrier ([`Self::has_data_classification`]
2846 /// opened the FOURTH, [`Self::has_horizon_kind`] the FIFTH,
2847 /// [`Self::has_optimization_direction`] the SIXTH; then
2848 /// `has_input_arity`, `has_output_arity`) land as one-line
2849 /// wrappers around the SAME resolver + the sibling
2850 /// [`Classification`] closed-set primitive, so a future variant
2851 /// added to [`CalmClassification`] (or any of the five other
2852 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2853 /// families through the SAME closed-set walk with no per-caller
2854 /// edit.
2855 ///
2856 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2857 /// preserves proofs; the classification-axis presence-probe body
2858 /// composes ONE resolver primitive
2859 /// ([`Self::resolved_classification`]) with ONE closed-set
2860 /// primitive ([`Classification::has_calm`]) so every downstream
2861 /// (`calm-<kind>` require-tag families on both surfaces in
2862 /// tatara-check, closed-set audit dispatchers, future variant
2863 /// additions on [`CalmClassification`]) binds through the SAME
2864 /// `has(kind)` shape rather than restating either the resolver
2865 /// walk or the closed-set equality at the callsite.
2866 #[must_use]
2867 pub fn has_calm(&self, kind: CalmClassification) -> bool {
2868 self.resolved_classification().has_calm(kind)
2869 }
2870
2871 /// True iff the resolved [`Classification`] carries the given
2872 /// [`DataClassification`] on its `data_classification` slot —
2873 /// byte-for-byte peer of [`Classification::has_data_classification`]
2874 /// wrapped through the [`Self::resolved_classification`] resolver
2875 /// so an operator-omitted `:classification` slot reads as the
2876 /// [`default_ephemeral_class`] baseline the sibling
2877 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2878 ///
2879 /// # Two-surface parity contract
2880 ///
2881 /// A given [`EphemeralSpec`] classifies identically through this
2882 /// primitive AND through
2883 /// `<eph.clone().into::<ProcessSpec>>().classification.has_data_classification(kind)`
2884 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2885 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2886 /// the lowering side both dereference the same
2887 /// `default_ephemeral_class()` value on `None` and the same
2888 /// authored value on `Some(_)`. This means the ephemeral-surface
2889 /// `data-classification-<kind>` `:requires` family in
2890 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2891 /// truth on the SAME authored spec as the point-surface family
2892 /// on the mechanically-lowered `ProcessSpec`.
2893 ///
2894 /// # FOURTH classification-axis peer on the ephemeral surface
2895 ///
2896 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`], and
2897 /// [`Self::has_calm`] — all four route through the SAME
2898 /// [`Self::resolved_classification`] resolver, so the operator-
2899 /// omitted `:classification` slot's fill-through logic lives at
2900 /// ONE substrate primitive rather than being restated in each
2901 /// per-axis probe body. SECOND occupant on the (Option-parent ×
2902 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
2903 /// of the ephemeral-surface presence-probe algebra alongside
2904 /// [`Self::has_calm`] — both probe REQUIRED [`Classification`]
2905 /// sub-slots whose child closed set carries its own `#[default]`
2906 /// ([`DataClassification::Internal`] here,
2907 /// [`CalmClassification::Monotone`] on the peer), so the
2908 /// default-arm short-circuit on the absent-classification arm
2909 /// reads `true` on the [`DataClassification`] child's
2910 /// `#[default]` variant precisely because BOTH the parent
2911 /// Option's fill-through baseline (`default_ephemeral_class`)
2912 /// AND the child's own `#[default]` land on the SAME variant
2913 /// ([`DataClassification::Internal`]). The two-defaults
2914 /// composition property now walks TWO independent defaulted-
2915 /// scalar-child slots on the SAME ephemeral resolver — a
2916 /// regression that promoted a different [`DataClassification`]
2917 /// variant to `#[default]` (or wired the arm to a fixed variant
2918 /// answer) fails HERE at ONE narrow substrate site before
2919 /// drifting through every unadorned ephemeral spec's baseline
2920 /// data-classification answer. Distinct from the FIRST + SECOND
2921 /// peers on the (Option-parent × NON-DEFAULT-scalar-child)
2922 /// corner, whose absent-classification arm defaults through a
2923 /// specific chosen baseline (`ConvergencePointType::Gate`,
2924 /// `SubstrateType::Compute`) rather than through the child's own
2925 /// `#[default]`. Four future sibling axes on the SAME
2926 /// `Cow`-resolver carrier ([`Self::has_horizon_kind`] opened the
2927 /// FIFTH, [`Self::has_optimization_direction`] the SIXTH; then
2928 /// `has_input_arity`, `has_output_arity`) land as one-line
2929 /// wrappers around the SAME resolver + the sibling
2930 /// [`Classification`] closed-set primitive, so a future variant
2931 /// added to [`DataClassification`] (or any of the four other
2932 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2933 /// families through the SAME closed-set walk with no per-caller
2934 /// edit.
2935 ///
2936 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2937 /// preserves proofs; the classification-axis presence-probe body
2938 /// composes ONE resolver primitive
2939 /// ([`Self::resolved_classification`]) with ONE closed-set
2940 /// primitive ([`Classification::has_data_classification`]) so
2941 /// every downstream (`data-classification-<kind>` require-tag
2942 /// families on both surfaces in tatara-check, closed-set audit
2943 /// dispatchers, future variant additions on
2944 /// [`DataClassification`]) binds through the SAME `has(kind)`
2945 /// shape rather than restating either the resolver walk or the
2946 /// closed-set equality at the callsite.
2947 #[must_use]
2948 pub fn has_data_classification(&self, kind: DataClassification) -> bool {
2949 self.resolved_classification().has_data_classification(kind)
2950 }
2951
2952 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
2953 /// carries the given [`HorizonKind`] discriminator on its
2954 /// `horizon.kind` slot — byte-for-byte peer of
2955 /// [`Classification::has_horizon_kind`] wrapped through the
2956 /// [`Self::resolved_classification`] resolver so an operator-
2957 /// omitted `:classification` slot reads as the
2958 /// [`default_ephemeral_class`] baseline the sibling
2959 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2960 ///
2961 /// # Two-surface parity contract
2962 ///
2963 /// A given [`EphemeralSpec`] classifies identically through this
2964 /// primitive AND through
2965 /// `<eph.clone().into::<ProcessSpec>>().classification.has_horizon_kind(kind)`
2966 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2967 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2968 /// the lowering side both dereference the same
2969 /// `default_ephemeral_class()` value on `None` and the same
2970 /// authored value on `Some(_)`. This means the ephemeral-surface
2971 /// `horizon-<kind>` `:requires` family in
2972 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2973 /// truth on the SAME authored spec as the point-surface family
2974 /// on the mechanically-lowered `ProcessSpec`.
2975 ///
2976 /// # FIFTH classification-axis peer on the ephemeral surface
2977 ///
2978 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2979 /// [`Self::has_calm`], and [`Self::has_data_classification`] — all
2980 /// five route through the SAME [`Self::resolved_classification`]
2981 /// resolver, so the operator-omitted `:classification` slot's
2982 /// fill-through logic lives at ONE substrate primitive rather
2983 /// than being restated in each per-axis probe body. OPENS a fresh
2984 /// (Option-parent × NESTED-STRUCT-scalar-child ×
2985 /// operator-resolvable-baseline) corner on the ephemeral-surface
2986 /// presence-probe algebra — the four prior peers on this surface
2987 /// all read the closed-set discriminator DIRECTLY off a scalar
2988 /// [`Classification`] slot (`point_type`, `substrate`, `calm`,
2989 /// `data_classification`); this probe instead threads through a
2990 /// NESTED-STRUCT intermediary ([`Horizon`], the defaulted nested
2991 /// struct owning the `horizon` axis) to reach a scalar
2992 /// [`HorizonKind`] discriminator on `horizon.kind`. The
2993 /// default-arm short-circuit on the absent-classification arm
2994 /// reads `true` on the [`HorizonKind`] child's `#[default]`
2995 /// variant precisely because BOTH the parent Option's fill-
2996 /// through baseline ([`default_ephemeral_class`], which fills
2997 /// `horizon: Horizon::default()`) AND the child's own `#[default]`
2998 /// land on the SAME variant ([`HorizonKind::Bounded`]). A
2999 /// regression that dropped `#[default]` on [`HorizonKind`], or
3000 /// promoted `Asymptotic` to `#[default]`, or wired the arm to a
3001 /// fixed variant answer, or crossed the wires through the wrong
3002 /// nested struct fails HERE at ONE narrow substrate site before
3003 /// drifting through every unadorned ephemeral spec's baseline
3004 /// horizon answer. Distinct from the FIRST + SECOND peers on the
3005 /// (Option-parent × NON-DEFAULT-scalar-child) corner
3006 /// (`has_point_type`, `has_substrate`) whose absent-classification
3007 /// arm defaults through a specific chosen baseline
3008 /// (`ConvergencePointType::Gate`, `SubstrateType::Compute`), AND
3009 /// distinct from the THIRD + FOURTH peers on the (Option-parent ×
3010 /// DEFAULTED-scalar-child) corner (`has_calm`,
3011 /// `has_data_classification`) which reach a defaulted scalar
3012 /// DIRECTLY off the parent without a nested-struct hop. Three
3013 /// future sibling axes on the SAME `Cow`-resolver carrier
3014 /// ([`Self::has_optimization_direction`] opened the SIXTH; then
3015 /// `has_input_arity`, `has_output_arity`) land as one-line
3016 /// wrappers around the SAME resolver + the sibling
3017 /// [`Classification`] closed-set primitive, so a future variant
3018 /// added to [`HorizonKind`] (or any of the three other closed
3019 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
3020 /// through the SAME closed-set walk with no per-caller edit.
3021 ///
3022 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3023 /// preserves proofs; the classification-axis presence-probe body
3024 /// composes ONE resolver primitive
3025 /// ([`Self::resolved_classification`]) with ONE closed-set
3026 /// primitive ([`Classification::has_horizon_kind`]) so every
3027 /// downstream (`horizon-<kind>` require-tag families on both
3028 /// surfaces in tatara-check, closed-set audit dispatchers, future
3029 /// variant additions on [`HorizonKind`]) binds through the SAME
3030 /// `has(kind)` shape rather than restating either the resolver
3031 /// walk or the closed-set equality at the callsite.
3032 #[must_use]
3033 pub fn has_horizon_kind(&self, kind: HorizonKind) -> bool {
3034 self.resolved_classification().has_horizon_kind(kind)
3035 }
3036
3037 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
3038 /// carries the given [`OptimizationDirection`] discriminator on its
3039 /// `horizon.direction` slot (with the substrate
3040 /// `Option::unwrap_or_default` treating `None` as the closed set's
3041 /// `#[default] Minimize`) — byte-for-byte peer of
3042 /// [`Classification::has_optimization_direction`] wrapped through
3043 /// the [`Self::resolved_classification`] resolver so an operator-
3044 /// omitted `:classification` slot reads as the
3045 /// [`default_ephemeral_class`] baseline the sibling
3046 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3047 ///
3048 /// # Two-surface parity contract
3049 ///
3050 /// A given [`EphemeralSpec`] classifies identically through this
3051 /// primitive AND through
3052 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
3053 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3054 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3055 /// the lowering side both dereference the same
3056 /// `default_ephemeral_class()` value on `None` and the same
3057 /// authored value on `Some(_)`, and the sibling
3058 /// [`Classification::has_optimization_direction`] applies the same
3059 /// `Option::unwrap_or_default` collapse on the inner
3060 /// `horizon.direction` slot on both sides. This means the
3061 /// ephemeral-surface `optimization-direction-<kind>` `:requires`
3062 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3063 /// SAME truth on the SAME authored spec as the point-surface
3064 /// family on the mechanically-lowered `ProcessSpec`.
3065 ///
3066 /// # SIXTH classification-axis peer on the ephemeral surface
3067 ///
3068 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3069 /// [`Self::has_calm`], [`Self::has_data_classification`], and
3070 /// [`Self::has_horizon_kind`] — all six route through the SAME
3071 /// [`Self::resolved_classification`] resolver, so the operator-
3072 /// omitted `:classification` slot's fill-through logic lives at
3073 /// ONE substrate primitive rather than being restated in each per-
3074 /// axis probe body. SECOND occupant on the (Option-parent ×
3075 /// NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
3076 /// corner alongside [`Self::has_horizon_kind`] — both probes thread
3077 /// through the SAME nested [`Horizon`] intermediary to reach a
3078 /// scalar discriminator on the six-axis classification lattice, but
3079 /// this method additionally traverses an `Option`-slot with
3080 /// `unwrap_or_default` so a Process filled through
3081 /// [`crate::classification::Horizon::default`] (leaves `direction:
3082 /// None`) still reads `true` on the closed set's default arm
3083 /// ([`OptimizationDirection::Minimize`]). The corner therefore
3084 /// admits BOTH direct nested-scalar shapes ([`Self::has_horizon_kind`]
3085 /// walks `horizon.kind: HorizonKind` directly) AND Option-nested-
3086 /// scalar shapes (this method walks `horizon.direction:
3087 /// Option<OptimizationDirection>` through `unwrap_or_default`),
3088 /// pinning the corner as a proven-repeatable primitive shape on the
3089 /// ephemeral surface rather than a single-example curiosity. The
3090 /// two-defaults composition property (parent Option's fill-through
3091 /// baseline via `default_ephemeral_class` AND child's closed-set
3092 /// `#[default]` land on the SAME variant) reaches through TWO
3093 /// hops here: the parent Option's `.unwrap_or_else(default_…)`
3094 /// AND the inner Option's `.unwrap_or_default()` both dereference
3095 /// to the same [`OptimizationDirection::Minimize`] baseline the
3096 /// closed set publishes. A regression that flipped
3097 /// [`OptimizationDirection`]'s `#[default]` off `Minimize` (which
3098 /// would silently invert every unadorned `Asymptotic` Process's
3099 /// rate-window evaluator polarity), or that dropped the resolver
3100 /// hop, or that wired the arm to a fixed variant answer, fails
3101 /// HERE at ONE narrow substrate site before drifting through every
3102 /// unadorned ephemeral spec's baseline direction answer. Two future
3103 /// sibling axes on the SAME `Cow`-resolver carrier
3104 /// (`has_input_arity`, `has_output_arity`) land as one-line
3105 /// wrappers around the SAME resolver + the sibling
3106 /// [`Classification`] closed-set primitive, so a future variant
3107 /// added to [`OptimizationDirection`] (or any of the two other
3108 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3109 /// families through the SAME closed-set walk with no per-caller
3110 /// edit.
3111 ///
3112 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3113 /// preserves proofs; the classification-axis presence-probe body
3114 /// composes ONE resolver primitive
3115 /// ([`Self::resolved_classification`]) with ONE closed-set
3116 /// primitive ([`Classification::has_optimization_direction`]) so
3117 /// every downstream (`optimization-direction-<kind>` require-tag
3118 /// families on both surfaces in tatara-check, closed-set audit
3119 /// dispatchers, future variant additions on
3120 /// [`OptimizationDirection`]) binds through the SAME `has(kind)`
3121 /// shape rather than restating either the resolver walk or the
3122 /// closed-set equality plus the nested-struct-Option-hop at the
3123 /// callsite.
3124 #[must_use]
3125 pub fn has_optimization_direction(&self, kind: OptimizationDirection) -> bool {
3126 self.resolved_classification()
3127 .has_optimization_direction(kind)
3128 }
3129
3130 /// True iff the resolved [`Classification`]'s nested
3131 /// [`ConvergencePointType`] projects (via the many-to-one
3132 /// [`ConvergencePointType::input_arity`] typed projection) to the
3133 /// given [`Arity`] discriminator — byte-for-byte peer of
3134 /// [`Classification::has_input_arity`] wrapped through the
3135 /// [`Self::resolved_classification`] resolver so an operator-omitted
3136 /// `:classification` slot reads as the [`default_ephemeral_class`]
3137 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
3138 /// lowering fills.
3139 ///
3140 /// # Two-surface parity contract
3141 ///
3142 /// A given [`EphemeralSpec`] classifies identically through this
3143 /// primitive AND through
3144 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
3145 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3146 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
3147 /// lowering side both dereference the same
3148 /// `default_ephemeral_class()` value on `None` and the same
3149 /// authored value on `Some(_)`, and the sibling
3150 /// [`Classification::has_input_arity`] applies the same
3151 /// `point_type.input_arity()` typed projection on both sides. This
3152 /// means the ephemeral-surface `input-arity-<kind>` `:requires`
3153 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3154 /// SAME truth on the SAME authored spec as the point-surface family
3155 /// on the mechanically-lowered `ProcessSpec`.
3156 ///
3157 /// # SEVENTH classification-axis peer on the ephemeral surface — first via a derived-typed-projection
3158 ///
3159 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3160 /// [`Self::has_calm`], [`Self::has_data_classification`],
3161 /// [`Self::has_horizon_kind`], and
3162 /// [`Self::has_optimization_direction`] — all seven route through
3163 /// the SAME [`Self::resolved_classification`] resolver, so the
3164 /// operator-omitted `:classification` slot's fill-through logic
3165 /// lives at ONE substrate primitive rather than being restated in
3166 /// each per-axis probe body. FIRST occupant on the (Option-parent ×
3167 /// NESTED-STRUCT-scalar-child × derived-typed-projection) corner on
3168 /// the ephemeral surface — byte-for-byte symmetric with the
3169 /// derived-typed-projection precedent set by
3170 /// [`Classification::has_input_arity`] on the point surface: THAT
3171 /// peer routes through [`ConvergencePointType::input_arity`] on a
3172 /// required [`Classification`] carrier; THIS peer routes through the
3173 /// SAME projection on the `Cow`-resolver carrier so the resolver
3174 /// walk composes with the projection at ONE substrate site rather
3175 /// than being restated per surface. Distinct from the SIXTH peer
3176 /// [`Self::has_optimization_direction`] (which walks
3177 /// `horizon.direction` through an `Option::unwrap_or_default`
3178 /// collapse to reach a defaulted scalar child) and the FIFTH peer
3179 /// [`Self::has_horizon_kind`] (which walks `horizon.kind` DIRECTLY
3180 /// as a scalar without any typed-projection hop) on ONE dimension:
3181 /// this probe threads through the many-to-one closed-set typed
3182 /// projection [`ConvergencePointType::input_arity`] (`Transform |
3183 /// Fork | Broadcast | Observe → One`, `Join | Gate | Select |
3184 /// Reduce → Many`) so the child's closed set ([`Arity`]) is REACHED
3185 /// THROUGH a projection layer, not read raw off a scalar. The
3186 /// corner therefore admits three ephemeral-surface traversal
3187 /// shapes through the SAME `resolved_classification().<field>`
3188 /// walk: direct-nested-scalar
3189 /// ([`Self::has_horizon_kind`] reads `horizon.kind: HorizonKind`
3190 /// directly), Option-nested-scalar
3191 /// ([`Self::has_optimization_direction`] reads `horizon.direction:
3192 /// Option<OptimizationDirection>` through `unwrap_or_default`), and
3193 /// derived-typed-projection (this method reads
3194 /// `point_type.input_arity(): Arity` through a many-to-one
3195 /// projection). The co-tenant derived-typed-projection axis on the
3196 /// SAME `Cow`-resolver carrier ([`Self::has_output_arity`]) lands as
3197 /// a one-line wrapper around the SAME resolver + the sibling
3198 /// [`Classification`] closed-set primitive, so a future variant
3199 /// added to [`Arity`] or to [`ConvergencePointType`] reaches BOTH
3200 /// surfaces' `<axis>-<kind>` prefix families through the SAME
3201 /// closed-set walk with no per-caller edit.
3202 ///
3203 /// # Semantics — VARIANT match on the projected image
3204 ///
3205 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
3206 /// `#[default]`), so exactly ONE of the two arms answers `true` per
3207 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
3208 /// shortcut. The absent-`:classification` baseline
3209 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
3210 /// [`ConvergencePointType::input_arity`] projects `Gate → Many`, so
3211 /// the ephemeral sugar surface's `input-arity-Many` require-tag
3212 /// reads `true` on every operator-authored spec that omits the
3213 /// `:classification` slot — pinning the workspace's convergent-by-
3214 /// default point posture on the input side. The many-to-one
3215 /// projection shape means the answer is invariant under intra-
3216 /// bucket point-type swaps (`Transform ↔ Fork ↔ Broadcast ↔
3217 /// Observe` all keep `input-arity-One = true`) and flips at bucket
3218 /// boundaries (`Transform ↔ Join` flips `input-arity-One` from
3219 /// `true` to `false`). A regression that dropped the resolver hop,
3220 /// probed [`ConvergencePointType`] directly (dropping the
3221 /// `.input_arity()` call), inverted the projection (`One ↔ Many`),
3222 /// or crossed the wires with the sibling
3223 /// [`ConvergencePointType::output_arity`] projection fails HERE at
3224 /// ONE narrow substrate site before drifting through every
3225 /// unadorned ephemeral spec's baseline input-arity answer.
3226 ///
3227 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3228 /// preserves proofs; the classification-axis presence-probe body
3229 /// composes ONE resolver primitive
3230 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
3231 /// ([`Classification::has_input_arity`]) so every downstream
3232 /// (`input-arity-<kind>` require-tag families on both surfaces in
3233 /// tatara-check, closed-set audit dispatchers, future variant
3234 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
3235 /// through the SAME `has(kind)` shape rather than restating either
3236 /// the resolver walk or the closed-set equality plus the typed-
3237 /// projection hop at the callsite.
3238 #[must_use]
3239 pub fn has_input_arity(&self, kind: Arity) -> bool {
3240 self.resolved_classification().has_input_arity(kind)
3241 }
3242
3243 /// True iff the resolved [`Classification`]'s nested
3244 /// [`ConvergencePointType`] projects (via the many-to-one
3245 /// [`ConvergencePointType::output_arity`] typed projection) to the
3246 /// given [`Arity`] discriminator — byte-for-byte peer of
3247 /// [`Classification::has_output_arity`] wrapped through the
3248 /// [`Self::resolved_classification`] resolver so an operator-omitted
3249 /// `:classification` slot reads as the [`default_ephemeral_class`]
3250 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
3251 /// lowering fills.
3252 ///
3253 /// # Two-surface parity contract
3254 ///
3255 /// A given [`EphemeralSpec`] classifies identically through this
3256 /// primitive AND through
3257 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
3258 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3259 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
3260 /// lowering side both dereference the same
3261 /// `default_ephemeral_class()` value on `None` and the same
3262 /// authored value on `Some(_)`, and the sibling
3263 /// [`Classification::has_output_arity`] applies the same
3264 /// `point_type.output_arity()` typed projection on both sides. This
3265 /// means the ephemeral-surface `output-arity-<kind>` `:requires`
3266 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3267 /// SAME truth on the SAME authored spec as the point-surface family
3268 /// on the mechanically-lowered `ProcessSpec`.
3269 ///
3270 /// # EIGHTH classification-axis peer — closes the ephemeral-side DAG-composition arity pair
3271 ///
3272 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3273 /// [`Self::has_calm`], [`Self::has_data_classification`],
3274 /// [`Self::has_horizon_kind`], [`Self::has_optimization_direction`],
3275 /// and [`Self::has_input_arity`] — all eight route through the SAME
3276 /// [`Self::resolved_classification`] resolver, so the operator-
3277 /// omitted `:classification` slot's fill-through logic lives at ONE
3278 /// substrate primitive rather than being restated in each per-axis
3279 /// probe body. SECOND occupant on the (Option-parent × NESTED-
3280 /// STRUCT-scalar-child × derived-typed-projection) corner on the
3281 /// ephemeral surface — co-tenant with [`Self::has_input_arity`] on
3282 /// the SAME `point_type` scalar carrier through the SAME [`Arity`]
3283 /// closed set but through the sibling many-to-one typed projection
3284 /// [`ConvergencePointType::output_arity`] (`Transform | Join | Gate
3285 /// | Select | Reduce | Observe → One`, `Fork | Broadcast → Many`).
3286 /// Closes the DAG-composition arity pair on the ephemeral side —
3287 /// the two projections DISAGREE on the diffusive arms `Fork |
3288 /// Broadcast` (input `One` vs. output `Many`) and on the convergent
3289 /// arms `Join | Gate | Select | Reduce` (input `Many` vs. output
3290 /// `One`), and AGREE on the endomorphic arms `Transform | Observe`
3291 /// (both `One`). Byte-for-byte symmetric with the DAG-composition
3292 /// arity pair on the point surface ([`Classification::has_input_arity`] +
3293 /// [`Classification::has_output_arity`]) — THAT pair walks a required
3294 /// [`Classification`] carrier; THIS pair walks the SAME projection
3295 /// pair on the `Cow`-resolver carrier so the resolver walk composes
3296 /// with the projection at ONE substrate site rather than being
3297 /// restated per surface.
3298 ///
3299 /// # Semantics — VARIANT match on the projected image
3300 ///
3301 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
3302 /// `#[default]`), so exactly ONE of the two arms answers `true` per
3303 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
3304 /// shortcut. The absent-`:classification` baseline
3305 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
3306 /// [`ConvergencePointType::output_arity`] projects `Gate → One`, so
3307 /// the ephemeral sugar surface's `output-arity-One` require-tag
3308 /// reads `true` on every operator-authored spec that omits the
3309 /// `:classification` slot — pinning the workspace's convergent-by-
3310 /// default point posture on the output side. The many-to-one
3311 /// projection shape means the answer is invariant under intra-
3312 /// bucket point-type swaps (`Fork ↔ Broadcast` both keep
3313 /// `output-arity-Many = true`; `Transform ↔ Join ↔ Gate ↔ Select ↔
3314 /// Reduce ↔ Observe` all keep `output-arity-One = true`) and flips
3315 /// at bucket boundaries (`Fork ↔ Transform` flips `output-arity-
3316 /// Many` from `true` to `false`). A regression that dropped the
3317 /// resolver hop, probed [`ConvergencePointType`] directly (dropping
3318 /// the `.output_arity()` call), inverted the projection (`One ↔
3319 /// Many`), or crossed the wires with the sibling
3320 /// [`ConvergencePointType::input_arity`] projection fails HERE at
3321 /// ONE narrow substrate site before drifting through every
3322 /// unadorned ephemeral spec's baseline output-arity answer.
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 primitive
3328 /// ([`Classification::has_output_arity`]) so every downstream
3329 /// (`output-arity-<kind>` require-tag families on both surfaces in
3330 /// tatara-check, closed-set audit dispatchers, future variant
3331 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
3332 /// through the SAME `has(kind)` shape rather than restating either
3333 /// the resolver walk or the closed-set equality plus the typed-
3334 /// projection hop at the callsite.
3335 #[must_use]
3336 pub fn has_output_arity(&self, kind: Arity) -> bool {
3337 self.resolved_classification().has_output_arity(kind)
3338 }
3339
3340 /// Derived-boolean predicate — does this ephemeral spec's
3341 /// resolved [`Classification`]'s [`Horizon`] project to `true`
3342 /// under [`crate::classification::HorizonKind::terminates`]?
3343 /// Byte-for-byte peer of
3344 /// [`Classification::horizon_terminates`] wrapped through the
3345 /// [`Self::resolved_classification`] resolver so an operator-
3346 /// omitted `:classification` slot on `(defephemeral …)` still
3347 /// answers via the substrate default. The ONE ephemeral-surface
3348 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3349 /// derived-nullary-boolean walk on the classification-horizon
3350 /// axis.
3351 ///
3352 /// # Two-surface parity — resolver hop + Classification primitive
3353 ///
3354 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3355 /// [`Self::has_calm`], [`Self::has_data_classification`],
3356 /// [`Self::has_horizon_kind`],
3357 /// [`Self::has_optimization_direction`],
3358 /// [`Self::has_input_arity`], and [`Self::has_output_arity`] on
3359 /// the (resolver-hop × [`Classification`] presence primitive)
3360 /// axis: all nine methods route through the SAME
3361 /// [`Self::resolved_classification`] resolver, and each composes
3362 /// against ONE [`Classification`] primitive. This method
3363 /// distinguishes itself by targeting the [`Classification`]
3364 /// primitive [`Classification::horizon_terminates`] which is the
3365 /// FIRST derived-nullary-boolean (no closed-set argument)
3366 /// primitive on the [`Classification`] surface — every prior
3367 /// peer probe on [`Classification`] admits a closed-set `kind`
3368 /// argument and answers a variant-equality question, while this
3369 /// probe collapses [`HorizonKind::ALL`] onto a single boolean
3370 /// via the closed set's own [`HorizonKind::terminates`]
3371 /// predicate.
3372 ///
3373 /// # Semantics — resolver hop + derived-nullary-boolean
3374 ///
3375 /// `horizon_terminates()` returns `true` iff
3376 /// `self.resolved_classification().horizon_terminates()`. The
3377 /// resolver returns the authored [`Classification`] when
3378 /// present and the substrate default
3379 /// [`Classification::gate_compute`] on absence. Because
3380 /// [`Classification::gate_compute`] uses [`Horizon::default`]
3381 /// (whose `kind` field defaults to [`HorizonKind::Bounded`] via
3382 /// `#[default]`), a bare ephemeral spec with no `:classification`
3383 /// slot answers `true` — the default-arm short-circuit
3384 /// propagates through THREE layers of `Default`
3385 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
3386 /// [`HorizonKind::default`]) to this predicate's answer, matching
3387 /// the default-arm shortcut every prior defaulted-child probe
3388 /// on this surface publishes. A regression that dropped the
3389 /// resolver hop, probed [`Classification::has_horizon_kind`]
3390 /// directly (dropping the `.terminates()` projection), or
3391 /// crossed the wires with the antisymmetric partner
3392 /// [`HorizonKind::requires_metric_axes`] fails HERE at ONE
3393 /// narrow substrate site before drifting through every
3394 /// unadorned ephemeral spec's baseline horizon-terminates
3395 /// answer.
3396 ///
3397 /// # Compounding
3398 ///
3399 /// The ephemeral require-tag classifier composes this primitive
3400 /// as a fixed tag `terminating-horizon` on
3401 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3402 /// surface's `terminating-horizon` fixed tag on
3403 /// `POINT_FIXED_TAG_ARMS` via [`Classification::horizon_terminates`]
3404 /// directly. The two-surface parity contract holds by
3405 /// construction: both surfaces route through the SAME
3406 /// [`Classification::horizon_terminates`] primitive after the
3407 /// ephemeral surface pays ONE resolver hop — a future
3408 /// [`HorizonKind`] variant or a future normalization at the
3409 /// substrate primitive lands at ONE site and both surfaces'
3410 /// `terminating-horizon` fixed tags inherit the shift
3411 /// mechanically. A future co-tenant peer on this surface (a
3412 /// hypothetical `horizon_requires_metric_axes` composing the
3413 /// antisymmetric partner [`HorizonKind::requires_metric_axes`]
3414 /// through the SAME resolver hop) lands as ONE peer inherent
3415 /// method with the same nullary-derived body.
3416 ///
3417 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3418 /// preserves proofs; the classification-axis derived-nullary-
3419 /// boolean probe body composes ONE resolver primitive
3420 /// ([`Self::resolved_classification`]) with ONE
3421 /// [`Classification`] primitive
3422 /// ([`Classification::horizon_terminates`]) so every downstream
3423 /// (`terminating-horizon` fixed tags on both surfaces in
3424 /// tatara-check, future scheduler / termination-shape
3425 /// validators, future variant additions on [`HorizonKind`])
3426 /// binds through the SAME `horizon_terminates()` shape rather
3427 /// than restating either the resolver walk or the closed-set
3428 /// projection composition at the callsite. THEORY.md §VI.1 —
3429 /// generation over composition; a future [`HorizonKind`]
3430 /// variant lands at ONE `ALL` entry + ONE `terminates` arm on
3431 /// the closed set and both surfaces pick it up mechanically.
3432 #[must_use]
3433 pub fn horizon_terminates(&self) -> bool {
3434 self.resolved_classification().horizon_terminates()
3435 }
3436
3437 /// Derived-boolean predicate — does this ephemeral spec's
3438 /// resolved [`Classification`]'s [`Horizon`] project to `true`
3439 /// under [`crate::classification::HorizonKind::requires_metric_axes`]?
3440 /// Byte-for-byte peer of
3441 /// [`Classification::horizon_requires_metric_axes`] wrapped
3442 /// through the [`Self::resolved_classification`] resolver so an
3443 /// operator-omitted `:classification` slot on `(defephemeral …)`
3444 /// still answers via the substrate default. The ONE ephemeral-
3445 /// surface substrate primitive that owns the
3446 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on
3447 /// the metric-axes-required question over the classification-
3448 /// horizon axis.
3449 ///
3450 /// # Antisymmetric peer of [`Self::horizon_terminates`]
3451 ///
3452 /// Byte-for-byte antisymmetric peer of [`Self::horizon_terminates`]
3453 /// via the SAME [`Self::resolved_classification`] resolver hop
3454 /// and the SAME closed set [`crate::classification::HorizonKind`]:
3455 /// [`Self::horizon_terminates`] composes
3456 /// [`Classification::horizon_terminates`] (walking
3457 /// [`crate::classification::HorizonKind::terminates`]); this
3458 /// method composes the ANTISYMMETRIC partner
3459 /// [`Classification::horizon_requires_metric_axes`] (walking
3460 /// [`crate::classification::HorizonKind::requires_metric_axes`]).
3461 /// The closed set pins the XOR contract
3462 /// `terminates() ^ requires_metric_axes()` on every variant, so
3463 /// exactly ONE of these two ephemeral-surface derived-nullary
3464 /// probes answers `true` per resolved [`Classification`] and the
3465 /// two probes together partition the resolver's output space into
3466 /// two disjoint buckets on every ephemeral spec — authored or
3467 /// defaulted.
3468 ///
3469 /// # Semantics — resolver hop + derived-nullary-boolean
3470 ///
3471 /// `horizon_requires_metric_axes()` returns `true` iff
3472 /// `self.resolved_classification().horizon_requires_metric_axes()`.
3473 /// The resolver returns the authored [`Classification`] when
3474 /// present and the substrate default
3475 /// [`Classification::gate_compute`] on absence. Because
3476 /// [`Classification::gate_compute`] uses [`Horizon::default`]
3477 /// (whose `kind` field defaults to
3478 /// [`crate::classification::HorizonKind::Bounded`] via
3479 /// `#[default]`), a bare ephemeral spec with no `:classification`
3480 /// slot answers `false` — the default-arm short-circuit
3481 /// propagates through THREE layers of `Default`
3482 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
3483 /// [`crate::classification::HorizonKind::default`]) to this
3484 /// predicate's answer, the mirror image of
3485 /// [`Self::horizon_terminates`]'s default-arm `true` answer. A
3486 /// regression that dropped the resolver hop, probed
3487 /// [`Classification::has_horizon_kind`] directly (dropping the
3488 /// `.requires_metric_axes()` projection), or crossed the wires
3489 /// with the antisymmetric partner
3490 /// [`crate::classification::HorizonKind::terminates`] fails HERE
3491 /// at ONE narrow substrate site before drifting through every
3492 /// unadorned ephemeral spec's baseline metric-provisioning
3493 /// answer.
3494 ///
3495 /// # Compounding
3496 ///
3497 /// The ephemeral require-tag classifier composes this primitive
3498 /// as a fixed tag `metric-axes-required` on
3499 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3500 /// surface's `metric-axes-required` fixed tag on
3501 /// `POINT_FIXED_TAG_ARMS` via
3502 /// [`Classification::horizon_requires_metric_axes`] directly. The
3503 /// two-surface parity contract holds by construction: both
3504 /// surfaces route through the SAME
3505 /// [`Classification::horizon_requires_metric_axes`] primitive
3506 /// after the ephemeral surface pays ONE resolver hop — a future
3507 /// [`crate::classification::HorizonKind`] variant or a future
3508 /// normalization at the substrate primitive lands at ONE site and
3509 /// both surfaces' `metric-axes-required` fixed tags inherit the
3510 /// shift mechanically.
3511 ///
3512 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3513 /// preserves proofs; the classification-axis derived-nullary-
3514 /// boolean probe body composes ONE resolver primitive
3515 /// ([`Self::resolved_classification`]) with ONE
3516 /// [`Classification`] primitive
3517 /// ([`Classification::horizon_requires_metric_axes`]) so every
3518 /// downstream (`metric-axes-required` fixed tags on both
3519 /// surfaces in tatara-check, future scheduler / metric-
3520 /// provisioning validators, future variant additions on
3521 /// [`crate::classification::HorizonKind`]) binds through the
3522 /// SAME `horizon_requires_metric_axes()` shape rather than
3523 /// restating either the resolver walk or the closed-set
3524 /// projection composition at the callsite. THEORY.md §VI.1 —
3525 /// generation over composition; a future
3526 /// [`crate::classification::HorizonKind`] variant lands at ONE
3527 /// `ALL` entry + ONE `requires_metric_axes` arm on the closed
3528 /// set and both surfaces pick it up mechanically.
3529 #[must_use]
3530 pub fn horizon_requires_metric_axes(&self) -> bool {
3531 self.resolved_classification()
3532 .horizon_requires_metric_axes()
3533 }
3534
3535 /// Derived-boolean predicate — does this ephemeral spec's
3536 /// resolved [`Classification`]'s [`crate::classification::CalmClassification`]
3537 /// project to `true` under
3538 /// [`crate::classification::CalmClassification::requires_coordination`]?
3539 /// Byte-for-byte peer of
3540 /// [`Classification::calm_requires_coordination`] wrapped through
3541 /// the [`Self::resolved_classification`] resolver so an operator-
3542 /// omitted `:classification` slot on `(defephemeral …)` still
3543 /// answers via the substrate default. The ONE ephemeral-surface
3544 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3545 /// derived-nullary-boolean walk on the coordination-required
3546 /// question over the classification-calm axis.
3547 ///
3548 /// # Third derived-nullary-boolean peer on the ephemeral surface
3549 ///
3550 /// Peer of [`Self::horizon_terminates`] and
3551 /// [`Self::horizon_requires_metric_axes`] on the ephemeral
3552 /// surface's (resolver-hop × derived-nullary-bool) shape — the
3553 /// FIRST peer threading the classification-calm axis rather than
3554 /// the classification-horizon axis. Distinct from both prior
3555 /// derived-nullary peers by ONE structural degree at the underlying
3556 /// [`Classification`] primitive: [`Self::horizon_terminates`] +
3557 /// [`Self::horizon_requires_metric_axes`] both walk the nested
3558 /// `.horizon.kind` sub-slot's derived projection, while this probe
3559 /// walks the direct scalar `.calm` field's derived projection.
3560 /// The resolver-hop shape is byte-identical.
3561 ///
3562 /// # Semantics — resolver hop + derived-nullary-boolean
3563 ///
3564 /// `calm_requires_coordination()` returns `true` iff
3565 /// `self.resolved_classification().calm_requires_coordination()`.
3566 /// The resolver returns the authored [`Classification`] when
3567 /// present and the substrate default
3568 /// [`Classification::gate_compute`] on absence. Because
3569 /// [`Classification::gate_compute`] carries
3570 /// [`crate::classification::CalmClassification::default = Monotone`],
3571 /// a bare ephemeral spec with no `:classification` slot answers
3572 /// `false` — the default-arm short-circuit propagates through TWO
3573 /// layers of `Default` ([`Classification::gate_compute`] →
3574 /// [`crate::classification::CalmClassification::default`]) to this
3575 /// predicate's answer. Distinct from the two `horizon_*` peers on
3576 /// this surface, which short-circuit through THREE layers of
3577 /// `Default` ([`Classification::gate_compute`] → [`Horizon::default`]
3578 /// → [`HorizonKind::default`]) because the horizon axis has a
3579 /// nested-struct wrapper between the classification field and the
3580 /// closed-set discriminator. A regression that dropped the
3581 /// resolver hop, probed [`Classification::has_calm`] directly
3582 /// (dropping the `.requires_coordination()` projection), or
3583 /// inverted the projection (silently promoting the Monotone
3584 /// baseline to "requires coordination") fails HERE at ONE narrow
3585 /// substrate site before drifting through every unadorned
3586 /// ephemeral spec's baseline coordination-mode answer.
3587 ///
3588 /// # Compounding
3589 ///
3590 /// The ephemeral require-tag classifier composes this primitive
3591 /// as a fixed tag `coordination-required` on
3592 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3593 /// surface's `coordination-required` fixed tag on
3594 /// `POINT_FIXED_TAG_ARMS` via
3595 /// [`Classification::calm_requires_coordination`] directly. The
3596 /// two-surface parity contract holds by construction: both
3597 /// surfaces route through the SAME
3598 /// [`Classification::calm_requires_coordination`] primitive after
3599 /// the ephemeral surface pays ONE resolver hop — a future
3600 /// [`crate::classification::CalmClassification`] variant or a
3601 /// future normalization at the substrate primitive lands at ONE
3602 /// site and both surfaces' `coordination-required` fixed tags
3603 /// inherit the shift mechanically.
3604 ///
3605 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3606 /// preserves proofs; the classification-axis derived-nullary-
3607 /// boolean probe body composes ONE resolver primitive
3608 /// ([`Self::resolved_classification`]) with ONE
3609 /// [`Classification`] primitive
3610 /// ([`Classification::calm_requires_coordination`]) so every
3611 /// downstream (`coordination-required` fixed tags on both
3612 /// surfaces in tatara-check, future scheduler / coordination-mode
3613 /// validators, future variant additions on
3614 /// [`crate::classification::CalmClassification`]) binds through
3615 /// the SAME `calm_requires_coordination()` shape rather than
3616 /// restating either the resolver walk or the closed-set
3617 /// projection composition at the callsite. THEORY.md §VI.1 —
3618 /// generation over composition; a future
3619 /// [`crate::classification::CalmClassification`] variant lands at
3620 /// ONE `ALL` entry + ONE `requires_coordination` arm on the
3621 /// closed set and both surfaces pick it up mechanically.
3622 #[must_use]
3623 pub fn calm_requires_coordination(&self) -> bool {
3624 self.resolved_classification().calm_requires_coordination()
3625 }
3626
3627 /// Derived-boolean predicate — does this ephemeral spec's
3628 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
3629 /// project to `true` under
3630 /// [`crate::classification::DataClassification::is_regulated`]?
3631 /// Byte-for-byte peer of
3632 /// [`Classification::data_is_regulated`] wrapped through the
3633 /// [`Self::resolved_classification`] resolver so an operator-
3634 /// omitted `:classification` slot on `(defephemeral …)` still
3635 /// answers via the substrate default. The ONE ephemeral-surface
3636 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3637 /// derived-nullary-boolean walk on the regulated-data question
3638 /// over the classification-data axis.
3639 ///
3640 /// # Fourth derived-nullary-boolean peer on the ephemeral surface
3641 ///
3642 /// Peer of [`Self::horizon_terminates`],
3643 /// [`Self::horizon_requires_metric_axes`], and
3644 /// [`Self::calm_requires_coordination`] on the ephemeral surface's
3645 /// (resolver-hop × derived-nullary-bool) shape — the FIRST peer
3646 /// threading the classification-data axis rather than the horizon
3647 /// or calm axes. Structural byte-for-byte peer of
3648 /// [`Self::calm_requires_coordination`]: both walk a DIRECT scalar
3649 /// closed-set field's derived projection on the resolved
3650 /// [`Classification`] (`.calm.requires_coordination()` /
3651 /// `.data_classification.is_regulated()`) — TWO layers of
3652 /// `Default` short-circuit ([`Classification::gate_compute`] →
3653 /// the direct scalar child's `#[default]`) — distinct from the
3654 /// two `horizon_*` peers which walk a NESTED-STRUCT projection
3655 /// (`.horizon.kind`) with THREE layers of `Default`. The resolver-
3656 /// hop shape is byte-identical across all four peers.
3657 ///
3658 /// # Semantics — resolver hop + derived-nullary-boolean
3659 ///
3660 /// `data_is_regulated()` returns `true` iff
3661 /// `self.resolved_classification().data_is_regulated()`. The
3662 /// resolver returns the authored [`Classification`] when present
3663 /// and the substrate default [`Classification::gate_compute`] on
3664 /// absence. Because [`Classification::gate_compute`] carries
3665 /// [`crate::classification::DataClassification::default = Internal`],
3666 /// a bare ephemeral spec with no `:classification` slot answers
3667 /// `false` — the default-arm short-circuit propagates through TWO
3668 /// layers of `Default` ([`Classification::gate_compute`] →
3669 /// [`crate::classification::DataClassification::default`]) to
3670 /// this predicate's answer, mirror-image of
3671 /// [`Self::calm_requires_coordination`]'s Monotone-default
3672 /// short-circuit through the same structural depth. Distinct
3673 /// from the two `horizon_*` peers on this surface which short-
3674 /// circuit through THREE layers of `Default` because the horizon
3675 /// axis has a nested-struct wrapper. A regression that dropped
3676 /// the resolver hop, probed [`Classification::has_data_classification`]
3677 /// directly (dropping the `.is_regulated()` projection), or
3678 /// inverted the projection (silently promoting the Internal
3679 /// baseline to "regulated") fails HERE at ONE narrow substrate
3680 /// site before drifting through every unadorned ephemeral spec's
3681 /// baseline regulatory-regime answer.
3682 ///
3683 /// # Compounding
3684 ///
3685 /// The ephemeral require-tag classifier composes this primitive
3686 /// as a fixed tag `data-regulated` on `EPHEMERAL_FIXED_TAG_ARMS`
3687 /// — byte-for-byte peer of the point surface's `data-regulated`
3688 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3689 /// [`Classification::data_is_regulated`] directly. The two-
3690 /// surface parity contract holds by construction: both surfaces
3691 /// route through the SAME
3692 /// [`Classification::data_is_regulated`] primitive after the
3693 /// ephemeral surface pays ONE resolver hop — a future
3694 /// [`crate::classification::DataClassification`] variant or a
3695 /// future normalization at the substrate primitive lands at ONE
3696 /// site and both surfaces' `data-regulated` fixed tags inherit
3697 /// the shift mechanically.
3698 ///
3699 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3700 /// preserves proofs; the classification-data-axis derived-nullary-
3701 /// boolean probe body composes ONE resolver primitive
3702 /// ([`Self::resolved_classification`]) with ONE
3703 /// [`Classification`] primitive
3704 /// ([`Classification::data_is_regulated`]) so every downstream
3705 /// (`data-regulated` fixed tags on both surfaces in tatara-check,
3706 /// future compliance-baseline / regulatory-regime validators,
3707 /// future variant additions on
3708 /// [`crate::classification::DataClassification`]) binds through
3709 /// the SAME `data_is_regulated()` shape rather than restating
3710 /// either the resolver walk or the closed-set projection
3711 /// composition at the callsite. THEORY.md §VI.1 — generation
3712 /// over composition; a future
3713 /// [`crate::classification::DataClassification`] variant lands
3714 /// at ONE `ALL` entry + ONE `is_regulated` arm on the closed set
3715 /// and both surfaces pick it up mechanically.
3716 #[must_use]
3717 pub fn data_is_regulated(&self) -> bool {
3718 self.resolved_classification().data_is_regulated()
3719 }
3720
3721 /// Derived-boolean predicate — does this ephemeral spec's
3722 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
3723 /// project to `true` under
3724 /// [`crate::classification::DataClassification::is_restricted`]?
3725 /// Byte-for-byte peer of
3726 /// [`Classification::data_is_restricted`] wrapped through the
3727 /// [`Self::resolved_classification`] resolver so an operator-
3728 /// omitted `:classification` slot on `(defephemeral …)` still
3729 /// answers via the substrate default. The ONE ephemeral-surface
3730 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3731 /// derived-nullary-boolean walk on the restricted-data question
3732 /// over the classification-data axis.
3733 ///
3734 /// # Fifth derived-nullary-boolean peer on the ephemeral surface
3735 ///
3736 /// Peer of [`Self::horizon_terminates`],
3737 /// [`Self::horizon_requires_metric_axes`],
3738 /// [`Self::calm_requires_coordination`], and
3739 /// [`Self::data_is_regulated`] on the ephemeral surface's
3740 /// (resolver-hop × derived-nullary-bool) shape — the SECOND peer
3741 /// threading the classification-data axis after
3742 /// [`Self::data_is_regulated`] opened it, pinning the data axis
3743 /// as a proven-repeatable structural sub-corner across TWO sibling
3744 /// closed-set projections (`is_regulated` / `is_restricted`).
3745 /// Structural byte-for-byte peer of
3746 /// [`Self::data_is_regulated`]: both walk the SAME DIRECT scalar
3747 /// closed-set field's derived projection on the resolved
3748 /// [`Classification`] (`.data_classification.is_regulated()` /
3749 /// `.is_restricted()`) — TWO layers of `Default` short-circuit
3750 /// ([`Classification::gate_compute`] → [`crate::classification::DataClassification::default = Internal`])
3751 /// — distinct from the two `horizon_*` peers which walk a NESTED-
3752 /// STRUCT projection (`.horizon.kind`) with THREE layers of
3753 /// `Default`. The resolver-hop shape is byte-identical across all
3754 /// five peers.
3755 ///
3756 /// # Semantics — resolver hop + derived-nullary-boolean
3757 ///
3758 /// `data_is_restricted()` returns `true` iff
3759 /// `self.resolved_classification().data_is_restricted()`. The
3760 /// resolver returns the authored [`Classification`] when present
3761 /// and the substrate default [`Classification::gate_compute`] on
3762 /// absence. Because [`Classification::gate_compute`] carries
3763 /// [`crate::classification::DataClassification::default = Internal`],
3764 /// a bare ephemeral spec with no `:classification` slot answers
3765 /// `true` — the default-arm short-circuit propagates through TWO
3766 /// layers of `Default` ([`Classification::gate_compute`] →
3767 /// [`crate::classification::DataClassification::default`]) to
3768 /// this predicate's answer. FIRST direct-scalar ephemeral-surface
3769 /// peer whose absent-classification default answers `true`, not
3770 /// `false` (`data_is_regulated` and `calm_requires_coordination`
3771 /// both project `false` on the same absent classification),
3772 /// mirror-image of [`Self::horizon_terminates`]'s `Bounded`-default
3773 /// `true` baseline on the nested-struct sub-corner. A regression
3774 /// that dropped the resolver hop, probed
3775 /// [`Classification::has_data_classification`] directly (dropping
3776 /// the `.is_restricted()` projection), or inverted the projection
3777 /// (silently demoting the Internal baseline to "unrestricted")
3778 /// fails HERE at ONE narrow substrate site before drifting
3779 /// through every unadorned ephemeral spec's baseline access-
3780 /// control-mandatory answer.
3781 ///
3782 /// # Compounding
3783 ///
3784 /// The ephemeral require-tag classifier composes this primitive
3785 /// as a fixed tag `data-restricted` on `EPHEMERAL_FIXED_TAG_ARMS`
3786 /// — byte-for-byte peer of the point surface's `data-restricted`
3787 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3788 /// [`Classification::data_is_restricted`] directly. The two-
3789 /// surface parity contract holds by construction: both surfaces
3790 /// route through the SAME
3791 /// [`Classification::data_is_restricted`] primitive after the
3792 /// ephemeral surface pays ONE resolver hop — a future
3793 /// [`crate::classification::DataClassification`] variant or a
3794 /// future normalization at the substrate primitive lands at ONE
3795 /// site and both surfaces' `data-restricted` fixed tags inherit
3796 /// the shift mechanically. The closed-set-internal implication
3797 /// `is_regulated() ⇒ is_restricted()` composes through the
3798 /// resolver hop to
3799 /// `data_is_regulated() ⇒ data_is_restricted()` at this surface
3800 /// too.
3801 ///
3802 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3803 /// preserves proofs; the classification-data-axis derived-nullary-
3804 /// boolean probe body composes ONE resolver primitive
3805 /// ([`Self::resolved_classification`]) with ONE
3806 /// [`Classification`] primitive
3807 /// ([`Classification::data_is_restricted`]) so every downstream
3808 /// (`data-restricted` fixed tags on both surfaces in tatara-check,
3809 /// future compliance-baseline / access-control-mandatory
3810 /// validators, future variant additions on
3811 /// [`crate::classification::DataClassification`]) binds through
3812 /// the SAME `data_is_restricted()` shape rather than restating
3813 /// either the resolver walk or the closed-set projection
3814 /// composition at the callsite. THEORY.md §VI.1 — generation
3815 /// over composition; a future
3816 /// [`crate::classification::DataClassification`] variant lands
3817 /// at ONE `ALL` entry + ONE `is_restricted` arm on the closed set
3818 /// and both surfaces pick it up mechanically.
3819 #[must_use]
3820 pub fn data_is_restricted(&self) -> bool {
3821 self.resolved_classification().data_is_restricted()
3822 }
3823
3824 /// Derived-boolean predicate — does this ephemeral spec's
3825 /// resolved [`Classification`]'s
3826 /// [`crate::classification::ConvergencePointType`] project to
3827 /// `true` under
3828 /// [`crate::classification::ConvergencePointType::is_endomorphic`]?
3829 /// Byte-for-byte peer of
3830 /// [`Classification::point_is_endomorphic`] wrapped through the
3831 /// [`Self::resolved_classification`] resolver so an operator-
3832 /// omitted `:classification` slot on `(defephemeral …)` still
3833 /// answers via the substrate default. The ONE ephemeral-surface
3834 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3835 /// derived-nullary-boolean walk on the 1→1 topology-bucket
3836 /// question over the classification-`point_type` axis.
3837 ///
3838 /// # Sixth derived-nullary-boolean peer on the ephemeral surface
3839 ///
3840 /// Peer of [`Self::horizon_terminates`],
3841 /// [`Self::horizon_requires_metric_axes`],
3842 /// [`Self::calm_requires_coordination`],
3843 /// [`Self::data_is_regulated`], and [`Self::data_is_restricted`]
3844 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
3845 /// shape — the FIRST peer threading the classification-`point_type`
3846 /// axis after the two `horizon_*`, one `calm_*`, and two `data_*`
3847 /// peers populated the horizon, calm, and data axes. Direct-scalar
3848 /// peer of the sibling `data_*` and `calm_*` arms but distinct by
3849 /// ONE structural degree at the underlying [`Classification`]
3850 /// primitive: [`crate::classification::ConvergencePointType`] has
3851 /// NO [`Default`] impl, so the absent-`:classification` baseline
3852 /// answers `false` via the resolver's substrate default
3853 /// [`Classification::gate_compute`] carrying its chosen
3854 /// `point_type: Gate` field (not via a `#[default]` short-circuit
3855 /// on the point-type axis itself). The resolver-hop shape is
3856 /// byte-identical across all six peers.
3857 ///
3858 /// # Semantics — resolver hop + derived-nullary-boolean
3859 ///
3860 /// `point_is_endomorphic()` returns `true` iff
3861 /// `self.resolved_classification().point_is_endomorphic()`. The
3862 /// resolver returns the authored [`Classification`] when present
3863 /// and the substrate default [`Classification::gate_compute`] on
3864 /// absence. Because [`Classification::gate_compute`] carries
3865 /// [`crate::classification::ConvergencePointType::Gate`] (a
3866 /// convergent barrier point, not a 1→1 endomorphism), a bare
3867 /// ephemeral spec with no `:classification` slot answers `false`.
3868 /// A regression that dropped the resolver hop, probed the wrong
3869 /// closed-set arm, or inverted the projection fails HERE at ONE
3870 /// narrow substrate site before drifting through every unadorned
3871 /// ephemeral spec's DAG-composition answer.
3872 ///
3873 /// # Compounding
3874 ///
3875 /// The ephemeral require-tag classifier composes this primitive
3876 /// as a fixed tag `endomorphic-point` on
3877 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3878 /// surface's `endomorphic-point` fixed tag on
3879 /// `POINT_FIXED_TAG_ARMS` via
3880 /// [`Classification::point_is_endomorphic`] directly. The two-
3881 /// surface parity contract holds by construction: both surfaces
3882 /// route through the SAME
3883 /// [`Classification::point_is_endomorphic`] primitive after the
3884 /// ephemeral surface pays ONE resolver hop — a future
3885 /// [`crate::classification::ConvergencePointType`] variant or a
3886 /// future normalization at the substrate primitive lands at ONE
3887 /// site and both surfaces' `endomorphic-point` fixed tags inherit
3888 /// the shift mechanically. Sibling projections
3889 /// [`crate::classification::ConvergencePointType::is_diffusive`]
3890 /// and [`crate::classification::ConvergencePointType::is_convergent`]
3891 /// compose byte-identically as future seventh + eighth ephemeral-
3892 /// surface peers; when all three land the three-way partition
3893 /// contract sealed on the closed set by
3894 /// `convergence_point_type_buckets_cover_every_variant` composes
3895 /// through the resolver-hop layer as a substrate-wide theorem.
3896 ///
3897 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3898 /// preserves proofs; the classification-`point_type`-axis derived-
3899 /// nullary-boolean probe body composes ONE resolver primitive
3900 /// ([`Self::resolved_classification`]) with ONE
3901 /// [`Classification`] primitive
3902 /// ([`Classification::point_is_endomorphic`]) so every downstream
3903 /// (`endomorphic-point` fixed tags on both surfaces in tatara-check,
3904 /// future DAG composition / edge-cardinality validators, future
3905 /// variant additions on
3906 /// [`crate::classification::ConvergencePointType`]) binds through
3907 /// the SAME `point_is_endomorphic()` shape rather than restating
3908 /// either the resolver walk or the closed-set projection
3909 /// composition at the callsite. THEORY.md §VI.1 — generation over
3910 /// composition; a future
3911 /// [`crate::classification::ConvergencePointType`] variant lands
3912 /// at ONE `ALL` entry + ONE `is_endomorphic` arm on the closed
3913 /// set and both surfaces pick it up mechanically.
3914 #[must_use]
3915 pub fn point_is_endomorphic(&self) -> bool {
3916 self.resolved_classification().point_is_endomorphic()
3917 }
3918
3919 /// Derived-boolean predicate — does this ephemeral spec's
3920 /// resolved [`Classification`]'s
3921 /// [`crate::classification::ConvergencePointType`] project to
3922 /// `true` under
3923 /// [`crate::classification::ConvergencePointType::is_diffusive`]?
3924 /// Byte-for-byte peer of
3925 /// [`Classification::point_is_diffusive`] wrapped through the
3926 /// [`Self::resolved_classification`] resolver so an operator-
3927 /// omitted `:classification` slot on `(defephemeral …)` still
3928 /// answers via the substrate default. The ONE ephemeral-surface
3929 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3930 /// derived-nullary-boolean walk on the 1→N fan-out topology-bucket
3931 /// question over the classification-`point_type` axis.
3932 ///
3933 /// # Seventh derived-nullary-boolean peer on the ephemeral surface
3934 ///
3935 /// Peer of [`Self::horizon_terminates`],
3936 /// [`Self::horizon_requires_metric_axes`],
3937 /// [`Self::calm_requires_coordination`],
3938 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`], and
3939 /// [`Self::point_is_endomorphic`] on the ephemeral surface's
3940 /// (resolver-hop × derived-nullary-bool) shape — the SEVENTH peer
3941 /// overall and the SECOND peer threading the classification-
3942 /// `point_type` axis. Direct-scalar peer of
3943 /// [`Self::point_is_endomorphic`]: both compose the SAME resolver
3944 /// hop and the SAME closed-set carrier through the SAME chosen-
3945 /// field baseline discipline (`Gate.is_diffusive() = false`,
3946 /// mirror-image of `Gate.is_endomorphic() = false`). The
3947 /// resolver-hop shape is byte-identical across all seven peers.
3948 ///
3949 /// # Semantics — resolver hop + derived-nullary-boolean
3950 ///
3951 /// `point_is_diffusive()` returns `true` iff
3952 /// `self.resolved_classification().point_is_diffusive()`. The
3953 /// resolver returns the authored [`Classification`] when present
3954 /// and the substrate default [`Classification::gate_compute`] on
3955 /// absence. Because [`Classification::gate_compute`] carries
3956 /// [`crate::classification::ConvergencePointType::Gate`] (a
3957 /// convergent barrier, not a fan-out), a bare ephemeral spec with
3958 /// no `:classification` slot answers `false`. A regression that
3959 /// dropped the resolver hop, probed the wrong closed-set arm, or
3960 /// inverted the projection fails HERE at ONE narrow substrate
3961 /// site before drifting through every unadorned ephemeral spec's
3962 /// DAG-composition answer.
3963 ///
3964 /// # Compounding — first ephemeral-surface corner-peer mutex on the `point_type` axis
3965 ///
3966 /// The ephemeral require-tag classifier composes this primitive
3967 /// as a fixed tag `diffusive-point` on `EPHEMERAL_FIXED_TAG_ARMS`
3968 /// — byte-for-byte peer of the point surface's `diffusive-point`
3969 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3970 /// [`Classification::point_is_diffusive`] directly. The two-
3971 /// surface parity contract holds by construction: both surfaces
3972 /// route through the SAME
3973 /// [`Classification::point_is_diffusive`] primitive after the
3974 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
3975 /// surface corner-peer pair on the `point_type` axis (with
3976 /// [`Self::point_is_endomorphic`]) whose two projections carry a
3977 /// non-trivial closed-set-internal MUTEX relationship
3978 /// (`point_is_endomorphic ⇒ ¬point_is_diffusive`), distinct from
3979 /// the sibling `data`-axis ephemeral corner-peer pair whose two
3980 /// projections carry a non-trivial IMPLICATION relationship. When
3981 /// the third sibling [`Self::point_is_convergent`] lands, the
3982 /// mutex closes into the full three-way XOR partition composed
3983 /// through the resolver-hop layer as a substrate-wide theorem.
3984 ///
3985 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3986 /// preserves proofs; the classification-`point_type`-axis derived-
3987 /// nullary-boolean probe body composes ONE resolver primitive
3988 /// ([`Self::resolved_classification`]) with ONE
3989 /// [`Classification`] primitive
3990 /// ([`Classification::point_is_diffusive`]) so every downstream
3991 /// (`diffusive-point` fixed tags on both surfaces in tatara-check,
3992 /// future DAG composition / edge-cardinality validators, future
3993 /// variant additions on
3994 /// [`crate::classification::ConvergencePointType`]) binds through
3995 /// the SAME `point_is_diffusive()` shape rather than restating
3996 /// either the resolver walk or the closed-set projection
3997 /// composition at the callsite. THEORY.md §VI.1 — generation over
3998 /// composition; a future
3999 /// [`crate::classification::ConvergencePointType`] variant lands
4000 /// at ONE `ALL` entry + ONE `is_diffusive` arm on the closed set
4001 /// and both surfaces pick it up mechanically.
4002 #[must_use]
4003 pub fn point_is_diffusive(&self) -> bool {
4004 self.resolved_classification().point_is_diffusive()
4005 }
4006
4007 /// Derived-boolean predicate — does this ephemeral spec's
4008 /// resolved [`Classification`]'s
4009 /// [`crate::classification::ConvergencePointType`] project to
4010 /// `true` under
4011 /// [`crate::classification::ConvergencePointType::is_convergent`]?
4012 /// Byte-for-byte peer of
4013 /// [`Classification::point_is_convergent`] wrapped through the
4014 /// [`Self::resolved_classification`] resolver so an operator-
4015 /// omitted `:classification` slot on `(defephemeral …)` still
4016 /// answers via the substrate default. The ONE ephemeral-surface
4017 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4018 /// derived-nullary-boolean walk on the N→1 fan-in topology-bucket
4019 /// question over the classification-`point_type` axis.
4020 ///
4021 /// # Eighth derived-nullary-boolean peer on the ephemeral surface
4022 ///
4023 /// Peer of [`Self::horizon_terminates`],
4024 /// [`Self::horizon_requires_metric_axes`],
4025 /// [`Self::calm_requires_coordination`],
4026 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4027 /// [`Self::point_is_endomorphic`], and [`Self::point_is_diffusive`]
4028 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4029 /// bool) shape — the EIGHTH peer overall and the THIRD peer
4030 /// threading the classification-`point_type` axis. Direct-scalar
4031 /// peer of [`Self::point_is_endomorphic`] and
4032 /// [`Self::point_is_diffusive`]: the three compose the SAME
4033 /// resolver hop and the SAME closed-set carrier through the SAME
4034 /// chosen-field baseline discipline, but the answer flips on the
4035 /// baseline — `Gate.is_convergent() = true`, so an ephemeral spec
4036 /// with no `:classification` slot answers `true` HERE (mirror-
4037 /// inverted from the two sibling probes which answer `false`).
4038 /// The resolver-hop shape is byte-identical across all eight
4039 /// peers.
4040 ///
4041 /// # Semantics — resolver hop + derived-nullary-boolean
4042 ///
4043 /// `point_is_convergent()` returns `true` iff
4044 /// `self.resolved_classification().point_is_convergent()`. The
4045 /// resolver returns the authored [`Classification`] when present
4046 /// and the substrate default [`Classification::gate_compute`] on
4047 /// absence. Because [`Classification::gate_compute`] carries
4048 /// [`crate::classification::ConvergencePointType::Gate`] (the
4049 /// canonical convergent barrier), a bare ephemeral spec with no
4050 /// `:classification` slot answers `true` — a regression that
4051 /// dropped the resolver hop, probed the wrong closed-set arm, or
4052 /// inverted the projection fails HERE at ONE narrow substrate
4053 /// site before drifting through every unadorned ephemeral spec's
4054 /// DAG-composition answer.
4055 ///
4056 /// # Compounding — closes the three-way XOR partition on the ephemeral surface
4057 ///
4058 /// The ephemeral require-tag classifier composes this primitive
4059 /// as a fixed tag `convergent-point` on `EPHEMERAL_FIXED_TAG_ARMS`
4060 /// — byte-for-byte peer of the point surface's `convergent-point`
4061 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4062 /// [`Classification::point_is_convergent`] directly. The two-
4063 /// surface parity contract holds by construction: both surfaces
4064 /// route through the SAME
4065 /// [`Classification::point_is_convergent`] primitive after the
4066 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
4067 /// surface peer on the `point_type` axis closing the mutex pair
4068 /// [`Self::point_is_endomorphic`] / [`Self::point_is_diffusive`]
4069 /// into the FULL three-way XOR partition contract composed
4070 /// through the resolver-hop layer as a substrate-wide theorem.
4071 ///
4072 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4073 /// preserves proofs; the classification-`point_type`-axis derived-
4074 /// nullary-boolean probe body composes ONE resolver primitive
4075 /// ([`Self::resolved_classification`]) with ONE
4076 /// [`Classification`] primitive
4077 /// ([`Classification::point_is_convergent`]) so every downstream
4078 /// (`convergent-point` fixed tags on both surfaces in tatara-check,
4079 /// future DAG composition / edge-cardinality validators, future
4080 /// variant additions on
4081 /// [`crate::classification::ConvergencePointType`]) binds through
4082 /// the SAME `point_is_convergent()` shape rather than restating
4083 /// either the resolver walk or the closed-set projection
4084 /// composition at the callsite. THEORY.md §VI.1 — generation over
4085 /// composition; a future
4086 /// [`crate::classification::ConvergencePointType`] variant lands
4087 /// at ONE `ALL` entry + ONE `is_convergent` arm on the closed set
4088 /// and both surfaces pick it up mechanically.
4089 #[must_use]
4090 pub fn point_is_convergent(&self) -> bool {
4091 self.resolved_classification().point_is_convergent()
4092 }
4093
4094 /// Derived-boolean predicate — does this ephemeral spec's
4095 /// resolved [`Classification`]'s
4096 /// [`crate::classification::SubstrateType`] project to `true`
4097 /// under [`crate::classification::SubstrateType::is_resource`]?
4098 /// Byte-for-byte peer of
4099 /// [`Classification::substrate_is_resource`] wrapped through the
4100 /// [`Self::resolved_classification`] resolver so an operator-
4101 /// omitted `:classification` slot on `(defephemeral …)` still
4102 /// answers via the substrate default. The ONE ephemeral-surface
4103 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4104 /// derived-nullary-boolean walk on the resource-plane bucket
4105 /// question over the classification-`substrate` axis.
4106 ///
4107 /// # Ninth derived-nullary-boolean peer on the ephemeral surface
4108 ///
4109 /// Peer of [`Self::horizon_terminates`],
4110 /// [`Self::horizon_requires_metric_axes`],
4111 /// [`Self::calm_requires_coordination`],
4112 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4113 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4114 /// and [`Self::point_is_convergent`] on the ephemeral surface's
4115 /// (resolver-hop × derived-nullary-bool) shape — the NINTH peer
4116 /// overall and the FIRST peer threading the classification-
4117 /// `substrate` axis (the fourth of six classification axes
4118 /// participating on this corner, after `horizon`, `calm`,
4119 /// `data_classification`, and `point_type`). The resolver-hop
4120 /// shape is byte-identical across all nine peers.
4121 ///
4122 /// # Semantics — resolver hop + derived-nullary-boolean
4123 ///
4124 /// `substrate_is_resource()` returns `true` iff
4125 /// `self.resolved_classification().substrate_is_resource()`. The
4126 /// resolver returns the authored [`Classification`] when present
4127 /// and the substrate default [`Classification::gate_compute`] on
4128 /// absence. Because [`Classification::gate_compute`] carries
4129 /// [`crate::classification::SubstrateType::Compute`] (the
4130 /// canonical resource-plane substrate), a bare ephemeral spec
4131 /// with no `:classification` slot answers `true` — a regression
4132 /// that dropped the resolver hop, probed the wrong closed-set
4133 /// arm, or inverted the projection fails HERE at ONE narrow
4134 /// substrate site before drifting through every unadorned
4135 /// ephemeral spec's plane-baseline answer.
4136 ///
4137 /// # Compounding — opens the substrate axis on the ephemeral surface
4138 ///
4139 /// The ephemeral require-tag classifier composes this primitive
4140 /// as a fixed tag `resource-substrate` on
4141 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4142 /// surface's `resource-substrate` fixed tag on
4143 /// `POINT_FIXED_TAG_ARMS` via
4144 /// [`Classification::substrate_is_resource`] directly. The two-
4145 /// surface parity contract holds by construction: both surfaces
4146 /// route through the SAME
4147 /// [`Classification::substrate_is_resource`] primitive after the
4148 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
4149 /// surface peer on the `substrate` axis — future sibling
4150 /// projections [`crate::classification::SubstrateType::is_policy`]
4151 /// and [`crate::classification::SubstrateType::is_telemetry`]
4152 /// compose byte-identically as future tenth + eleventh peers,
4153 /// closing the axis into a proven-repeatable three-peer sub-
4154 /// corner exactly as the `point_type` axis was closed on this
4155 /// surface by
4156 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4157 ///
4158 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4159 /// preserves proofs; the classification-`substrate`-axis derived-
4160 /// nullary-boolean probe body composes ONE resolver primitive
4161 /// ([`Self::resolved_classification`]) with ONE
4162 /// [`Classification`] primitive
4163 /// ([`Classification::substrate_is_resource`]) so every
4164 /// downstream (`resource-substrate` fixed tags on both surfaces
4165 /// in tatara-check, future plane-baseline / compliance-baseline
4166 /// selectors, future variant additions on
4167 /// [`crate::classification::SubstrateType`]) binds through the
4168 /// SAME `substrate_is_resource()` shape rather than restating
4169 /// either the resolver walk or the closed-set projection
4170 /// composition at the callsite. THEORY.md §VI.1 — generation
4171 /// over composition; a future
4172 /// [`crate::classification::SubstrateType`] variant lands at ONE
4173 /// `ALL` entry + ONE `is_resource` arm on the closed set and
4174 /// both surfaces pick it up mechanically.
4175 #[must_use]
4176 pub fn substrate_is_resource(&self) -> bool {
4177 self.resolved_classification().substrate_is_resource()
4178 }
4179
4180 /// Derived-boolean predicate — does this ephemeral spec's
4181 /// resolved [`Classification`]'s
4182 /// [`crate::classification::SubstrateType`] project to `true`
4183 /// under [`crate::classification::SubstrateType::is_policy`]?
4184 /// Byte-for-byte peer of
4185 /// [`Classification::substrate_is_policy`] wrapped through the
4186 /// [`Self::resolved_classification`] resolver so an operator-
4187 /// omitted `:classification` slot on `(defephemeral …)` still
4188 /// answers via the substrate default. The ONE ephemeral-surface
4189 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4190 /// derived-nullary-boolean walk on the policy-plane bucket
4191 /// question over the classification-`substrate` axis.
4192 ///
4193 /// # Tenth derived-nullary-boolean peer on the ephemeral surface
4194 ///
4195 /// Peer of [`Self::horizon_terminates`],
4196 /// [`Self::horizon_requires_metric_axes`],
4197 /// [`Self::calm_requires_coordination`],
4198 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4199 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4200 /// [`Self::point_is_convergent`], and
4201 /// [`Self::substrate_is_resource`] on the ephemeral surface's
4202 /// (resolver-hop × derived-nullary-bool) shape — the TENTH peer
4203 /// overall and the SECOND peer threading the classification-
4204 /// `substrate` axis, promoting that axis on this surface from a
4205 /// proven-repeatable one-off to a proven-repeatable pair.
4206 /// FIRST ephemeral-surface substrate-axis corner-peer pair
4207 /// carrying a non-trivial closed-set-internal MUTEX relationship
4208 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`), structural
4209 /// twin of the sibling `point_type`-axis MUTEX pair sealed on
4210 /// this surface by
4211 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
4212 /// The resolver-hop shape is byte-identical across all ten peers.
4213 ///
4214 /// # Semantics — resolver hop + derived-nullary-boolean
4215 ///
4216 /// `substrate_is_policy()` returns `true` iff
4217 /// `self.resolved_classification().substrate_is_policy()`. The
4218 /// resolver returns the authored [`Classification`] when present
4219 /// and the substrate default [`Classification::gate_compute`] on
4220 /// absence. Because [`Classification::gate_compute`] carries
4221 /// [`crate::classification::SubstrateType::Compute`] (the
4222 /// canonical resource-plane substrate, NOT a policy plane), a
4223 /// bare ephemeral spec with no `:classification` slot answers
4224 /// `false` — a regression that dropped the resolver hop, probed
4225 /// the wrong closed-set arm, or inverted the projection fails
4226 /// HERE at ONE narrow substrate site before drifting through
4227 /// every unadorned ephemeral spec's plane-baseline answer.
4228 ///
4229 /// # Compounding — second substrate-axis peer on the ephemeral surface
4230 ///
4231 /// The ephemeral require-tag classifier composes this primitive
4232 /// as a fixed tag `policy-substrate` on
4233 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4234 /// surface's `policy-substrate` fixed tag on
4235 /// `POINT_FIXED_TAG_ARMS` via
4236 /// [`Classification::substrate_is_policy`] directly. The two-
4237 /// surface parity contract holds by construction: both surfaces
4238 /// route through the SAME
4239 /// [`Classification::substrate_is_policy`] primitive after the
4240 /// ephemeral surface pays ONE resolver hop. SECOND ephemeral-
4241 /// surface peer on the `substrate` axis — sibling projection
4242 /// [`crate::classification::SubstrateType::is_telemetry`]
4243 /// composes byte-identically as a future eleventh peer, closing
4244 /// the axis into a proven-repeatable three-peer sub-corner
4245 /// exactly as the `point_type` axis was closed on this surface
4246 /// by
4247 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4248 ///
4249 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4250 /// preserves proofs; the classification-`substrate`-axis derived-
4251 /// nullary-boolean probe body composes ONE resolver primitive
4252 /// ([`Self::resolved_classification`]) with ONE
4253 /// [`Classification`] primitive
4254 /// ([`Classification::substrate_is_policy`]) so every
4255 /// downstream (`policy-substrate` fixed tags on both surfaces
4256 /// in tatara-check, future plane-baseline / compliance-baseline
4257 /// selectors, future variant additions on
4258 /// [`crate::classification::SubstrateType`]) binds through the
4259 /// SAME `substrate_is_policy()` shape rather than restating
4260 /// either the resolver walk or the closed-set projection
4261 /// composition at the callsite. THEORY.md §VI.1 — generation
4262 /// over composition; a future
4263 /// [`crate::classification::SubstrateType`] variant lands at ONE
4264 /// `ALL` entry + ONE `is_policy` arm on the closed set and
4265 /// both surfaces pick it up mechanically.
4266 #[must_use]
4267 pub fn substrate_is_policy(&self) -> bool {
4268 self.resolved_classification().substrate_is_policy()
4269 }
4270
4271 /// Derived-boolean predicate — does this ephemeral spec's
4272 /// resolved [`Classification`]'s
4273 /// [`crate::classification::SubstrateType`] project to `true`
4274 /// under [`crate::classification::SubstrateType::is_telemetry`]?
4275 /// Byte-for-byte peer of
4276 /// [`Classification::substrate_is_telemetry`] wrapped through
4277 /// the [`Self::resolved_classification`] resolver so an operator-
4278 /// omitted `:classification` slot on `(defephemeral …)` still
4279 /// answers via the substrate default. The ONE ephemeral-surface
4280 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4281 /// derived-nullary-boolean walk on the telemetry-plane bucket
4282 /// question over the classification-`substrate` axis.
4283 ///
4284 /// # Eleventh derived-nullary-boolean peer on the ephemeral surface — CLOSES the substrate axis
4285 ///
4286 /// Peer of [`Self::horizon_terminates`],
4287 /// [`Self::horizon_requires_metric_axes`],
4288 /// [`Self::calm_requires_coordination`],
4289 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4290 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4291 /// [`Self::point_is_convergent`], [`Self::substrate_is_resource`],
4292 /// and [`Self::substrate_is_policy`] on the ephemeral surface's
4293 /// (resolver-hop × derived-nullary-bool) shape — the ELEVENTH
4294 /// peer overall and the THIRD peer threading the classification-
4295 /// `substrate` axis. This peer CLOSES the substrate axis on the
4296 /// ephemeral surface into the FULL three-way XOR partition
4297 /// contract `substrate_is_resource ⊕ substrate_is_policy ⊕
4298 /// substrate_is_telemetry` — sealed on this surface by
4299 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
4300 /// the resolver-hop peer of the parent-composed
4301 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`.
4302 /// Structural twin of the sibling `point_type`-axis ternary lift
4303 /// sealed on this surface by
4304 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4305 /// The resolver-hop shape is byte-identical across all eleven
4306 /// peers.
4307 ///
4308 /// # Semantics — resolver hop + derived-nullary-boolean
4309 ///
4310 /// `substrate_is_telemetry()` returns `true` iff
4311 /// `self.resolved_classification().substrate_is_telemetry()`.
4312 /// The resolver returns the authored [`Classification`] when
4313 /// present and the substrate default [`Classification::gate_compute`]
4314 /// on absence. Because [`Classification::gate_compute`] carries
4315 /// [`crate::classification::SubstrateType::Compute`] (the
4316 /// canonical resource-plane substrate, NOT a telemetry plane),
4317 /// a bare ephemeral spec with no `:classification` slot answers
4318 /// `false` — a regression that dropped the resolver hop, probed
4319 /// the wrong closed-set arm, or inverted the projection fails
4320 /// HERE at ONE narrow substrate site before drifting through
4321 /// every unadorned ephemeral spec's plane-baseline answer.
4322 ///
4323 /// # Compounding — CLOSES the substrate axis on the ephemeral surface
4324 ///
4325 /// The ephemeral require-tag classifier composes this primitive
4326 /// as a fixed tag `telemetry-substrate` on
4327 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4328 /// surface's `telemetry-substrate` fixed tag on
4329 /// `POINT_FIXED_TAG_ARMS` via
4330 /// [`Classification::substrate_is_telemetry`] directly. The two-
4331 /// surface parity contract holds by construction: both surfaces
4332 /// route through the SAME
4333 /// [`Classification::substrate_is_telemetry`] primitive after the
4334 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
4335 /// surface peer on the `substrate` axis — closes the axis into a
4336 /// proven-repeatable three-peer sub-corner exactly as the
4337 /// `point_type` axis was closed on this surface by
4338 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4339 ///
4340 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4341 /// preserves proofs; the classification-`substrate`-axis derived-
4342 /// nullary-boolean probe body composes ONE resolver primitive
4343 /// ([`Self::resolved_classification`]) with ONE
4344 /// [`Classification`] primitive
4345 /// ([`Classification::substrate_is_telemetry`]) so every
4346 /// downstream (`telemetry-substrate` fixed tags on both surfaces
4347 /// in tatara-check, future plane-baseline / compliance-baseline
4348 /// selectors, future variant additions on
4349 /// [`crate::classification::SubstrateType`]) binds through the
4350 /// SAME `substrate_is_telemetry()` shape rather than restating
4351 /// either the resolver walk or the closed-set projection
4352 /// composition at the callsite. THEORY.md §VI.1 — generation
4353 /// over composition; a future
4354 /// [`crate::classification::SubstrateType`] variant lands at ONE
4355 /// `ALL` entry + ONE `is_telemetry` arm on the closed set and
4356 /// both surfaces pick it up mechanically.
4357 #[must_use]
4358 pub fn substrate_is_telemetry(&self) -> bool {
4359 self.resolved_classification().substrate_is_telemetry()
4360 }
4361
4362 /// Derived-boolean predicate — does this ephemeral spec's
4363 /// resolved [`Classification`]'s
4364 /// [`crate::classification::CalmClassification`] project to `true`
4365 /// under [`crate::classification::CalmClassification::is_monotone`]?
4366 /// Byte-for-byte peer of [`Classification::calm_is_monotone`]
4367 /// wrapped through the [`Self::resolved_classification`] resolver
4368 /// so an operator-omitted `:classification` slot on
4369 /// `(defephemeral …)` still answers via the substrate default.
4370 /// The ONE ephemeral-surface substrate primitive that owns the
4371 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4372 /// CALM-monotone-plane question — the positive framing peer of
4373 /// [`Self::calm_requires_coordination`].
4374 ///
4375 /// # Twelfth derived-nullary-boolean peer on the ephemeral surface — CLOSES the calm axis
4376 ///
4377 /// Peer of [`Self::horizon_terminates`],
4378 /// [`Self::horizon_requires_metric_axes`],
4379 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4380 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4381 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4382 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4383 /// and [`Self::substrate_is_telemetry`] on the ephemeral
4384 /// surface's (resolver-hop × derived-nullary-bool) shape — the
4385 /// TWELFTH peer overall and the SECOND peer threading the
4386 /// classification-`calm` axis. This peer CLOSES the calm axis
4387 /// on the ephemeral surface into the FULL binary XOR partition
4388 /// contract `calm_is_monotone ⊕ calm_requires_coordination` —
4389 /// sealed on this surface by
4390 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
4391 /// the resolver-hop peer of the parent-composed
4392 /// `classification_calm_probes_form_binary_xor_partition_over_all`.
4393 /// Structural twin of the sibling horizon-axis binary XOR
4394 /// sealed on the closed set by
4395 /// `horizon_kind_terminate_xor_requires_metric_axes`, lifted
4396 /// through the resolver hop to the ephemeral surface. The
4397 /// resolver-hop shape is byte-identical across all twelve peers.
4398 ///
4399 /// # Semantics — resolver hop + derived-nullary-boolean
4400 ///
4401 /// `calm_is_monotone()` returns `true` iff
4402 /// `self.resolved_classification().calm_is_monotone()`. The
4403 /// resolver returns the authored [`Classification`] when present
4404 /// and the substrate default [`Classification::gate_compute`] on
4405 /// absence. Because [`Classification::gate_compute`] carries
4406 /// [`crate::classification::CalmClassification::default =
4407 /// Monotone`] via `#[default]`, a bare ephemeral spec with no
4408 /// `:classification` slot answers `true` — every unadorned
4409 /// `(defephemeral …)` reads as gossip-eligible under the
4410 /// positive CALM framing, safe under Hellerstein's theorem
4411 /// (monotone operations distribute without coordination). A
4412 /// regression that dropped the resolver hop, probed the wrong
4413 /// closed-set arm, or inverted the projection fails HERE at ONE
4414 /// narrow substrate site before drifting through every
4415 /// unadorned ephemeral spec's positive-CALM-framing answer.
4416 /// Mirror-inverted from the sibling
4417 /// `calm_requires_coordination_probes_false_on_absent_classification`
4418 /// (both walk the SAME defaulted `calm` field, so
4419 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
4420 /// closed set's disjoint XOR partition).
4421 ///
4422 /// # Compounding — CLOSES the calm axis on the ephemeral surface
4423 ///
4424 /// The ephemeral require-tag classifier composes this primitive
4425 /// as a fixed tag `monotone-calm` on `EPHEMERAL_FIXED_TAG_ARMS`
4426 /// — byte-for-byte peer of the point surface's `monotone-calm`
4427 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4428 /// [`Classification::calm_is_monotone`] directly. The two-
4429 /// surface parity contract holds by construction: both surfaces
4430 /// route through the SAME [`Classification::calm_is_monotone`]
4431 /// primitive after the ephemeral surface pays ONE resolver hop.
4432 /// SECOND ephemeral-surface peer on the `calm` axis — CLOSES the
4433 /// axis into a proven-repeatable two-peer sub-corner exactly as
4434 /// the `horizon` axis is closed on the closed-set layer by
4435 /// `horizon_kind_terminate_xor_requires_metric_axes`.
4436 ///
4437 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4438 /// preserves proofs; the classification-`calm`-axis derived-
4439 /// nullary-boolean probe body composes ONE resolver primitive
4440 /// ([`Self::resolved_classification`]) with ONE
4441 /// [`Classification`] primitive
4442 /// ([`Classification::calm_is_monotone`]) so every downstream
4443 /// (`monotone-calm` fixed tags on both surfaces in tatara-check,
4444 /// future scheduler / gossip-eligibility validators reading the
4445 /// positive CALM framing, future variant additions on
4446 /// [`crate::classification::CalmClassification`]) binds through
4447 /// the SAME `calm_is_monotone()` shape rather than restating
4448 /// either the resolver walk or the closed-set projection
4449 /// composition at the callsite. THEORY.md §VI.1 — generation
4450 /// over composition; a future
4451 /// [`crate::classification::CalmClassification`] variant lands
4452 /// at ONE `ALL` entry + ONE `is_monotone` arm on the closed set
4453 /// and both surfaces pick it up mechanically.
4454 #[must_use]
4455 pub fn calm_is_monotone(&self) -> bool {
4456 self.resolved_classification().calm_is_monotone()
4457 }
4458
4459 /// Derived-boolean predicate — does this ephemeral spec's
4460 /// resolved [`Classification`]'s
4461 /// [`crate::classification::DataClassification`] project to `true`
4462 /// under [`crate::classification::DataClassification::is_public`]?
4463 /// Byte-for-byte peer of [`Classification::data_is_public`]
4464 /// wrapped through the [`Self::resolved_classification`] resolver
4465 /// so an operator-omitted `:classification` slot on
4466 /// `(defephemeral …)` still answers via the substrate default.
4467 /// The ONE ephemeral-surface substrate primitive that owns the
4468 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4469 /// freely-distributable-data question — the positive framing peer
4470 /// of [`Self::data_is_restricted`].
4471 ///
4472 /// # Thirteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the data axis
4473 ///
4474 /// Peer of [`Self::horizon_terminates`],
4475 /// [`Self::horizon_requires_metric_axes`],
4476 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4477 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4478 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4479 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4480 /// [`Self::substrate_is_telemetry`], and [`Self::calm_is_monotone`]
4481 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
4482 /// shape — the THIRTEENTH peer overall and the THIRD peer
4483 /// threading the classification-`data_classification` axis. This
4484 /// peer CLOSES the data axis on the ephemeral surface into the
4485 /// FULL binary XOR partition contract
4486 /// `data_is_public ⊕ data_is_restricted` — sealed on this surface
4487 /// by `ephemeral_data_probes_form_binary_xor_partition_over_all`,
4488 /// the resolver-hop peer of the parent-composed
4489 /// `classification_data_probes_form_binary_xor_partition_over_all`.
4490 /// Structural twin of the sibling calm-axis binary XOR sealed on
4491 /// this surface by
4492 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
4493 /// lifted through the resolver hop from the six-variant data-axis
4494 /// closed set to the ephemeral surface. The resolver-hop shape is
4495 /// byte-identical across all thirteen peers.
4496 ///
4497 /// # Semantics — resolver hop + derived-nullary-boolean
4498 ///
4499 /// `data_is_public()` returns `true` iff
4500 /// `self.resolved_classification().data_is_public()`. The
4501 /// resolver returns the authored [`Classification`] when present
4502 /// and the substrate default [`Classification::gate_compute`] on
4503 /// absence. Because [`Classification::gate_compute`] carries
4504 /// [`crate::classification::DataClassification::default =
4505 /// Internal`] via `#[default]`, a bare ephemeral spec with no
4506 /// `:classification` slot answers `false` — every unadorned
4507 /// `(defephemeral …)` reads as access-controlled by default (safe
4508 /// under compliance baseline: an operator must deliberately opt
4509 /// the dataset into public distribution rather than the substrate
4510 /// silently promoting an unadorned Process onto the freely-
4511 /// distributable path). A regression that dropped the resolver
4512 /// hop, probed the wrong closed-set arm, or inverted the
4513 /// projection fails HERE at ONE narrow substrate site before
4514 /// drifting through every unadorned ephemeral spec's positive-
4515 /// distribution-framing answer. Mirror-inverted from the sibling
4516 /// `data_is_restricted_probes_true_on_absent_classification`
4517 /// (both walk the SAME defaulted `data_classification` field, so
4518 /// `is_restricted = true` ⇒ `is_public = false` on the closed
4519 /// set's disjoint XOR partition).
4520 ///
4521 /// # Compounding — CLOSES the data axis on the ephemeral surface
4522 ///
4523 /// The ephemeral require-tag classifier composes this primitive
4524 /// as a fixed tag `public-data` on `EPHEMERAL_FIXED_TAG_ARMS`
4525 /// — byte-for-byte peer of the point surface's `public-data`
4526 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4527 /// [`Classification::data_is_public`] directly. The two-
4528 /// surface parity contract holds by construction: both surfaces
4529 /// route through the SAME [`Classification::data_is_public`]
4530 /// primitive after the ephemeral surface pays ONE resolver hop.
4531 /// THIRD ephemeral-surface peer on the `data_classification` axis
4532 /// — CLOSES the axis into a proven-repeatable three-peer sub-
4533 /// corner (data_is_regulated, data_is_restricted, data_is_public)
4534 /// whose complementary XOR partition seals on the closed set by
4535 /// `data_classification_public_xor_restricted` and composes
4536 /// through the resolver hop as a substrate-wide theorem.
4537 ///
4538 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4539 /// preserves proofs; the classification-`data_classification`-axis
4540 /// derived-nullary-boolean probe body composes ONE resolver
4541 /// primitive ([`Self::resolved_classification`]) with ONE
4542 /// [`Classification`] primitive
4543 /// ([`Classification::data_is_public`]) so every downstream
4544 /// (`public-data` fixed tags on both surfaces in tatara-check,
4545 /// future compliance-baseline / audit-log-optional validators
4546 /// reading the positive distribution framing, future variant
4547 /// additions on
4548 /// [`crate::classification::DataClassification`]) binds through
4549 /// the SAME `data_is_public()` shape rather than restating either
4550 /// the resolver walk or the closed-set projection composition at
4551 /// the callsite. THEORY.md §VI.1 — generation over composition; a
4552 /// future [`crate::classification::DataClassification`] variant
4553 /// lands at ONE `ALL` entry + ONE `is_public` arm on the closed
4554 /// set and both surfaces pick it up mechanically.
4555 #[must_use]
4556 pub fn data_is_public(&self) -> bool {
4557 self.resolved_classification().data_is_public()
4558 }
4559
4560 /// Derived-boolean predicate — does this ephemeral spec's resolved
4561 /// [`Classification`]'s
4562 /// [`crate::classification::Horizon::direction`] slot (defaulted
4563 /// through [`crate::classification::OptimizationDirection::default =
4564 /// Minimize`] on absence) project to `true` under
4565 /// [`crate::classification::OptimizationDirection::prefers_lower`]?
4566 /// Byte-for-byte peer of
4567 /// [`crate::classification::Classification::direction_prefers_lower`]
4568 /// wrapped through the [`Self::resolved_classification`] resolver so
4569 /// an operator-omitted `:classification` slot on
4570 /// `(defephemeral …)` still answers via the substrate default. The
4571 /// ONE ephemeral-surface substrate primitive that owns the
4572 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4573 /// lower-is-better optimization-polarity question.
4574 ///
4575 /// # Fourteenth derived-nullary-boolean peer on the ephemeral surface — opens the optimization-direction axis
4576 ///
4577 /// Peer of the thirteen prior nullary-boolean substrate primitives
4578 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4579 /// [`Self::horizon_requires_metric_axes`],
4580 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4581 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4582 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4583 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4584 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4585 /// [`Self::data_is_public`]) on the ephemeral surface's
4586 /// (resolver-hop × derived-nullary-bool) shape — the FOURTEENTH
4587 /// peer overall and the FIRST peer threading the classification-
4588 /// `horizon.direction` axis on this surface. Opens the SIXTH
4589 /// classification axis into the ephemeral fixed-tag algebra after
4590 /// the horizon, calm, data, point, and substrate axes. The
4591 /// resolver-hop shape is byte-identical across all fourteen peers.
4592 ///
4593 /// # Semantics — resolver hop + derived-nullary-boolean
4594 ///
4595 /// `direction_prefers_lower()` returns `true` iff
4596 /// `self.resolved_classification().direction_prefers_lower()`. The
4597 /// resolver returns the authored [`Classification`] when present
4598 /// and the substrate default [`Classification::gate_compute`] on
4599 /// absence. Because [`Classification::gate_compute`] carries
4600 /// `horizon: Horizon::default()` whose `direction` field is `None`,
4601 /// and [`crate::classification::OptimizationDirection::default =
4602 /// Minimize`] projects `prefers_lower = true`, a bare ephemeral
4603 /// spec with no `:classification` slot answers `true` — every
4604 /// unadorned `(defephemeral …)` reads as lower-is-better under the
4605 /// substrate polarity default (safe under the asymptotic-health
4606 /// rate-window evaluator's convention: an operator must
4607 /// deliberately opt into Maximize polarity rather than the
4608 /// substrate silently flipping every unadorned Process onto the
4609 /// higher-is-better path). A regression that dropped the resolver
4610 /// hop, probed the wrong closed-set arm, or inverted the projection
4611 /// fails HERE at ONE narrow substrate site before drifting through
4612 /// every unadorned ephemeral spec's rate-window evaluator polarity.
4613 ///
4614 /// # Compounding — opens the optimization-direction axis on the ephemeral surface
4615 ///
4616 /// The ephemeral require-tag classifier composes this primitive as
4617 /// a fixed tag `prefers-lower-direction` on
4618 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4619 /// surface's `prefers-lower-direction` fixed tag on
4620 /// `POINT_FIXED_TAG_ARMS` via
4621 /// [`Classification::direction_prefers_lower`] directly. The
4622 /// two-surface parity contract holds by construction: both surfaces
4623 /// route through the SAME [`Classification::direction_prefers_lower`]
4624 /// primitive after the ephemeral surface pays ONE resolver hop.
4625 /// A future antisymmetric peer (`direction_prefers_higher`) closes
4626 /// the binary XOR partition on this axis — mirror of the calm-axis
4627 /// (`monotone-calm ⊕ coordination-required`) and data-axis
4628 /// (`public-data ⊕ data-restricted`) closures on this surface.
4629 ///
4630 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4631 /// preserves proofs; the classification-`horizon.direction`-axis
4632 /// derived-nullary-boolean probe body composes ONE resolver
4633 /// primitive ([`Self::resolved_classification`]) with ONE
4634 /// [`Classification`] primitive
4635 /// ([`Classification::direction_prefers_lower`]) so every
4636 /// downstream (the `prefers-lower-direction` fixed tags on both
4637 /// surfaces in tatara-check, future asymptotic-health rate-window
4638 /// / regression-detector evaluators, future variant additions on
4639 /// [`crate::classification::OptimizationDirection`]) binds through
4640 /// the SAME `direction_prefers_lower()` shape rather than restating
4641 /// either the resolver walk or the closed-set projection
4642 /// composition at the callsite. THEORY.md §VI.1 — generation over
4643 /// composition; a future
4644 /// [`crate::classification::OptimizationDirection`] variant lands
4645 /// at ONE `ALL` entry + ONE `prefers_lower` arm on the closed set
4646 /// and both surfaces pick it up mechanically.
4647 #[must_use]
4648 pub fn direction_prefers_lower(&self) -> bool {
4649 self.resolved_classification().direction_prefers_lower()
4650 }
4651
4652 /// POSITIVE-FRAMING PEER of [`Self::direction_prefers_lower`] —
4653 /// does this ephemeral spec's resolved [`Classification`]'s
4654 /// [`crate::classification::Horizon::direction`] slot (defaulted
4655 /// through [`crate::classification::OptimizationDirection::default =
4656 /// Minimize`] on absence) project to `true` under
4657 /// [`crate::classification::OptimizationDirection::prefers_higher`]?
4658 /// Byte-for-byte peer of
4659 /// [`crate::classification::Classification::direction_prefers_higher`]
4660 /// wrapped through the [`Self::resolved_classification`] resolver
4661 /// so an operator-omitted `:classification` slot on
4662 /// `(defephemeral …)` still answers via the substrate default. The
4663 /// ONE ephemeral-surface substrate primitive that owns the
4664 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4665 /// higher-is-better optimization-polarity question.
4666 ///
4667 /// # Fifteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the optimization-direction axis
4668 ///
4669 /// Peer of the fourteen prior nullary-boolean substrate primitives
4670 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4671 /// [`Self::horizon_requires_metric_axes`],
4672 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4673 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4674 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4675 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4676 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4677 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`]) on
4678 /// the ephemeral surface's (resolver-hop × derived-nullary-bool)
4679 /// shape — the FIFTEENTH peer overall and the SECOND peer
4680 /// threading the classification-`horizon.direction` axis on this
4681 /// surface. CLOSES the SIXTH classification axis into a binary XOR
4682 /// partition on the ephemeral surface after the horizon, calm,
4683 /// data, point, and substrate axes — completing the axis-coverage
4684 /// milestone on this surface: ALL SIX classification axes now
4685 /// have their partitions closed at the ephemeral-surface derived-
4686 /// nullary corner. The resolver-hop shape is byte-identical across
4687 /// all fifteen peers.
4688 ///
4689 /// # Semantics — resolver hop + derived-nullary-boolean
4690 ///
4691 /// `direction_prefers_higher()` returns `true` iff
4692 /// `self.resolved_classification().direction_prefers_higher()`.
4693 /// The resolver returns the authored [`Classification`] when
4694 /// present and the substrate default
4695 /// [`Classification::gate_compute`] on absence. Because
4696 /// [`Classification::gate_compute`] carries `horizon:
4697 /// Horizon::default()` whose `direction` field is `None`, and
4698 /// [`crate::classification::OptimizationDirection::default =
4699 /// Minimize`] projects `prefers_higher = false`, a bare ephemeral
4700 /// spec with no `:classification` slot answers `false` — every
4701 /// unadorned `(defephemeral …)` reads as lower-is-better under the
4702 /// substrate polarity default (safe under the asymptotic-health
4703 /// rate-window evaluator's convention: an operator must
4704 /// deliberately opt into Maximize polarity rather than the
4705 /// substrate silently flipping every unadorned Process onto the
4706 /// higher-is-better path). A regression that dropped the resolver
4707 /// hop, probed the wrong closed-set arm, or inverted the
4708 /// projection fails HERE at ONE narrow substrate site before
4709 /// drifting through every unadorned ephemeral spec's rate-window
4710 /// evaluator polarity.
4711 ///
4712 /// # Compounding — CLOSES the optimization-direction axis on the ephemeral surface
4713 ///
4714 /// The ephemeral require-tag classifier composes this primitive as
4715 /// a fixed tag `prefers-higher-direction` on
4716 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4717 /// surface's `prefers-higher-direction` fixed tag on
4718 /// `POINT_FIXED_TAG_ARMS` via
4719 /// [`Classification::direction_prefers_higher`] directly. The
4720 /// two-surface parity contract holds by construction: both
4721 /// surfaces route through the SAME
4722 /// [`Classification::direction_prefers_higher`] primitive after
4723 /// the ephemeral surface pays ONE resolver hop. SECOND
4724 /// optimization-direction-axis peer CLOSES the axis into the FULL
4725 /// binary XOR partition contract on this surface — the resolver-
4726 /// hop peer of the parent-composed
4727 /// `classification_direction_probes_form_binary_xor_partition_over_all`,
4728 /// mirror of the calm-axis (`monotone-calm ⊕ coordination-required`)
4729 /// and data-axis (`public-data ⊕ data-restricted`) closures on
4730 /// this surface.
4731 ///
4732 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4733 /// preserves proofs; the classification-`horizon.direction`-axis
4734 /// derived-nullary-boolean probe body composes ONE resolver
4735 /// primitive ([`Self::resolved_classification`]) with ONE
4736 /// [`Classification`] primitive
4737 /// ([`Classification::direction_prefers_higher`]) so every
4738 /// downstream (the `prefers-higher-direction` fixed tags on both
4739 /// surfaces in tatara-check, future asymptotic-health rate-window
4740 /// / regression-detector evaluators, future variant additions on
4741 /// [`crate::classification::OptimizationDirection`]) binds through
4742 /// the SAME `direction_prefers_higher()` shape rather than
4743 /// restating either the resolver walk or the closed-set projection
4744 /// composition at the callsite. THEORY.md §VI.1 — generation over
4745 /// composition; a future
4746 /// [`crate::classification::OptimizationDirection`] variant lands
4747 /// at ONE `ALL` entry + ONE `prefers_higher` arm on the closed set
4748 /// and both surfaces pick it up mechanically.
4749 #[must_use]
4750 pub fn direction_prefers_higher(&self) -> bool {
4751 self.resolved_classification().direction_prefers_higher()
4752 }
4753
4754 /// Derived-boolean predicate — does this ephemeral spec's resolved
4755 /// [`Classification`]'s `point_type` slot project to `Arity::One`
4756 /// under
4757 /// [`crate::classification::ConvergencePointType::input_arity`]?
4758 /// Byte-for-byte peer of
4759 /// [`crate::classification::Classification::input_arity_is_one`]
4760 /// wrapped through the [`Self::resolved_classification`] resolver
4761 /// so an operator-omitted `:classification` slot on
4762 /// `(defephemeral …)` still answers via the substrate default. The
4763 /// ONE ephemeral-surface substrate primitive that owns the
4764 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4765 /// single-input side of the DAG-composition input-arity projection.
4766 ///
4767 /// # Sixteenth derived-nullary-boolean peer on the ephemeral surface — opens the input-arity axis
4768 ///
4769 /// Peer of the fifteen prior nullary-boolean substrate primitives
4770 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4771 /// [`Self::horizon_requires_metric_axes`],
4772 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4773 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4774 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4775 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4776 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4777 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4778 /// [`Self::direction_prefers_higher`]) on the ephemeral surface's
4779 /// (resolver-hop × derived-nullary-bool) shape — the SIXTEENTH
4780 /// peer overall and the FIRST peer threading the classification-
4781 /// `point_type`-derived input-arity axis on this surface. Opens
4782 /// the SEVENTH classification axis into the ephemeral fixed-tag
4783 /// algebra after the horizon, calm, data, point-type, substrate,
4784 /// and optimization-direction axes. First peer on the derived-
4785 /// typed-projection stratum of the ephemeral surface — composes
4786 /// an extra closed-set-level projection hop
4787 /// ([`crate::classification::ConvergencePointType::input_arity`])
4788 /// compared to the sibling `point_is_*` triple that walks the raw
4789 /// `point_type` slot through the resolver. The resolver-hop shape
4790 /// is byte-identical across all sixteen peers.
4791 ///
4792 /// # Semantics — resolver hop + derived-nullary-boolean
4793 ///
4794 /// `input_arity_is_one()` returns `true` iff
4795 /// `self.resolved_classification().input_arity_is_one()`. The
4796 /// resolver returns the authored [`Classification`] when present
4797 /// and the substrate default [`Classification::gate_compute`] on
4798 /// absence. Because [`Classification::gate_compute`] carries
4799 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
4800 /// ephemeral spec with no `:classification` slot answers `false` —
4801 /// every unadorned `(defephemeral …)` lands in the multi-input
4802 /// bucket under the substrate default (`Gate` gates a
4803 /// many-to-one bucket dispatch, so the single-input bucket only
4804 /// applies to operator-authored specs on the `Transform | Fork |
4805 /// Broadcast | Observe` arms). A regression that dropped the
4806 /// resolver hop, probed the wrong closed-set arm, or crossed the
4807 /// wires with the sibling
4808 /// [`crate::classification::ConvergencePointType::output_arity`]
4809 /// projection (which disagrees on six of the eight variants) fails
4810 /// HERE at ONE narrow substrate site before drifting through
4811 /// every unadorned ephemeral spec's DAG-composition input-arity
4812 /// audit.
4813 ///
4814 /// # Compounding — opens the input-arity axis on the ephemeral surface
4815 ///
4816 /// The ephemeral require-tag classifier will compose this
4817 /// primitive as a fixed tag `single-input-arity` on
4818 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4819 /// surface's `single-input-arity` fixed tag on
4820 /// `POINT_FIXED_TAG_ARMS` via
4821 /// [`Classification::input_arity_is_one`] directly. The
4822 /// two-surface parity contract holds by construction: both
4823 /// surfaces route through the SAME
4824 /// [`Classification::input_arity_is_one`] primitive after the
4825 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
4826 /// peer ([`Self::input_arity_is_many`]) closes the binary XOR
4827 /// partition on this axis — mirror of the calm-axis
4828 /// (`monotone-calm ⊕ coordination-required`), data-axis
4829 /// (`public-data ⊕ data-restricted`), and optimization-direction-
4830 /// axis (`prefers-lower-direction ⊕ prefers-higher-direction`)
4831 /// closures on this surface.
4832 ///
4833 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4834 /// preserves proofs; the classification-`point_type`-derived
4835 /// input-arity-axis derived-nullary-boolean probe body composes
4836 /// ONE resolver primitive ([`Self::resolved_classification`])
4837 /// with ONE [`Classification`] primitive
4838 /// ([`Classification::input_arity_is_one`]) so every downstream
4839 /// (the future `single-input-arity` fixed tag on the ephemeral
4840 /// surface in tatara-check, future DAG-composition input-arity
4841 /// validators keying on the single-input framing, future variant
4842 /// additions on
4843 /// [`crate::classification::ConvergencePointType`]) binds through
4844 /// the SAME `input_arity_is_one()` shape rather than restating
4845 /// either the resolver walk or the two-hop closed-set projection
4846 /// composition at the callsite. THEORY.md §VI.1 — generation over
4847 /// composition; a future
4848 /// [`crate::classification::ConvergencePointType`] variant lands
4849 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
4850 /// and both surfaces pick it up mechanically.
4851 #[must_use]
4852 pub fn input_arity_is_one(&self) -> bool {
4853 self.resolved_classification().input_arity_is_one()
4854 }
4855
4856 /// ANTISYMMETRIC PEER of [`Self::input_arity_is_one`] — does
4857 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
4858 /// slot project to `Arity::Many` under
4859 /// [`crate::classification::ConvergencePointType::input_arity`]?
4860 /// Byte-for-byte peer of
4861 /// [`crate::classification::Classification::input_arity_is_many`]
4862 /// wrapped through the [`Self::resolved_classification`] resolver
4863 /// so an operator-omitted `:classification` slot on
4864 /// `(defephemeral …)` still answers via the substrate default. The
4865 /// ONE ephemeral-surface substrate primitive that owns the
4866 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4867 /// multi-input side of the DAG-composition input-arity projection.
4868 ///
4869 /// # Seventeenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the input-arity axis
4870 ///
4871 /// Peer of the sixteen prior nullary-boolean substrate primitives
4872 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4873 /// [`Self::horizon_requires_metric_axes`],
4874 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4875 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4876 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4877 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4878 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4879 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4880 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`])
4881 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4882 /// bool) shape — the SEVENTEENTH peer overall and the SECOND peer
4883 /// threading the classification-`point_type`-derived input-arity
4884 /// axis on this surface. CLOSES the SEVENTH classification axis
4885 /// into the FULL binary XOR partition contract
4886 /// `input_arity_is_one ⊕ input_arity_is_many` on the ephemeral
4887 /// surface — the resolver-hop peer of the parent-composed
4888 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`.
4889 /// The resolver-hop shape is byte-identical across all seventeen
4890 /// peers.
4891 ///
4892 /// # Semantics — resolver hop + derived-nullary-boolean
4893 ///
4894 /// `input_arity_is_many()` returns `true` iff
4895 /// `self.resolved_classification().input_arity_is_many()`. The
4896 /// resolver returns the authored [`Classification`] when present
4897 /// and the substrate default [`Classification::gate_compute`] on
4898 /// absence. Because [`Classification::gate_compute`] carries
4899 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
4900 /// ephemeral spec with no `:classification` slot answers `true` —
4901 /// every unadorned `(defephemeral …)` lands in the multi-input
4902 /// bucket under the substrate default. Direct antisymmetric
4903 /// mirror of [`Self::input_arity_is_one`] on the SAME resolver
4904 /// walk + SAME projection through the SAME closed set.
4905 ///
4906 /// # Compounding — CLOSES the input-arity axis on the ephemeral surface
4907 ///
4908 /// The ephemeral require-tag classifier will compose this
4909 /// primitive as a fixed tag `multi-input-arity` on
4910 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4911 /// surface's `multi-input-arity` fixed tag on
4912 /// `POINT_FIXED_TAG_ARMS` via
4913 /// [`Classification::input_arity_is_many`] directly. The
4914 /// two-surface parity contract holds by construction: both
4915 /// surfaces route through the SAME
4916 /// [`Classification::input_arity_is_many`] primitive after the
4917 /// ephemeral surface pays ONE resolver hop. SECOND input-arity-
4918 /// axis peer CLOSES the axis into the FULL binary XOR partition
4919 /// contract on this surface — the resolver-hop peer of the
4920 /// parent-composed
4921 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`,
4922 /// mirror of the calm-axis (`monotone-calm ⊕
4923 /// coordination-required`), data-axis (`public-data ⊕
4924 /// data-restricted`), and optimization-direction-axis
4925 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
4926 /// closures on this surface — the SEVENTH classification axis to
4927 /// reach the closed XOR partition landmark on the ephemeral
4928 /// resolver-hop surface, opening the derived-typed-projection
4929 /// stratum on this surface for the first time.
4930 ///
4931 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4932 /// preserves proofs; the classification-`point_type`-derived
4933 /// input-arity-axis derived-nullary-boolean probe body composes
4934 /// ONE resolver primitive ([`Self::resolved_classification`])
4935 /// with ONE [`Classification`] primitive
4936 /// ([`Classification::input_arity_is_many`]) so every downstream
4937 /// (the future `multi-input-arity` fixed tag on the ephemeral
4938 /// surface in tatara-check, future DAG-composition input-arity
4939 /// validators keying on the multi-input framing, future variant
4940 /// additions on
4941 /// [`crate::classification::ConvergencePointType`]) binds through
4942 /// the SAME `input_arity_is_many()` shape rather than restating
4943 /// either `!self.input_arity_is_one()` or the two-hop
4944 /// `self.resolved_classification().point_type.input_arity().is_many()`
4945 /// chain at each callsite. THEORY.md §VI.1 — generation over
4946 /// composition; a future
4947 /// [`crate::classification::ConvergencePointType`] variant lands
4948 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
4949 /// and both surfaces pick it up mechanically.
4950 #[must_use]
4951 pub fn input_arity_is_many(&self) -> bool {
4952 self.resolved_classification().input_arity_is_many()
4953 }
4954
4955 /// Derived-boolean predicate — does this ephemeral spec's resolved
4956 /// [`Classification`]'s `point_type` slot project to `Arity::One`
4957 /// under
4958 /// [`crate::classification::ConvergencePointType::output_arity`]?
4959 /// Byte-for-byte peer of
4960 /// [`crate::classification::Classification::output_arity_is_one`]
4961 /// wrapped through the [`Self::resolved_classification`] resolver
4962 /// so an operator-omitted `:classification` slot on
4963 /// `(defephemeral …)` still answers via the substrate default. The
4964 /// ONE ephemeral-surface substrate primitive that owns the
4965 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4966 /// single-output side of the DAG-composition output-arity projection.
4967 ///
4968 /// # Eighteenth derived-nullary-boolean peer on the ephemeral surface — opens the output-arity axis
4969 ///
4970 /// Peer of the seventeen prior nullary-boolean substrate primitives
4971 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4972 /// [`Self::horizon_requires_metric_axes`],
4973 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4974 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4975 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4976 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4977 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4978 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4979 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
4980 /// [`Self::input_arity_is_many`]) on the ephemeral surface's
4981 /// (resolver-hop × derived-nullary-bool) shape — the EIGHTEENTH
4982 /// peer overall and the FIRST peer threading the classification-
4983 /// `point_type`-derived OUTPUT-arity axis on this surface. Opens
4984 /// the EIGHTH classification axis into the ephemeral fixed-tag
4985 /// algebra after the horizon, calm, data, point-type, substrate,
4986 /// optimization-direction, and input-arity axes. SECOND peer on
4987 /// the derived-typed-projection stratum of the ephemeral surface
4988 /// (after [`Self::input_arity_is_one`]) — composes an extra
4989 /// closed-set-level projection hop
4990 /// ([`crate::classification::ConvergencePointType::output_arity`])
4991 /// compared to the sibling `point_is_*` triple that walks the raw
4992 /// `point_type` slot through the resolver. The resolver-hop shape
4993 /// is byte-identical across all eighteen peers.
4994 ///
4995 /// # Distinctness from the input-arity axis
4996 ///
4997 /// The input-arity and output-arity axes carve the eight-variant
4998 /// [`crate::classification::ConvergencePointType`] closed set into
4999 /// DISTINCT partitions — six of the eight variants (`Fork |
5000 /// Broadcast | Join | Gate | Select | Reduce`) DISAGREE between the
5001 /// two projections, and only the two endomorphic variants
5002 /// (`Transform | Observe` — both `(One, One)`) agree. The ephemeral
5003 /// resolver-hop surface inherits this distinctness verbatim: the
5004 /// absent-classification baseline (`gate_compute` → `point_type:
5005 /// Gate`) FLIPS between the two axes — `input_arity_is_one` is
5006 /// `false` on the baseline but `output_arity_is_one` is `true`.
5007 /// So `output_arity_is_one` is NOT a redundant restatement of
5008 /// `input_arity_is_one` even after both wrap through the SAME
5009 /// resolver.
5010 ///
5011 /// # Semantics — resolver hop + derived-nullary-boolean
5012 ///
5013 /// `output_arity_is_one()` returns `true` iff
5014 /// `self.resolved_classification().output_arity_is_one()`. The
5015 /// resolver returns the authored [`Classification`] when present
5016 /// and the substrate default [`Classification::gate_compute`] on
5017 /// absence. Because [`Classification::gate_compute`] carries
5018 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5019 /// ephemeral spec with no `:classification` slot answers `true` —
5020 /// every unadorned `(defephemeral …)` lands in the single-output
5021 /// bucket under the substrate default (`Gate` gates a many-to-one
5022 /// bucket dispatch, so the multi-output bucket only applies to
5023 /// operator-authored specs on the `Fork | Broadcast` arms). A
5024 /// regression that dropped the resolver hop, probed the wrong
5025 /// closed-set arm, or crossed the wires with the sibling
5026 /// [`crate::classification::ConvergencePointType::input_arity`]
5027 /// projection (which disagrees on six of the eight variants) fails
5028 /// HERE at ONE narrow substrate site before drifting through every
5029 /// unadorned ephemeral spec's DAG-composition output-arity audit.
5030 ///
5031 /// # Compounding — opens the output-arity axis on the ephemeral surface
5032 ///
5033 /// The ephemeral require-tag classifier will compose this
5034 /// primitive as a fixed tag `single-output-arity` on
5035 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5036 /// surface's `single-output-arity` fixed tag on
5037 /// `POINT_FIXED_TAG_ARMS` via
5038 /// [`Classification::output_arity_is_one`] directly. The
5039 /// two-surface parity contract holds by construction: both
5040 /// surfaces route through the SAME
5041 /// [`Classification::output_arity_is_one`] primitive after the
5042 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
5043 /// peer ([`Self::output_arity_is_many`]) closes the binary XOR
5044 /// partition on this axis — mirror of the input-arity-axis
5045 /// (`input_arity_is_one ⊕ input_arity_is_many`), the calm-axis
5046 /// (`monotone-calm ⊕ coordination-required`), the data-axis
5047 /// (`public-data ⊕ data-restricted`), and the optimization-
5048 /// direction-axis (`prefers-lower-direction ⊕
5049 /// prefers-higher-direction`) closures on this surface,
5050 /// completing the DAG-composition arity PAIR on the ephemeral
5051 /// derived-typed-projection stratum.
5052 ///
5053 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5054 /// preserves proofs; the classification-`point_type`-derived
5055 /// output-arity-axis derived-nullary-boolean probe body composes
5056 /// ONE resolver primitive ([`Self::resolved_classification`])
5057 /// with ONE [`Classification`] primitive
5058 /// ([`Classification::output_arity_is_one`]) so every downstream
5059 /// (the future `single-output-arity` fixed tag on the ephemeral
5060 /// surface in tatara-check, future DAG-composition output-arity
5061 /// validators keying on the single-output framing, future variant
5062 /// additions on
5063 /// [`crate::classification::ConvergencePointType`]) binds through
5064 /// the SAME `output_arity_is_one()` shape rather than restating
5065 /// either the resolver walk or the two-hop closed-set projection
5066 /// composition at the callsite. THEORY.md §VI.1 — generation over
5067 /// composition; a future
5068 /// [`crate::classification::ConvergencePointType`] variant lands
5069 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
5070 /// and both surfaces pick it up mechanically.
5071 #[must_use]
5072 pub fn output_arity_is_one(&self) -> bool {
5073 self.resolved_classification().output_arity_is_one()
5074 }
5075
5076 /// ANTISYMMETRIC PEER of [`Self::output_arity_is_one`] — does
5077 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
5078 /// slot project to `Arity::Many` under
5079 /// [`crate::classification::ConvergencePointType::output_arity`]?
5080 /// Byte-for-byte peer of
5081 /// [`crate::classification::Classification::output_arity_is_many`]
5082 /// wrapped through the [`Self::resolved_classification`] resolver
5083 /// so an operator-omitted `:classification` slot on
5084 /// `(defephemeral …)` still answers via the substrate default. The
5085 /// ONE ephemeral-surface substrate primitive that owns the
5086 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5087 /// multi-output side of the DAG-composition output-arity projection.
5088 ///
5089 /// # Nineteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the output-arity axis
5090 ///
5091 /// Peer of the eighteen prior nullary-boolean substrate primitives
5092 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5093 /// [`Self::horizon_requires_metric_axes`],
5094 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5095 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5096 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5097 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5098 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5099 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5100 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
5101 /// [`Self::input_arity_is_many`], [`Self::output_arity_is_one`])
5102 /// on the ephemeral surface's (resolver-hop × derived-nullary-
5103 /// bool) shape — the NINETEENTH peer overall and the SECOND peer
5104 /// threading the classification-`point_type`-derived OUTPUT-arity
5105 /// axis on this surface. CLOSES the EIGHTH classification axis
5106 /// into the FULL binary XOR partition contract
5107 /// `output_arity_is_one ⊕ output_arity_is_many` on the ephemeral
5108 /// surface — the resolver-hop peer of the parent-composed
5109 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`.
5110 /// The resolver-hop shape is byte-identical across all nineteen
5111 /// peers. Completes the DAG-composition arity PAIR on the
5112 /// ephemeral derived-typed-projection stratum
5113 /// (`input_arity_is_{one,many}` + `output_arity_is_{one,many}` on
5114 /// the SAME resolver walk through the SAME closed set).
5115 ///
5116 /// # Semantics — resolver hop + derived-nullary-boolean
5117 ///
5118 /// `output_arity_is_many()` returns `true` iff
5119 /// `self.resolved_classification().output_arity_is_many()`. The
5120 /// resolver returns the authored [`Classification`] when present
5121 /// and the substrate default [`Classification::gate_compute`] on
5122 /// absence. Because [`Classification::gate_compute`] carries
5123 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5124 /// ephemeral spec with no `:classification` slot answers `false` —
5125 /// every unadorned `(defephemeral …)` lands in the single-output
5126 /// bucket under the substrate default. Direct antisymmetric
5127 /// mirror of [`Self::output_arity_is_one`] on the SAME resolver
5128 /// walk + SAME projection through the SAME closed set.
5129 ///
5130 /// # Compounding — CLOSES the output-arity axis on the ephemeral surface
5131 ///
5132 /// The ephemeral require-tag classifier will compose this
5133 /// primitive as a fixed tag `multi-output-arity` on
5134 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5135 /// surface's `multi-output-arity` fixed tag on
5136 /// `POINT_FIXED_TAG_ARMS` via
5137 /// [`Classification::output_arity_is_many`] directly. The
5138 /// two-surface parity contract holds by construction: both
5139 /// surfaces route through the SAME
5140 /// [`Classification::output_arity_is_many`] primitive after the
5141 /// ephemeral surface pays ONE resolver hop. SECOND output-arity-
5142 /// axis peer CLOSES the axis into the FULL binary XOR partition
5143 /// contract on this surface — the resolver-hop peer of the
5144 /// parent-composed
5145 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`,
5146 /// mirror of the input-arity-axis (`input_arity_is_one ⊕
5147 /// input_arity_is_many`), the calm-axis (`monotone-calm ⊕
5148 /// coordination-required`), the data-axis (`public-data ⊕
5149 /// data-restricted`), and the optimization-direction-axis
5150 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
5151 /// closures on this surface — the EIGHTH classification axis to
5152 /// reach the closed XOR partition landmark on the ephemeral
5153 /// resolver-hop surface, completing the DAG-composition arity
5154 /// PAIR on the derived-typed-projection stratum of this surface.
5155 ///
5156 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5157 /// preserves proofs; the classification-`point_type`-derived
5158 /// output-arity-axis derived-nullary-boolean probe body composes
5159 /// ONE resolver primitive ([`Self::resolved_classification`])
5160 /// with ONE [`Classification`] primitive
5161 /// ([`Classification::output_arity_is_many`]) so every downstream
5162 /// (the future `multi-output-arity` fixed tag on the ephemeral
5163 /// surface in tatara-check, future DAG-composition output-arity
5164 /// validators keying on the multi-output framing, future variant
5165 /// additions on
5166 /// [`crate::classification::ConvergencePointType`]) binds through
5167 /// the SAME `output_arity_is_many()` shape rather than restating
5168 /// either `!self.output_arity_is_one()` or the two-hop
5169 /// `self.resolved_classification().point_type.output_arity().is_many()`
5170 /// chain at each callsite. THEORY.md §VI.1 — generation over
5171 /// composition; a future
5172 /// [`crate::classification::ConvergencePointType`] variant lands
5173 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
5174 /// and both surfaces pick it up mechanically.
5175 #[must_use]
5176 pub fn output_arity_is_many(&self) -> bool {
5177 self.resolved_classification().output_arity_is_many()
5178 }
5179
5180 /// True iff this ephemeral spec's [`Self::routing`] slot is
5181 /// populated AND the inner [`RoutingSpec`]'s derived
5182 /// [`RoutingForm`] equals `kind` — the substrate primitive that
5183 /// owns the (`&EphemeralSpec`, [`RoutingForm`]) → `bool` presence-
5184 /// probe shape on the sugar-surface type.
5185 ///
5186 /// # Peer to [`crate::routing::RoutingSpec::has_form`]
5187 ///
5188 /// [`RoutingSpec::has_form`] carries the same `(&self, RoutingForm)
5189 /// -> bool` signature on the inner routing carrier reached through
5190 /// the Option gate; this peer composes byte-identical semantics on
5191 /// [`EphemeralSpec`]'s direct `routing: Option<RoutingSpec>` slot,
5192 /// so both surfaces' `routing-form-<kind>` require-tag families
5193 /// route through the SAME `RoutingSpec::has_form` primitive. A
5194 /// future normalization at the probe shape (a widened return
5195 /// carrying the derived [`RoutingForm`] variant, a debug-build
5196 /// assertion on operator-set vs defaulted overrides on the
5197 /// `stable_name_claim` bool, a fleet-wide warn on `Stable`
5198 /// combined with content-hashed hostnames) lands at ONE site per
5199 /// surface and every downstream `routing-form-<kind>` require-tag
5200 /// family + closed-set audit dispatcher picks it up mechanically.
5201 ///
5202 /// # Semantics — Option-gated derived-scalar match
5203 ///
5204 /// [`EphemeralSpec::routing`] is an `Option<RoutingSpec>`: `None`
5205 /// on an in-cluster-only ephemeral env (no per-instance edges
5206 /// declared), `Some(_)` when the operator authored the
5207 /// `:routing (…)` slot. `has_routing_form(kind)` returns `true`
5208 /// iff the slot is `Some(spec)` AND `spec.has_form(kind)` — the
5209 /// Option-parent gate short-circuits `false` on `None` regardless
5210 /// of `kind`, and the reachable arm reads the DERIVED
5211 /// [`RoutingForm`] through the ONE substrate composer
5212 /// [`RoutingForm::from_is_stable`] over the child
5213 /// `stable_name_claim` bool (a `false` default projects to
5214 /// [`RoutingForm::Instance`], a `true` operator override projects
5215 /// to [`RoutingForm::Stable`]).
5216 ///
5217 /// # Corner — (Option-parent × derived-scalar-child)
5218 ///
5219 /// SAME corner as the point surface's `routing-form-<kind>`
5220 /// family (via [`crate::routing::RoutingSpec::has_form`] reached
5221 /// through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`)
5222 /// — both surfaces' Option-parent hop threads through the SAME
5223 /// `Option<RoutingSpec>` field name on their respective sugar
5224 /// structs. The [`From<EphemeralSpec>`] lowering copies
5225 /// `e.routing → ProcessSpec::routing` byte-for-byte at the
5226 /// [`From`] impl in this module (see the `routing: e.routing`
5227 /// line), so the SAME `Option<RoutingSpec>` reaches both
5228 /// surfaces' `routing-form-<kind>` families through the SAME
5229 /// [`RoutingSpec::has_form`] walk. Distinct from
5230 /// [`Self::has_teardown_policy`] on this same surface, which
5231 /// walks a required-scalar-child through no Option-parent hop.
5232 ///
5233 /// # Compounding
5234 ///
5235 /// The ephemeral require-tag classifier composes this primitive
5236 /// with the closed-set `FromStr` autoderived on [`RoutingForm`]
5237 /// through the `strip_and_classify_prefixed_kind` substrate to
5238 /// publish a `routing-form-<kind>` prefix family byte-for-byte
5239 /// symmetrical with the point surface's family via
5240 /// [`crate::routing::RoutingSpec::has_form`]. A future third
5241 /// [`RoutingForm`] variant added to `ALL` (a hypothetical
5242 /// `Anchored` for "hold the claim only for a specific
5243 /// generation") reaches BOTH surfaces' `routing-form-<kind>`
5244 /// prefix families through the SAME closed-set walk with no
5245 /// per-caller edit — the two-surface symmetry means adding a
5246 /// variant on the closed set publishes it in lockstep across
5247 /// every downstream consumer.
5248 ///
5249 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
5250 /// preserves proofs — the Option-gated derived-scalar-carrier
5251 /// presence-probe body lives at ONE substrate site per surface
5252 /// so every downstream (`routing-form-<kind>` require-tag families
5253 /// on both surfaces in tatara-check, closed-set audit dispatchers,
5254 /// future variant additions on [`RoutingForm`]) binds through the
5255 /// SAME `has(kind)` shape rather than restating the
5256 /// `spec.routing.as_ref().is_some_and(|r| r.has_form(kind))`
5257 /// closure body at each call site). THEORY.md §VI.1 (generation
5258 /// over composition — a future variant lands at ONE `ALL` entry +
5259 /// one `as_str` arm on the closed set and the probe picks it up
5260 /// mechanically without further per-consumer edits).
5261 #[must_use]
5262 pub fn has_routing_form(&self, kind: RoutingForm) -> bool {
5263 self.routing.as_ref().is_some_and(|r| r.has_form(kind))
5264 }
5265
5266 /// True iff at least one declared export in `self.exports` would
5267 /// fire on the given terminal-reached [`ProcessPhase`] — the peer
5268 /// of [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5269 /// on the [`EphemeralSpec`] surface.
5270 ///
5271 /// # Semantics — byte-identical to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5272 ///
5273 /// Both surfaces walk the SAME slice-level substrate primitive
5274 /// [`ExportSpecSliceExt::has_applicable_at`] on their respective
5275 /// `Vec<ExportSpec>` slot: [`EphemeralSpec`]'s `exports` field is
5276 /// copied byte-for-byte into `EphemeralLifetime::exports` at the
5277 /// `From<EphemeralSpec>` lowering, so a `has_applicable_exports_at`
5278 /// query on the authored ephemeral spec answers identically to a
5279 /// `has_applicable_exports` query on the lowered `EphemeralLifetime`.
5280 /// A regression at the compound `(when, phase) → fires_on(phase)`
5281 /// walk fails at [`ExportSpecSliceExt::has_applicable_at`]'s tests
5282 /// rather than as silent drift at either surface's inherent method.
5283 ///
5284 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5285 ///
5286 /// Same shape, same axis, same body — the point-domain surface
5287 /// composes through `spec.lifetime.resolved_ephemeral().is_some_and(
5288 /// |e| e.exports.has_applicable_at(phase))`; the ephemeral sugar
5289 /// surface reads `self.exports.has_applicable_at(phase)` directly
5290 /// because `EphemeralSpec` stores `exports: Vec<ExportSpec>` as a
5291 /// top-level field. Both routes bind through THIS ONE slice-level
5292 /// primitive so a future normalization (widening the trigger from
5293 /// a stored discriminator to a computed predicate, adding a phase
5294 /// that composes across multiple trigger arms, threading a
5295 /// per-export justification back for editor tooltips) lands at ONE
5296 /// site and every downstream inherits the shift by construction.
5297 ///
5298 /// # Compounding
5299 ///
5300 /// The ephemeral require-tag classifier composes this primitive
5301 /// with the closed-set [`ProcessPhase`]'s autoderived `FromStr`
5302 /// through the `strip_and_classify_prefixed_kind` substrate to
5303 /// publish an `exports-fire-on-<phase>` closed-set prefix family
5304 /// byte-for-byte symmetrical with the point surface's family via
5305 /// `spec.lifetime.resolved_ephemeral().is_some_and(|e|
5306 /// e.exports.has_applicable_at(phase))`. A future twelfth
5307 /// [`ProcessPhase`] variant reaches BOTH surfaces' prefix families
5308 /// through the ONE [`crate::export::ExportTrigger::fires_on`]
5309 /// exhaustive match — either the new phase inherits a per-trigger
5310 /// fire rule at that single substrate site or it collapses to
5311 /// `false` for every trigger (the current non-terminal tail),
5312 /// without a per-caller edit anywhere else.
5313 ///
5314 /// A future normalization at the compound `(when, phase) →
5315 /// fires_on(phase)` walk (a widening that returns the applicable
5316 /// exports themselves rather than a bool, a debug-build assertion
5317 /// on redundant `Always`-triggered exports coexisting with an
5318 /// `OnAttested` peer, a fleet-wide warn on empty-export ephemerals
5319 /// declaring `OnAttested` postconditions) lands at the ONE
5320 /// slice-level substrate primitive [`ExportSpecSliceExt::has_applicable_at`]
5321 /// both this method and [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
5322 /// compose against — so the two struct-level union methods stay
5323 /// symmetric by construction.
5324 ///
5325 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
5326 /// proofs — the walk composes the SAME slice-level substrate
5327 /// primitive on both this ephemeral surface and the
5328 /// [`crate::lifetime::EphemeralLifetime`] surface, so a regression
5329 /// at the compound `(when, phase) → fires_on(phase)` chain fails
5330 /// at ONE site rather than as silent drift between the two peers).
5331 /// THEORY.md §VI.1 (generation over composition — a future
5332 /// [`ProcessPhase`] variant or a future [`crate::export::ExportTrigger`]
5333 /// variant reaches both `exports-fire-on-<phase>` require-tag
5334 /// surfaces mechanically through the SAME closed-set walk).
5335 #[must_use]
5336 pub fn has_applicable_exports_at(&self, phase: ProcessPhase) -> bool {
5337 self.exports.has_applicable_at(phase)
5338 }
5339}
5340
5341impl From<EphemeralSpec> for ProcessSpec {
5342 fn from(e: EphemeralSpec) -> Self {
5343 let classification = e.classification.unwrap_or_else(default_ephemeral_class);
5344 let mut spec = Self {
5345 identity: crate::spec::IdentitySpec {
5346 parent: e.parent,
5347 name_override: None,
5348 },
5349 classification,
5350 intent: Intent {
5351 aplicacao: Some(e.aplicacao),
5352 ..Intent::default()
5353 },
5354 boundary: Boundary {
5355 preconditions: e.preconditions,
5356 postconditions: e.postconditions,
5357 timeout: e.verify_timeout,
5358 },
5359 compliance: Default::default(),
5360 depends_on: vec![],
5361 signals: Default::default(),
5362 // Routes through the ONE substrate composer
5363 // [`Lifetime::ephemeral`] — pre-lift this was one of
5364 // ELEVEN+ hand-authored `Lifetime { ephemeral: Some(<e>),
5365 // .. }` sites past the ★★ PRIME-DIRECTIVE ≥ 2 threshold.
5366 // See the composer's doc-comment for the full migration
5367 // rationale.
5368 lifetime: Lifetime::ephemeral(EphemeralLifetime {
5369 ttl: e.ttl,
5370 teardown_policy: e.teardown,
5371 max_concurrent: e.max_concurrent,
5372 exports: e.exports,
5373 }),
5374 // R5 — propagate routing template (None = no edges).
5375 routing: e.routing,
5376 // EncapsulatesSpec isn't exposed via EphemeralSpec sugar;
5377 // operators wanting Adopt/Observe author the full
5378 // (defpoint …) form. Sugar path stays greenfield-Manage.
5379 encapsulates: None,
5380 suspended: false,
5381 };
5382 // Belt-and-suspenders: make sure exactly-one Intent invariant holds.
5383 spec.intent.nix = None;
5384 spec.intent.flux = None;
5385 spec.intent.lisp = None;
5386 spec.intent.container = None;
5387 spec.intent.guest = None;
5388 spec
5389 }
5390}
5391
5392fn default_ephemeral_class() -> Classification {
5393 // Delegates through the substrate `(Gate, Compute)` baseline owner
5394 // so the shape lives at ONE workspace-wide site — see
5395 // [`Classification::gate_compute`] for the pre-lift ten-callsite
5396 // duplication history and the sibling-default correspondence
5397 // pinned there.
5398 Classification::gate_compute()
5399}
5400
5401/// Compile a `(defephemeral …)` Lisp source into named `EphemeralSpec` values.
5402pub fn compile_ephemeral_source(
5403 src: &str,
5404) -> tatara_lisp::Result<Vec<tatara_lisp::NamedDefinition<EphemeralSpec>>> {
5405 tatara_lisp::compile_named::<EphemeralSpec>(src)
5406}
5407
5408#[cfg(test)]
5409mod tests {
5410 use super::*;
5411 use crate::boundary::{assert_slice_refinement_composition_laws, ConditionKind};
5412 use crate::classification::{
5413 Arity, CalmClassification, ConvergencePointType, DataClassification, Horizon, HorizonKind,
5414 OptimizationDirection, SubstrateType,
5415 };
5416 use crate::intent::IntentVariant;
5417 use crate::lifetime::LifetimeVariant;
5418
5419 /// LANDMARK PIN — the (ephemeral-surface test-fixture ×
5420 /// [`Classification::gate_compute_with_axis`] on horizon-nested
5421 /// axes) sweep equivalence. Nine ephemeral-surface probe-sweep
5422 /// tests in this module (`has_horizon_kind_*`,
5423 /// `has_optimization_direction_*`, `horizon_terminates_*`,
5424 /// `horizon_requires_metric_axes_*`, `horizon_terminates_xor_*`)
5425 /// pre-sweep restated the SAME `let mut c =
5426 /// Classification::gate_compute(); c.horizon = Horizon { <slot>:
5427 /// populated, ..Horizon::default() }` five-line fixture at each
5428 /// callsite, mutating exactly ONE horizon-nested slot to
5429 /// `populated`; post-sweep each callsite reads
5430 /// [`Classification::gate_compute_with_axis(populated)`] — one
5431 /// line — and the four-baseline-slot restatement lives at ONE
5432 /// substrate primitive. This pin asserts byte-parity between the
5433 /// pre-sweep hand-authored `Horizon` struct-literal shape (both
5434 /// the [`HorizonKind::kind`] mutation shape AND the
5435 /// [`OptimizationDirection`]-into-`Some(_)` mutation shape) and
5436 /// the post-sweep composer output on every variant of each closed
5437 /// set, so a regression that either (a) changed
5438 /// [`ClassificationAxis for HorizonKind`] to stomp a non-`kind`
5439 /// sub-slot, (b) changed [`ClassificationAxis for OptimizationDirection`]
5440 /// to drop the `Some(...)` wrap, or (c) reintroduced a whole-
5441 /// `Horizon`-reset shape that dropped a sibling sub-slot would
5442 /// fail HERE at ONE landmark site before landing at the peer
5443 /// probe-sweep pins that use the composer.
5444 ///
5445 /// Byte-for-byte peer of the sibling landmark
5446 /// `with_axis_optimization_direction_overlay_wraps_variant_in_some`
5447 /// on the point-surface classification-module tests — this pin
5448 /// carries the same substrate contract through to the ephemeral-
5449 /// surface tests that consume the composer.
5450 #[test]
5451 fn gate_compute_with_axis_on_horizon_nested_axes_matches_hand_authored_shape() {
5452 for kind in HorizonKind::ALL {
5453 let via_composer = Classification::gate_compute_with_axis(kind);
5454 let mut via_hand_authored = Classification::gate_compute();
5455 via_hand_authored.horizon = Horizon {
5456 kind,
5457 ..Horizon::default()
5458 };
5459 assert_eq!(
5460 via_composer, via_hand_authored,
5461 "HorizonKind::{kind:?}: composer vs pre-sweep hand-authored struct-literal drift",
5462 );
5463 }
5464 for direction in OptimizationDirection::ALL {
5465 let via_composer = Classification::gate_compute_with_axis(direction);
5466 let mut via_hand_authored = Classification::gate_compute();
5467 via_hand_authored.horizon = Horizon {
5468 direction: Some(direction),
5469 ..Horizon::default()
5470 };
5471 assert_eq!(
5472 via_composer, via_hand_authored,
5473 "OptimizationDirection::{direction:?}: composer vs pre-sweep hand-authored struct-literal drift",
5474 );
5475 }
5476 }
5477
5478 /// Primitive-owner pin — `EphemeralSpec::with_classification_axis`
5479 /// on a `classification: None` carrier produces an ephemeral spec
5480 /// whose `classification` slot is
5481 /// `Some(Classification::gate_compute_with_axis(axis))` byte-for-
5482 /// byte on every axis-variant, and preserves every non-
5483 /// classification slot at its pre-call value. A regression that
5484 /// (a) failed to wrap the composed [`Classification`] in `Some(_)`
5485 /// on the `None`-arm, (b) mutated a sibling slot on `EphemeralSpec`
5486 /// through the axis overlay, or (c) picked a different `None`-arm
5487 /// fill-through than the sibling
5488 /// [`Self::resolved_classification`] resolver would fail HERE.
5489 #[test]
5490 fn with_classification_axis_on_none_arm_fills_through_gate_compute() {
5491 fn baseline() -> EphemeralSpec {
5492 EphemeralSpec {
5493 aplicacao: demo_overlay(),
5494 ttl: "2h".into(),
5495 teardown: TeardownPolicy::OnAttested,
5496 max_concurrent: 3,
5497 postconditions: vec![],
5498 preconditions: vec![],
5499 verify_timeout: Some("30m".into()),
5500 classification: None,
5501 parent: Some("seph.1".into()),
5502 exports: vec![],
5503 routing: None,
5504 }
5505 }
5506 // Direct-scalar axes: composer output matches
5507 // `Classification::gate_compute_with_axis(axis)` byte-for-byte,
5508 // wrapped in `Some(_)`.
5509 for kind in ConvergencePointType::ALL {
5510 let via_composer = baseline().with_classification_axis(kind);
5511 assert_eq!(
5512 via_composer.classification,
5513 Some(Classification::gate_compute_with_axis(kind)),
5514 "ConvergencePointType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5515 );
5516 }
5517 for kind in SubstrateType::ALL {
5518 let via_composer = baseline().with_classification_axis(kind);
5519 assert_eq!(
5520 via_composer.classification,
5521 Some(Classification::gate_compute_with_axis(kind)),
5522 "SubstrateType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5523 );
5524 }
5525 for kind in CalmClassification::ALL {
5526 let via_composer = baseline().with_classification_axis(kind);
5527 assert_eq!(
5528 via_composer.classification,
5529 Some(Classification::gate_compute_with_axis(kind)),
5530 "CalmClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5531 );
5532 }
5533 for kind in DataClassification::ALL {
5534 let via_composer = baseline().with_classification_axis(kind);
5535 assert_eq!(
5536 via_composer.classification,
5537 Some(Classification::gate_compute_with_axis(kind)),
5538 "DataClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5539 );
5540 }
5541 // Horizon-nested axes: same shape through the trait's
5542 // sub-slot overlay.
5543 for kind in HorizonKind::ALL {
5544 let via_composer = baseline().with_classification_axis(kind);
5545 assert_eq!(
5546 via_composer.classification,
5547 Some(Classification::gate_compute_with_axis(kind)),
5548 "HorizonKind::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5549 );
5550 }
5551 for direction in OptimizationDirection::ALL {
5552 let via_composer = baseline().with_classification_axis(direction);
5553 assert_eq!(
5554 via_composer.classification,
5555 Some(Classification::gate_compute_with_axis(direction)),
5556 "OptimizationDirection::{direction:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5557 );
5558 }
5559 // Non-classification slots: every one preserved byte-for-byte
5560 // across the overlay on every axis. Compare through JSON
5561 // round-trip since `AplicacaoIntent` / `ExportSpec` /
5562 // `RoutingSpec` do not carry `PartialEq`.
5563 for kind in ConvergencePointType::ALL {
5564 let via_composer = baseline().with_classification_axis(kind);
5565 let baseline_ref = baseline();
5566 assert_eq!(
5567 serde_json::to_string(&via_composer.aplicacao).unwrap(),
5568 serde_json::to_string(&baseline_ref.aplicacao).unwrap(),
5569 "aplicacao slot drifted under axis overlay for kind={kind:?}",
5570 );
5571 assert_eq!(via_composer.ttl, baseline_ref.ttl);
5572 assert_eq!(via_composer.teardown, baseline_ref.teardown);
5573 assert_eq!(via_composer.max_concurrent, baseline_ref.max_concurrent);
5574 assert_eq!(
5575 via_composer.postconditions.len(),
5576 baseline_ref.postconditions.len()
5577 );
5578 assert_eq!(
5579 via_composer.preconditions.len(),
5580 baseline_ref.preconditions.len()
5581 );
5582 assert_eq!(via_composer.verify_timeout, baseline_ref.verify_timeout);
5583 assert_eq!(via_composer.parent, baseline_ref.parent);
5584 assert_eq!(via_composer.exports.len(), baseline_ref.exports.len());
5585 assert!(via_composer.routing.is_none());
5586 }
5587 }
5588
5589 /// Primitive-owner pin —
5590 /// `EphemeralSpec::with_classification_axis` on a
5591 /// `classification: Some(prior)` carrier composes the axis
5592 /// overlay onto `prior` via [`ClassificationAxis::overlay`],
5593 /// preserving every OTHER axis slot on `prior`. Distinct from the
5594 /// `None`-arm pin above: the `Some(prior)` arm does NOT reset
5595 /// through [`Classification::gate_compute`], and consecutive
5596 /// `.with_classification_axis(...)` calls compose arbitrary
5597 /// N-axis conjunctions on the ephemeral surface with the same
5598 /// order-independence guarantee [`Classification::with_axis`]
5599 /// carries on distinct-slot axes.
5600 #[test]
5601 fn with_classification_axis_on_some_arm_chains_onto_prior() {
5602 fn baseline() -> EphemeralSpec {
5603 EphemeralSpec {
5604 aplicacao: demo_overlay(),
5605 ttl: "1h".into(),
5606 teardown: TeardownPolicy::Always,
5607 max_concurrent: 0,
5608 postconditions: vec![],
5609 preconditions: vec![],
5610 verify_timeout: None,
5611 classification: None,
5612 parent: None,
5613 exports: vec![],
5614 routing: None,
5615 }
5616 }
5617 // Prior authored point_type = Fork; overlay substrate = Storage
5618 // preserves the Fork point_type on the composed classification.
5619 let seeded = baseline().with_classification_axis(ConvergencePointType::Fork);
5620 let composed = seeded.with_classification_axis(SubstrateType::Storage);
5621 let classification = composed
5622 .classification
5623 .as_ref()
5624 .expect("with_classification_axis populates Some(_)");
5625 assert_eq!(classification.point_type, ConvergencePointType::Fork);
5626 assert_eq!(classification.substrate, SubstrateType::Storage);
5627 // Order independence on distinct-slot axes: swapping the axis
5628 // chain reads the SAME final classification.
5629 let forward = baseline()
5630 .with_classification_axis(ConvergencePointType::Fork)
5631 .with_classification_axis(SubstrateType::Storage)
5632 .with_classification_axis(CalmClassification::NonMonotone)
5633 .with_classification_axis(DataClassification::Pii)
5634 .classification
5635 .unwrap();
5636 let reverse = baseline()
5637 .with_classification_axis(DataClassification::Pii)
5638 .with_classification_axis(CalmClassification::NonMonotone)
5639 .with_classification_axis(SubstrateType::Storage)
5640 .with_classification_axis(ConvergencePointType::Fork)
5641 .classification
5642 .unwrap();
5643 assert_eq!(
5644 forward, reverse,
5645 "with_classification_axis chain must be order-independent on distinct-slot axes",
5646 );
5647 // Nested horizon-sub-slot overlays compose onto the same
5648 // carrier without stomping each other: the (kind, direction)
5649 // pair rides both chains.
5650 let paired = baseline()
5651 .with_classification_axis(HorizonKind::Asymptotic)
5652 .with_classification_axis(OptimizationDirection::Maximize)
5653 .classification
5654 .unwrap();
5655 assert_eq!(paired.horizon.kind, HorizonKind::Asymptotic);
5656 assert_eq!(
5657 paired.horizon.direction,
5658 Some(OptimizationDirection::Maximize)
5659 );
5660 }
5661
5662 /// Primitive-owner pin —
5663 /// `EphemeralSpec::with_classification_axis` composes byte-for-
5664 /// byte with the pre-sweep hand-authored two-shape callsite
5665 /// pattern that recurred at ~36 sites in
5666 /// `tatara-reconciler::bin::tatara-check`: either
5667 /// `let mut c = Classification::gate_compute(); c.<axis> =
5668 /// populated; EphemeralSpec { classification: Some(c), ..
5669 /// baseline }`, or the newer `let c =
5670 /// Classification::gate_compute_with_axis(populated); EphemeralSpec
5671 /// { classification: Some(c), ..baseline }`. Both restated
5672 /// pre-sweep shapes classify identically to
5673 /// `baseline.with_classification_axis(populated)` on every
5674 /// [`ClassificationAxis`] impl. A regression that drifted the
5675 /// composer body away from the pre-sweep shape (a stray reset of a
5676 /// non-classification slot, a stomping of a nested horizon sub-
5677 /// slot on the direct-scalar axes) fails HERE at ONE landmark site
5678 /// before drifting through the ~36 swept callsites in tatara-
5679 /// check.rs.
5680 #[test]
5681 fn with_classification_axis_matches_pre_sweep_hand_authored_shape() {
5682 fn baseline() -> EphemeralSpec {
5683 EphemeralSpec {
5684 aplicacao: demo_overlay(),
5685 ttl: "1h".into(),
5686 teardown: TeardownPolicy::Always,
5687 max_concurrent: 0,
5688 postconditions: vec![],
5689 preconditions: vec![],
5690 verify_timeout: None,
5691 classification: None,
5692 parent: None,
5693 exports: vec![],
5694 routing: None,
5695 }
5696 }
5697 // Direct-scalar axes: `<eph>.with_classification_axis(kind)`
5698 // matches the pre-sweep two-shape callsite pattern on every
5699 // ConvergencePointType variant.
5700 for kind in ConvergencePointType::ALL {
5701 let via_composer = baseline().with_classification_axis(kind);
5702 let mut hand_classification = Classification::gate_compute();
5703 hand_classification.point_type = kind;
5704 let via_hand = EphemeralSpec {
5705 classification: Some(hand_classification),
5706 ..baseline()
5707 };
5708 assert_eq!(
5709 via_composer.classification, via_hand.classification,
5710 "ConvergencePointType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5711 );
5712 }
5713 for kind in SubstrateType::ALL {
5714 let via_composer = baseline().with_classification_axis(kind);
5715 let mut hand_classification = Classification::gate_compute();
5716 hand_classification.substrate = kind;
5717 let via_hand = EphemeralSpec {
5718 classification: Some(hand_classification),
5719 ..baseline()
5720 };
5721 assert_eq!(
5722 via_composer.classification, via_hand.classification,
5723 "SubstrateType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5724 );
5725 }
5726 for kind in CalmClassification::ALL {
5727 let via_composer = baseline().with_classification_axis(kind);
5728 let mut hand_classification = Classification::gate_compute();
5729 hand_classification.calm = kind;
5730 let via_hand = EphemeralSpec {
5731 classification: Some(hand_classification),
5732 ..baseline()
5733 };
5734 assert_eq!(
5735 via_composer.classification, via_hand.classification,
5736 "CalmClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5737 );
5738 }
5739 for kind in DataClassification::ALL {
5740 let via_composer = baseline().with_classification_axis(kind);
5741 let mut hand_classification = Classification::gate_compute();
5742 hand_classification.data_classification = kind;
5743 let via_hand = EphemeralSpec {
5744 classification: Some(hand_classification),
5745 ..baseline()
5746 };
5747 assert_eq!(
5748 via_composer.classification, via_hand.classification,
5749 "DataClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5750 );
5751 }
5752 // Horizon-nested axes: composer matches the newer
5753 // `gate_compute_with_axis` shape used on the horizon-nested
5754 // sweep sites in tatara-check.rs.
5755 for kind in HorizonKind::ALL {
5756 let via_composer = baseline().with_classification_axis(kind);
5757 let via_hand = EphemeralSpec {
5758 classification: Some(Classification::gate_compute_with_axis(kind)),
5759 ..baseline()
5760 };
5761 assert_eq!(
5762 via_composer.classification, via_hand.classification,
5763 "HorizonKind::{kind:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
5764 );
5765 }
5766 for direction in OptimizationDirection::ALL {
5767 let via_composer = baseline().with_classification_axis(direction);
5768 let via_hand = EphemeralSpec {
5769 classification: Some(Classification::gate_compute_with_axis(direction)),
5770 ..baseline()
5771 };
5772 assert_eq!(
5773 via_composer.classification, via_hand.classification,
5774 "OptimizationDirection::{direction:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
5775 );
5776 }
5777 }
5778
5779 fn demo_overlay() -> AplicacaoIntent {
5780 AplicacaoIntent {
5781 chart_ref: "oci://ghcr.io/pleme-io/charts/lareira-demo-app".into(),
5782 version: "0.5.5".into(),
5783 profile: "all-in-one".into(),
5784 values_overlay: serde_json::json!({
5785 "cluster": { "name": "ephemeral-test-01", "namespace": "demo-test" },
5786 "data": { "mysql": { "persistence": { "enabled": false } } },
5787 "compliance": { "overlays": [] }
5788 }),
5789 release_name: Some("demo-app-consolidated".into()),
5790 target_namespace: Some("demo-test".into()),
5791 install_timeout: Some("25m".into()),
5792 }
5793 }
5794
5795 #[test]
5796 fn defaults_resolve_for_ephemeral_spec() {
5797 let e = EphemeralSpec {
5798 aplicacao: demo_overlay(),
5799 ttl: crate::lifetime::default_ephemeral_ttl(),
5800 teardown: TeardownPolicy::default(),
5801 max_concurrent: crate::lifetime::default_ephemeral_max_concurrent(),
5802 postconditions: vec![],
5803 preconditions: vec![],
5804 verify_timeout: None,
5805 classification: None,
5806 parent: None,
5807 exports: vec![],
5808 routing: None,
5809 };
5810 let ps: ProcessSpec = e.into();
5811 // Intent must resolve to Aplicacao.
5812 match ps.intent.variant().unwrap() {
5813 IntentVariant::Aplicacao(a) => {
5814 assert_eq!(a.profile, "all-in-one");
5815 assert_eq!(a.install_timeout.as_deref(), Some("25m"));
5816 }
5817 other => panic!("expected Aplicacao, got {other:?}"),
5818 }
5819 // Lifetime must resolve to Ephemeral with defaults.
5820 match ps.lifetime.variant().unwrap() {
5821 LifetimeVariant::Ephemeral(e) => {
5822 assert_eq!(e.ttl, "1h");
5823 assert_eq!(e.teardown_policy, TeardownPolicy::Always);
5824 }
5825 other => panic!("expected ephemeral, got {other:?}"),
5826 }
5827 // Default classification gates the Process at Compute/Internal.
5828 assert_eq!(ps.classification.point_type, ConvergencePointType::Gate);
5829 assert_eq!(ps.classification.substrate, SubstrateType::Compute);
5830 }
5831
5832 #[test]
5833 fn ephemeral_lisp_round_trip() {
5834 let src = r#"
5835 (defephemeral closed-loop-attest
5836 :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
5837 :version "0.5.5"
5838 :profile "all-in-one"
5839 :values-overlay (:cluster (:name "ephemeral-test-01")
5840 :data (:mysql (:persistence (:enabled #f)))
5841 :compliance (:overlays []))
5842 :release-name "demo-app-consolidated"
5843 :target-namespace "demo-test"
5844 :install-timeout "25m")
5845 :ttl "1h"
5846 :teardown OnAttested
5847 :max-concurrent 1
5848 :postconditions
5849 ((:kind HelmReleaseReleased
5850 :params (:name "demo-app-consolidated"
5851 :namespace "demo-test"))
5852 (:kind ClosedLoopAuth
5853 :params (:issuer (:service "demo-app-issuer" :port 8080)
5854 :consumer (:service "demo-app-gateway" :port 8000)
5855 :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
5856 "#;
5857 let defs = compile_ephemeral_source(src).expect("compile");
5858 assert_eq!(defs.len(), 1);
5859 let d = &defs[0];
5860 assert_eq!(d.name, "closed-loop-attest");
5861
5862 // Aplicacao body landed correctly.
5863 assert_eq!(
5864 d.spec.aplicacao.chart_ref,
5865 "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
5866 );
5867 assert_eq!(d.spec.aplicacao.profile, "all-in-one");
5868 assert_eq!(
5869 d.spec.aplicacao.target_namespace.as_deref(),
5870 Some("demo-test")
5871 );
5872 // values-overlay JSON is preserved.
5873 assert_eq!(
5874 d.spec.aplicacao.values_overlay["cluster"]["name"],
5875 "ephemeral-test-01"
5876 );
5877 // Boolean #f is preserved as a typed JSON bool (not the string "false").
5878 // tatara-lisp uses Scheme syntax for bools — `#t` / `#f`.
5879 assert_eq!(
5880 d.spec.aplicacao.values_overlay["data"]["mysql"]["persistence"]["enabled"],
5881 false
5882 );
5883
5884 // Lifetime knobs.
5885 assert_eq!(d.spec.ttl, "1h");
5886 assert_eq!(d.spec.teardown, TeardownPolicy::OnAttested);
5887 assert_eq!(d.spec.max_concurrent, 1);
5888
5889 // Two postconditions, both typed.
5890 assert_eq!(d.spec.postconditions.len(), 2);
5891 assert_eq!(
5892 d.spec.postconditions[0].kind,
5893 ConditionKind::HelmReleaseReleased
5894 );
5895 assert_eq!(d.spec.postconditions[1].kind, ConditionKind::ClosedLoopAuth);
5896
5897 // Lowers to ProcessSpec with the right shape.
5898 let ps: ProcessSpec = d.spec.clone().into();
5899 assert!(matches!(
5900 ps.intent.variant().unwrap(),
5901 IntentVariant::Aplicacao(_)
5902 ));
5903 assert!(matches!(
5904 ps.lifetime.variant().unwrap(),
5905 LifetimeVariant::Ephemeral(_)
5906 ));
5907 assert_eq!(ps.boundary.postconditions.len(), 2);
5908 }
5909
5910 /// End-to-end: the `:exports` slot on `(defephemeral …)` compiles
5911 /// into typed `ExportSpec` values via the Universal-Deserialize
5912 /// fallthrough — no per-domain keyword handlers needed.
5913 ///
5914 /// Receipts (empty-body source) is exercised via the Rust serde
5915 /// path only (see `export::tests::export_spec_serde_round_trip`).
5916 /// tatara-lisp's empty-kw-form `(:)` currently parses as a single-
5917 /// element array rather than a JSON `{}`; the same limitation
5918 /// affects `(:permanent)` on Lifetime. Tracked: extend the reader
5919 /// to accept `(:foo (:))` ⇒ `{"foo": {}}` as a typed-empty form,
5920 /// then re-enable Receipts here.
5921 #[test]
5922 fn exports_lisp_round_trip() {
5923 use crate::export::{ArtifactVariant, ChannelVariant, ExportTrigger, ReportFormat};
5924 let src = r#"
5925 (defephemeral closed-loop-attest
5926 :aplicacao (:chart-ref "oci://x"
5927 :version "1.0.0"
5928 :profile "minimal"
5929 :values-overlay ())
5930 :ttl "30m"
5931 :teardown OnAttested
5932 :exports
5933 ((:source (:test-report (:configmap "junit-results"
5934 :key "junit.xml"
5935 :format Junit))
5936 :channel (:nats-subject (:subject "pleme.pleme-dev.ephemeral.r1.test-report"
5937 :stream "EPHEMERAL_TEST_REPORTS"))
5938 :when OnAttested)
5939 (:source (:test-report (:configmap "junit-results"
5940 :key "junit.xml"
5941 :format Junit))
5942 :channel (:http-event (:signal-type "test-report"))
5943 :when Always)
5944 (:source (:run-marker (:labels (:run-id "r1" :phase "end")))
5945 :channel (:http-event (:signal-type "ephemeral-marker"))
5946 :when Always)))
5947 "#;
5948 let defs = compile_ephemeral_source(src).expect("compile");
5949 assert_eq!(defs.len(), 1);
5950 let d = &defs[0];
5951 assert_eq!(d.spec.exports.len(), 3);
5952
5953 // First export — TestReport → NATS subject + OnAttested
5954 let r = &d.spec.exports[0];
5955 match r.source.variant().unwrap() {
5956 ArtifactVariant::TestReport(tr) => {
5957 assert_eq!(tr.configmap, "junit-results");
5958 assert_eq!(tr.format, ReportFormat::Junit);
5959 }
5960 other => panic!("expected TestReport, got {other:?}"),
5961 }
5962 match r.channel.variant().unwrap() {
5963 ChannelVariant::NatsSubject(n) => {
5964 assert_eq!(n.subject, "pleme.pleme-dev.ephemeral.r1.test-report");
5965 assert_eq!(n.stream, "EPHEMERAL_TEST_REPORTS");
5966 }
5967 other => panic!("expected NatsSubject, got {other:?}"),
5968 }
5969 assert_eq!(r.when, ExportTrigger::OnAttested);
5970
5971 // Second export — TestReport → HTTP + Always
5972 let t = &d.spec.exports[1];
5973 match t.channel.variant().unwrap() {
5974 ChannelVariant::HttpEvent(h) => assert_eq!(h.signal_type, "test-report"),
5975 other => panic!("expected HttpEvent, got {other:?}"),
5976 }
5977 assert_eq!(t.when, ExportTrigger::Always);
5978
5979 // Third export — RunMarker (BTreeMap<String,String> round-trip).
5980 // tatara-lisp lowercases + normalizes keyword keys before
5981 // handing off to serde_json — kebab `:run-id` may land as
5982 // either `run-id` or `runId` depending on the reader path.
5983 // Accept either; the round-trip property under test is
5984 // "label survives compile" not "exact case-form".
5985 let m = &d.spec.exports[2];
5986 match m.source.variant().unwrap() {
5987 ArtifactVariant::RunMarker(rm) => {
5988 assert_eq!(rm.labels.len(), 2);
5989 let run_id = rm
5990 .labels
5991 .get("run-id")
5992 .or_else(|| rm.labels.get("runId"))
5993 .or_else(|| rm.labels.get("run_id"))
5994 .expect("run-id label present under some normalization");
5995 assert_eq!(run_id, "r1");
5996 assert_eq!(rm.labels.get("phase").map(String::as_str), Some("end"));
5997 }
5998 other => panic!("expected RunMarker, got {other:?}"),
5999 }
6000
6001 // Lowered ProcessSpec carries the exports through unchanged.
6002 let ps: ProcessSpec = d.spec.clone().into();
6003 assert_eq!(ps.lifetime.ephemeral.as_ref().unwrap().exports.len(), 3);
6004 }
6005
6006 // ── EphemeralSpec::has_condition_kind substrate pins ─────────────
6007 //
6008 // Fail-before-pass-after granularity:
6009 // `EphemeralSpec::has_condition_kind` did not exist before this
6010 // commit — the (preconditions ∪ postconditions .iter().any(|c|
6011 // c.kind == K)) union-probe shape lived at ONE struct-level site
6012 // (`Boundary::has_condition_kind` on the point surface's nested
6013 // [`Boundary`] slot). The lift adds the peer inherent method on the
6014 // [`EphemeralSpec`] sugar-surface so both struct-level union
6015 // callers compose against the SAME slice-level substrate primitive
6016 // [`ConditionSliceExt::has_kind`] in lockstep. A regression that
6017 // (a) hard-coded the arm to a single kind, (b) dropped the pre-
6018 // condition side of the OR (a re-inheritance of the pre-lift
6019 // ephemeral `closed-loop-auth` post-only shape at the union-tag
6020 // level), or (c) probed the wrong slot fails HERE at the substrate
6021 // primitive rather than as silent operator-facing drift at the
6022 // ephemeral `condition-<kind>` require-tag surface.
6023
6024 fn empty_ephemeral() -> EphemeralSpec {
6025 EphemeralSpec {
6026 aplicacao: AplicacaoIntent::chart_only("oci://ghcr.io/x", "1"),
6027 ttl: "1h".into(),
6028 teardown: TeardownPolicy::Always,
6029 max_concurrent: 0,
6030 postconditions: vec![],
6031 preconditions: vec![],
6032 verify_timeout: None,
6033 classification: None,
6034 parent: None,
6035 exports: vec![],
6036 routing: None,
6037 }
6038 }
6039
6040 fn cond(kind: ConditionKind) -> Condition {
6041 Condition {
6042 kind,
6043 params: serde_json::json!({}),
6044 }
6045 }
6046
6047 /// EMPTY-SPEC pin — a default [`EphemeralSpec`] (empty
6048 /// preconditions, empty postconditions) returns `false` for EVERY
6049 /// [`ConditionKind`]. Sweep `ConditionKind::ALL` so a new variant
6050 /// added without a matching arm in the presence probe surfaces at
6051 /// rustc's exhaustiveness gate on the ALL literal (arity forced by
6052 /// `[Self; 8]`) rather than as a silent false-positive at every
6053 /// downstream `condition-<kind>` ephemeral require-tag callsite.
6054 /// Byte-for-byte peer of
6055 /// `has_condition_kind_returns_false_on_empty_boundary_for_every_kind`
6056 /// on the [`Boundary`] surface.
6057 #[test]
6058 fn has_condition_kind_returns_false_on_empty_ephemeral_for_every_kind() {
6059 let spec = empty_ephemeral();
6060 for kind in ConditionKind::ALL {
6061 assert!(
6062 !spec.has_condition_kind(kind),
6063 "empty ephemeral spec must return false for {kind:?}",
6064 );
6065 }
6066 }
6067
6068 /// POSTCONDITION-only pin — an ephemeral spec that carries the
6069 /// kind on ONLY postconditions returns `true` for that kind,
6070 /// `false` for every other variant. Sweep the ALL × ALL cross so
6071 /// a regression that hard-coded the arm to a single kind or
6072 /// probed the wrong slot fails HERE at the substrate primitive.
6073 #[test]
6074 fn has_condition_kind_reads_ephemeral_postconditions_per_kind() {
6075 for populated in ConditionKind::ALL {
6076 let mut spec = empty_ephemeral();
6077 spec.postconditions.push(cond(populated));
6078 for query in ConditionKind::ALL {
6079 let expected = query == populated;
6080 assert_eq!(
6081 spec.has_condition_kind(query),
6082 expected,
6083 "ephemeral postcondition populated={populated:?}: \
6084 query {query:?} drifted",
6085 );
6086 }
6087 }
6088 }
6089
6090 /// PRECONDITION-only pin — mirrors the postcondition sweep on the
6091 /// other half of the union. Locks the union semantics on both
6092 /// halves separately so a regression that dropped the pre-
6093 /// condition side of the OR fails here even though the
6094 /// postcondition-side pin above passes.
6095 #[test]
6096 fn has_condition_kind_reads_ephemeral_preconditions_per_kind() {
6097 for populated in ConditionKind::ALL {
6098 let mut spec = empty_ephemeral();
6099 spec.preconditions.push(cond(populated));
6100 for query in ConditionKind::ALL {
6101 let expected = query == populated;
6102 assert_eq!(
6103 spec.has_condition_kind(query),
6104 expected,
6105 "ephemeral precondition populated={populated:?}: \
6106 query {query:?} drifted",
6107 );
6108 }
6109 }
6110 }
6111
6112 /// UNION pin — a kind that appears on preconditions returns
6113 /// `true` even when postconditions carries a DIFFERENT kind, and
6114 /// vice versa. Pins the OR-composition of the two halves so a
6115 /// regression that collapsed the union to an intersection (AND)
6116 /// silently reclassifies pre-only or post-only kinds as absent.
6117 /// Byte-for-byte peer of
6118 /// `has_condition_kind_unions_pre_and_post_condition_arms` on the
6119 /// [`Boundary`] surface.
6120 #[test]
6121 fn has_condition_kind_unions_pre_and_post_ephemeral_condition_arms() {
6122 let mut spec = empty_ephemeral();
6123 spec.preconditions
6124 .push(cond(ConditionKind::KustomizationHealthy));
6125 spec.postconditions
6126 .push(cond(ConditionKind::ClosedLoopAuth));
6127 assert!(
6128 spec.has_condition_kind(ConditionKind::KustomizationHealthy),
6129 "pre-only kind must resolve through the union",
6130 );
6131 assert!(
6132 spec.has_condition_kind(ConditionKind::ClosedLoopAuth),
6133 "post-only kind must resolve through the union",
6134 );
6135 assert!(
6136 !spec.has_condition_kind(ConditionKind::PromQL),
6137 "an absent kind must return false even with populated halves",
6138 );
6139 }
6140
6141 /// COMPOSITION pin — [`EphemeralSpec::has_condition_kind`] equals
6142 /// the OR of the two slice-level probes on the pre/post fields.
6143 /// The struct-level union body composes ONLY [`ConditionSliceExt::has_kind`]
6144 /// on each half; a regression that inlined a wide-net predicate
6145 /// (`.iter().any(|c| c.kind != kind).not()`, an `all` instead of
6146 /// `any`) drifts from the slice-level primitive here. Byte-for-
6147 /// byte peer of the
6148 /// `boundary_has_condition_kind_equals_or_of_half_slice_probes`
6149 /// composition pin on the [`Boundary`] surface.
6150 #[test]
6151 fn ephemeral_has_condition_kind_equals_or_of_half_slice_probes() {
6152 // Sweep every ConditionKind on both halves independently so the
6153 // cross of half-slice probes reaches the OR-composition body
6154 // exhaustively.
6155 for populated in ConditionKind::ALL {
6156 let mut spec = empty_ephemeral();
6157 spec.preconditions.push(cond(populated));
6158 spec.postconditions.push(cond(ConditionKind::PromQL));
6159 for query in ConditionKind::ALL {
6160 let via_or_of_halves =
6161 spec.preconditions.has_kind(query) || spec.postconditions.has_kind(query);
6162 assert_eq!(
6163 spec.has_condition_kind(query),
6164 via_or_of_halves,
6165 "populated={populated:?} query={query:?}: struct-level \
6166 union drifted from OR of slice-level probes",
6167 );
6168 }
6169 }
6170 }
6171
6172 // ── EphemeralSpec::has_(pre|post)condition_kind substrate pins ──
6173 //
6174 // Fail-before-pass-after granularity: the two half-slice arms did
6175 // not exist on the ephemeral surface before this commit — the
6176 // ephemeral require-tag classifier in `tatara-check` and the
6177 // `closed-loop-auth` fixed-tag arm reached
6178 // `spec.postconditions.has_kind(K)` through direct field access,
6179 // asymmetric with the union-arm [`EphemeralSpec::has_condition_kind`]
6180 // that already routed through the named struct method. The lift
6181 // closes the (precondition, postcondition, union) triad on the
6182 // ephemeral sugar surface so a future normalization at the
6183 // presence-probe shape lands at ONE site per surface for all
6184 // three arms.
6185
6186 /// EMPTY-SPEC pin — an ephemeral spec with no preconditions and
6187 /// no postconditions returns `false` for EVERY [`ConditionKind`]
6188 /// on both half-slice arms. Sweep `ConditionKind::ALL` so a new
6189 /// variant added without a matching arm surfaces at rustc's
6190 /// exhaustiveness gate on the ALL literal (arity forced by the
6191 /// closed-set array) rather than as a silent false-positive at
6192 /// every downstream require-tag callsite on the ephemeral
6193 /// surface.
6194 #[test]
6195 fn ephemeral_has_precondition_and_postcondition_kind_return_false_on_empty_spec() {
6196 let spec = empty_ephemeral();
6197 for kind in ConditionKind::ALL {
6198 assert!(
6199 !spec.has_precondition_kind(kind),
6200 "empty ephemeral must return false on precondition arm for {kind:?}",
6201 );
6202 assert!(
6203 !spec.has_postcondition_kind(kind),
6204 "empty ephemeral must return false on postcondition arm for {kind:?}",
6205 );
6206 }
6207 }
6208
6209 /// SLICE-SELECTIVITY pin (precondition arm) — an ephemeral spec
6210 /// with a kind on the precondition side ONLY resolves `true` at
6211 /// [`EphemeralSpec::has_precondition_kind`] and `false` at
6212 /// [`EphemeralSpec::has_postcondition_kind`]. Locks the (side-
6213 /// select, kind-select) partition so a regression that pointed
6214 /// the precondition arm at `self.postconditions` (a copy-paste
6215 /// from the sibling arm during the lift) surfaces HERE.
6216 #[test]
6217 fn ephemeral_has_precondition_kind_reads_preconditions_slice_only() {
6218 for populated in ConditionKind::ALL {
6219 let mut spec = empty_ephemeral();
6220 spec.preconditions.push(cond(populated));
6221 for query in ConditionKind::ALL {
6222 let expected_pre = query == populated;
6223 assert_eq!(
6224 spec.has_precondition_kind(query),
6225 expected_pre,
6226 "precondition-only populated={populated:?}: query {query:?} \
6227 drifted on ephemeral precondition arm",
6228 );
6229 assert!(
6230 !spec.has_postcondition_kind(query),
6231 "precondition-only populated={populated:?}: query {query:?} must \
6232 return false on ephemeral postcondition arm (postconditions is empty)",
6233 );
6234 }
6235 }
6236 }
6237
6238 /// SLICE-SELECTIVITY pin (postcondition arm) — mirror of the
6239 /// precondition-only sweep on the other half. Locks the
6240 /// postcondition arm's binding to `self.postconditions` so a
6241 /// regression that pointed it at `self.preconditions` fails HERE
6242 /// even though the precondition-arm pin above passes.
6243 #[test]
6244 fn ephemeral_has_postcondition_kind_reads_postconditions_slice_only() {
6245 for populated in ConditionKind::ALL {
6246 let mut spec = empty_ephemeral();
6247 spec.postconditions.push(cond(populated));
6248 for query in ConditionKind::ALL {
6249 let expected_post = query == populated;
6250 assert_eq!(
6251 spec.has_postcondition_kind(query),
6252 expected_post,
6253 "postcondition-only populated={populated:?}: query {query:?} \
6254 drifted on ephemeral postcondition arm",
6255 );
6256 assert!(
6257 !spec.has_precondition_kind(query),
6258 "postcondition-only populated={populated:?}: query {query:?} must \
6259 return false on ephemeral precondition arm (preconditions is empty)",
6260 );
6261 }
6262 }
6263 }
6264
6265 /// COMPOSITION-LAW pin — [`EphemeralSpec::has_condition_kind`]
6266 /// equals `has_precondition_kind(k) || has_postcondition_kind(k)`
6267 /// at EVERY (pre-populated, post-populated, query) triple on
6268 /// `ConditionKind::ALL`. Byte-for-byte peer of the
6269 /// `boundary_has_condition_kind_composes_precondition_and_postcondition_arms`
6270 /// composition-law pin on the [`Boundary`] surface — the
6271 /// two-surface parity contract binds the ephemeral sugar type
6272 /// and the point-domain boundary type through the SAME
6273 /// (`condition_kind = precondition_kind ∨ postcondition_kind`)
6274 /// composition, so every downstream `condition-<K>` require-tag
6275 /// classifier on either surface inherits the composition
6276 /// mechanically.
6277 #[test]
6278 fn ephemeral_has_condition_kind_composes_precondition_and_postcondition_arms() {
6279 for pre_kind in ConditionKind::ALL {
6280 for post_kind in ConditionKind::ALL {
6281 let mut spec = empty_ephemeral();
6282 spec.preconditions.push(cond(pre_kind));
6283 spec.postconditions.push(cond(post_kind));
6284 for query in ConditionKind::ALL {
6285 let via_arms =
6286 spec.has_precondition_kind(query) || spec.has_postcondition_kind(query);
6287 assert_eq!(
6288 spec.has_condition_kind(query),
6289 via_arms,
6290 "ephemeral union arm drifted from OR of half-slice arms: \
6291 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6292 );
6293 }
6294 }
6295 }
6296 }
6297
6298 /// SUBSTRATE-DELEGATION pin — the two half-slice arms on the
6299 /// ephemeral surface delegate verbatim to
6300 /// [`crate::boundary::ConditionSliceExt::has_kind`] on the
6301 /// underlying [`Vec<Condition>`] slice, no inline reimplementation.
6302 /// Sweep the full `ConditionKind::ALL` × `ConditionKind::ALL`
6303 /// cross so a regression that inlined a divergent walk at either
6304 /// arm surfaces HERE at the substrate boundary rather than as
6305 /// silent skew between the struct-level arm and the slice-level
6306 /// primitive.
6307 #[test]
6308 fn ephemeral_has_precondition_and_postcondition_kind_delegate_to_slice_has_kind() {
6309 for populated in ConditionKind::ALL {
6310 let mut spec = empty_ephemeral();
6311 spec.preconditions.push(cond(populated));
6312 spec.postconditions.push(cond(populated));
6313 for query in ConditionKind::ALL {
6314 assert_eq!(
6315 spec.has_precondition_kind(query),
6316 spec.preconditions.has_kind(query),
6317 "ephemeral precondition arm must delegate to preconditions.has_kind: \
6318 populated={populated:?} query={query:?}",
6319 );
6320 assert_eq!(
6321 spec.has_postcondition_kind(query),
6322 spec.postconditions.has_kind(query),
6323 "ephemeral postcondition arm must delegate to postconditions.has_kind: \
6324 populated={populated:?} query={query:?}",
6325 );
6326 }
6327 }
6328 }
6329
6330 // ── EphemeralSpec::find_(pre|post|)condition_kind widened triad ──
6331 //
6332 // Fail-before-pass-after granularity: the three widened
6333 // `find_*_kind` arms did not exist on the ephemeral surface before
6334 // this commit — the (widened `Option<&Condition>` return) axis
6335 // lived at ONE struct-level site (`Boundary::find_condition_kind`
6336 // on the point surface's nested [`Boundary`] slot). The lift adds
6337 // the peer inherent methods on the [`EphemeralSpec`] sugar-surface
6338 // so both struct-level widened callers compose against the SAME
6339 // slice-level substrate primitive
6340 // [`crate::boundary::ConditionSliceExt::find_kind`] in lockstep.
6341 // A regression that (a) hard-coded the arm to a single kind, (b)
6342 // reversed the walk order on the union (postcondition first), or
6343 // (c) collapsed `or_else` to `and_then` (silently narrowing the
6344 // union to an intersection) fails HERE at the substrate primitive
6345 // rather than as silent operator-facing drift at the ephemeral
6346 // require-tag surface.
6347
6348 /// EMPTY-SPEC pin (find-triad) — a default [`EphemeralSpec`]
6349 /// (empty preconditions, empty postconditions) returns `None`
6350 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
6351 /// `ConditionKind::ALL` × three-arm cross so a new variant added
6352 /// without a matching arm surfaces at rustc's exhaustiveness gate
6353 /// on the ALL literal (arity forced by the closed-set array)
6354 /// rather than as a silent false-`Some` at every downstream
6355 /// widened callsite on the ephemeral surface.
6356 #[test]
6357 fn ephemeral_find_condition_kind_triad_returns_none_on_empty_spec() {
6358 let spec = empty_ephemeral();
6359 for kind in ConditionKind::ALL {
6360 assert!(
6361 spec.find_precondition_kind(kind).is_none(),
6362 "empty ephemeral must return None on precondition find arm for {kind:?}",
6363 );
6364 assert!(
6365 spec.find_postcondition_kind(kind).is_none(),
6366 "empty ephemeral must return None on postcondition find arm for {kind:?}",
6367 );
6368 assert!(
6369 spec.find_condition_kind(kind).is_none(),
6370 "empty ephemeral must return None on union find arm for {kind:?}",
6371 );
6372 }
6373 }
6374
6375 /// SUBSTRATE-DELEGATION pin (ephemeral find-triad) — the three
6376 /// widened `find_*_kind` methods on [`EphemeralSpec`] delegate
6377 /// verbatim to [`crate::boundary::ConditionSliceExt::find_kind`]
6378 /// on the underlying [`Vec<Condition>`] slices, no inline
6379 /// reimplementation. The `find_condition_kind` union walks
6380 /// preconditions first then postconditions via `Option::or_else`.
6381 /// Sweep `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
6382 /// so a regression that (a) inlined a divergent walk at either
6383 /// half-slice arm, (b) reversed the union walk order on the
6384 /// ephemeral surface only (breaking two-surface parity with
6385 /// [`crate::boundary::Boundary::find_condition_kind`]), or (c)
6386 /// collapsed `or_else` to `and_then` surfaces HERE at the substrate
6387 /// boundary. Byte-for-byte peer of the point-domain
6388 /// `find_condition_kind_triad_delegates_to_slice_find_kind` pin.
6389 #[test]
6390 fn ephemeral_find_condition_kind_triad_delegates_to_slice_find_kind() {
6391 for pre_kind in ConditionKind::ALL {
6392 for post_kind in ConditionKind::ALL {
6393 let mut spec = empty_ephemeral();
6394 spec.preconditions.push(cond(pre_kind));
6395 spec.postconditions.push(cond(post_kind));
6396 for query in ConditionKind::ALL {
6397 let via_pre = spec.preconditions.find_kind(query);
6398 let via_post = spec.postconditions.find_kind(query);
6399 assert_eq!(
6400 spec.find_precondition_kind(query).map(|c| c.kind),
6401 via_pre.map(|c| c.kind),
6402 "ephemeral precondition find arm must delegate: \
6403 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6404 );
6405 assert_eq!(
6406 spec.find_postcondition_kind(query).map(|c| c.kind),
6407 via_post.map(|c| c.kind),
6408 "ephemeral postcondition find arm must delegate: \
6409 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6410 );
6411 let expected_union = via_pre.or(via_post).map(|c| c.kind);
6412 assert_eq!(
6413 spec.find_condition_kind(query).map(|c| c.kind),
6414 expected_union,
6415 "ephemeral union find arm must equal precondition.or_else(postcondition): \
6416 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6417 );
6418 }
6419 }
6420 }
6421 }
6422
6423 /// PRECONDITION-PRECEDENCE pin (ephemeral) — a kind authored on
6424 /// BOTH sides returns the precondition-side [`Condition`] from
6425 /// `find_condition_kind`. Byte-for-byte peer of the point-domain
6426 /// `find_condition_kind_returns_precondition_side_on_dual_populated`
6427 /// pin, so the two-surface parity contract binds the walk order
6428 /// on both surfaces through ONE composition law. Uses two params-
6429 /// distinguishable [`Condition`]s so a regression on the ephemeral
6430 /// surface only that reversed the walk order surfaces at the
6431 /// returned params payload rather than silently at the presence
6432 /// bit.
6433 #[test]
6434 fn ephemeral_find_condition_kind_returns_precondition_side_on_dual_populated() {
6435 let mut spec = empty_ephemeral();
6436 spec.preconditions.push(Condition {
6437 kind: ConditionKind::ClosedLoopAuth,
6438 params: serde_json::json!({ "side": "pre" }),
6439 });
6440 spec.postconditions.push(Condition {
6441 kind: ConditionKind::ClosedLoopAuth,
6442 params: serde_json::json!({ "side": "post" }),
6443 });
6444 let hit = spec
6445 .find_condition_kind(ConditionKind::ClosedLoopAuth)
6446 .expect("dual-populated ephemeral spec must resolve Some");
6447 assert_eq!(
6448 hit.params.get("side").and_then(serde_json::Value::as_str),
6449 Some("pre"),
6450 "ephemeral find_condition_kind must walk preconditions first",
6451 );
6452 }
6453
6454 /// STRUCT-LEVEL DELEGATION pin (ephemeral has ↔ find) — the three
6455 /// [`EphemeralSpec`] `has_*_kind` arms equal their widened peers'
6456 /// `.is_some()` projection at EVERY (pre-populated, post-populated,
6457 /// query) triple on `ConditionKind::ALL`. Byte-for-byte peer of
6458 /// the point-domain
6459 /// `boundary_has_triad_equals_find_triad_is_some_projection` pin,
6460 /// so both surfaces' has/find refinement bridge stays symmetric by
6461 /// construction — a future consumer that reads
6462 /// `spec.has_condition_kind(k)` as sugar for
6463 /// `spec.find_condition_kind(k).is_some()` on either surface stays
6464 /// typed against the SAME truth table across the two-surface
6465 /// parity contract.
6466 #[test]
6467 fn ephemeral_has_triad_equals_find_triad_is_some_projection() {
6468 for pre_kind in ConditionKind::ALL {
6469 for post_kind in ConditionKind::ALL {
6470 let mut spec = empty_ephemeral();
6471 spec.preconditions.push(cond(pre_kind));
6472 spec.postconditions.push(cond(post_kind));
6473 for query in ConditionKind::ALL {
6474 assert_eq!(
6475 spec.has_precondition_kind(query),
6476 spec.find_precondition_kind(query).is_some(),
6477 "ephemeral precondition has/find bridge drifted: \
6478 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6479 );
6480 assert_eq!(
6481 spec.has_postcondition_kind(query),
6482 spec.find_postcondition_kind(query).is_some(),
6483 "ephemeral postcondition has/find bridge drifted: \
6484 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6485 );
6486 assert_eq!(
6487 spec.has_condition_kind(query),
6488 spec.find_condition_kind(query).is_some(),
6489 "ephemeral union has/find bridge drifted: \
6490 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6491 );
6492 }
6493 }
6494 }
6495 }
6496
6497 // ── EphemeralSpec::iter_(pre|post|)condition_kind widened triad ──
6498 //
6499 // Fail-before-pass-after granularity: the three widened
6500 // `iter_*_kind` arms did not exist on the ephemeral surface before
6501 // this commit — the (widened `impl Iterator<Item = &Condition>`
6502 // stream) axis lived at ONE struct-level site
6503 // (`Boundary::iter_condition_kind` on the point surface's nested
6504 // [`Boundary`] slot). The lift adds the peer inherent methods on
6505 // the [`EphemeralSpec`] sugar-surface so both struct-level widened
6506 // callers compose against the SAME slice-level substrate primitive
6507 // [`crate::boundary::ConditionSliceExt::iter_kind`] in lockstep.
6508 // A regression that (a) hard-coded the arm to a single kind, (b)
6509 // reversed the chain order on the union (postcondition first), or
6510 // (c) collapsed the chain to a `.zip(...)` (silently narrowing the
6511 // union to an intersection-by-position) fails HERE at the
6512 // substrate primitive rather than as silent operator-facing drift
6513 // at the ephemeral require-tag surface.
6514
6515 /// EMPTY-SPEC pin (iter-triad) — a default [`EphemeralSpec`]
6516 /// (empty preconditions, empty postconditions) yields nothing
6517 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
6518 /// `ConditionKind::ALL` × three-arm cross so a new variant added
6519 /// without a matching arm surfaces at rustc's exhaustiveness gate
6520 /// on the ALL literal rather than as a silent phantom-yield at
6521 /// every downstream widened callsite on the ephemeral surface.
6522 #[test]
6523 fn ephemeral_iter_condition_kind_triad_yields_nothing_on_empty_spec() {
6524 let spec = empty_ephemeral();
6525 for kind in ConditionKind::ALL {
6526 assert_eq!(
6527 spec.iter_precondition_kind(kind).count(),
6528 0,
6529 "empty ephemeral must yield nothing on precondition iter arm for {kind:?}",
6530 );
6531 assert_eq!(
6532 spec.iter_postcondition_kind(kind).count(),
6533 0,
6534 "empty ephemeral must yield nothing on postcondition iter arm for {kind:?}",
6535 );
6536 assert_eq!(
6537 spec.iter_condition_kind(kind).count(),
6538 0,
6539 "empty ephemeral must yield nothing on union iter arm for {kind:?}",
6540 );
6541 }
6542 }
6543
6544 /// SUBSTRATE-DELEGATION pin (ephemeral iter-triad) — the three
6545 /// widened `iter_*_kind` methods on [`EphemeralSpec`] delegate
6546 /// verbatim to [`crate::boundary::ConditionSliceExt::iter_kind`]
6547 /// on the underlying [`Vec<Condition>`] slices, no inline
6548 /// reimplementation. The `iter_condition_kind` union chains
6549 /// preconditions first then postconditions via
6550 /// [`Iterator::chain`]. Sweep
6551 /// `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
6552 /// so a regression that (a) inlined a divergent walk at either
6553 /// half-slice arm, (b) reversed the chain order on the ephemeral
6554 /// surface only (breaking two-surface parity with
6555 /// [`crate::boundary::Boundary::iter_condition_kind`]), or (c)
6556 /// collapsed the chain to a `.zip(...)` surfaces HERE at the
6557 /// substrate boundary. Byte-for-byte peer of the point-domain
6558 /// `iter_condition_kind_triad_delegates_to_slice_iter_kind` pin.
6559 #[test]
6560 fn ephemeral_iter_condition_kind_triad_delegates_to_slice_iter_kind() {
6561 for pre_kind in ConditionKind::ALL {
6562 for post_kind in ConditionKind::ALL {
6563 let mut spec = empty_ephemeral();
6564 spec.preconditions.push(cond(pre_kind));
6565 spec.postconditions.push(cond(post_kind));
6566 for query in ConditionKind::ALL {
6567 let via_pre: Vec<_> = spec
6568 .preconditions
6569 .iter_kind(query)
6570 .map(|c| c.kind)
6571 .collect();
6572 let via_post: Vec<_> = spec
6573 .postconditions
6574 .iter_kind(query)
6575 .map(|c| c.kind)
6576 .collect();
6577 assert_eq!(
6578 spec.iter_precondition_kind(query)
6579 .map(|c| c.kind)
6580 .collect::<Vec<_>>(),
6581 via_pre,
6582 "ephemeral precondition iter arm must delegate: \
6583 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6584 );
6585 assert_eq!(
6586 spec.iter_postcondition_kind(query)
6587 .map(|c| c.kind)
6588 .collect::<Vec<_>>(),
6589 via_post,
6590 "ephemeral postcondition iter arm must delegate: \
6591 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6592 );
6593 let mut expected_union = via_pre.clone();
6594 expected_union.extend(via_post.iter().copied());
6595 assert_eq!(
6596 spec.iter_condition_kind(query)
6597 .map(|c| c.kind)
6598 .collect::<Vec<_>>(),
6599 expected_union,
6600 "ephemeral union iter arm must chain precondition ⨟ postcondition: \
6601 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6602 );
6603 }
6604 }
6605 }
6606 }
6607
6608 /// PRECONDITION-PRECEDENCE pin (ephemeral iter) — a kind
6609 /// authored on BOTH sides yields precondition-side matches
6610 /// FIRST in the union chain. Byte-for-byte peer of the
6611 /// point-domain
6612 /// `iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated`
6613 /// pin — the two-surface parity contract binds the chain order
6614 /// on both surfaces through ONE composition law. Uses two
6615 /// params-distinguishable [`Condition`]s so a regression on the
6616 /// ephemeral surface only that reversed the chain order surfaces
6617 /// at the returned params payload rather than silently at the
6618 /// count.
6619 #[test]
6620 fn ephemeral_iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated()
6621 {
6622 let mut spec = empty_ephemeral();
6623 spec.preconditions.push(Condition {
6624 kind: ConditionKind::ClosedLoopAuth,
6625 params: serde_json::json!({ "side": "pre-1" }),
6626 });
6627 spec.postconditions.push(Condition {
6628 kind: ConditionKind::ClosedLoopAuth,
6629 params: serde_json::json!({ "side": "post-1" }),
6630 });
6631 spec.postconditions.push(Condition {
6632 kind: ConditionKind::ClosedLoopAuth,
6633 params: serde_json::json!({ "side": "post-2" }),
6634 });
6635 let sides: Vec<_> = spec
6636 .iter_condition_kind(ConditionKind::ClosedLoopAuth)
6637 .map(|c| {
6638 c.params
6639 .get("side")
6640 .and_then(serde_json::Value::as_str)
6641 .unwrap_or_default()
6642 .to_owned()
6643 })
6644 .collect();
6645 assert_eq!(
6646 sides,
6647 vec!["pre-1".to_owned(), "post-1".to_owned(), "post-2".to_owned(),],
6648 "ephemeral iter_condition_kind must yield every precondition-side match before \
6649 any postcondition-side match (chain order pinned by two-surface parity)",
6650 );
6651 }
6652
6653 /// STRUCT-LEVEL DELEGATION pin (find ↔ iter on EphemeralSpec) —
6654 /// the three [`EphemeralSpec`] `find_*_kind` arms equal their
6655 /// widened peers' `.next()` projection at EVERY (pre-populated,
6656 /// post-populated, query) triple on `ConditionKind::ALL`.
6657 /// Byte-for-byte peer of the point-domain
6658 /// `boundary_find_triad_equals_iter_triad_next_projection` pin,
6659 /// so both surfaces' find/iter refinement bridge stays symmetric
6660 /// by construction across the two-surface parity contract.
6661 #[test]
6662 fn ephemeral_find_triad_equals_iter_triad_next_projection() {
6663 for pre_kind in ConditionKind::ALL {
6664 for post_kind in ConditionKind::ALL {
6665 let mut spec = empty_ephemeral();
6666 spec.preconditions.push(cond(pre_kind));
6667 spec.postconditions.push(cond(post_kind));
6668 for query in ConditionKind::ALL {
6669 assert_eq!(
6670 spec.find_precondition_kind(query).map(|c| c.kind),
6671 spec.iter_precondition_kind(query).next().map(|c| c.kind),
6672 "ephemeral precondition find/iter bridge drifted: \
6673 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6674 );
6675 assert_eq!(
6676 spec.find_postcondition_kind(query).map(|c| c.kind),
6677 spec.iter_postcondition_kind(query).next().map(|c| c.kind),
6678 "ephemeral postcondition find/iter bridge drifted: \
6679 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6680 );
6681 assert_eq!(
6682 spec.find_condition_kind(query).map(|c| c.kind),
6683 spec.iter_condition_kind(query).next().map(|c| c.kind),
6684 "ephemeral union find/iter bridge drifted: \
6685 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6686 );
6687 }
6688 }
6689 }
6690 }
6691
6692 // ── EphemeralSpec count triad — scalar cardinality peers ─────────
6693 //
6694 // Byte-for-byte peers of the point-domain `Boundary`
6695 // `count_(pre|post|)condition_kind` triad, tested at the ephemeral
6696 // sugar surface. Same SUM composition on the union arm, same
6697 // slice-level substrate delegation, same composition-law bridge
6698 // against the widened iter refinement.
6699
6700 /// EMPTY-SPEC pin (count-triad) — a default [`EphemeralSpec`]
6701 /// counts `0` from every arm of the count triad for EVERY
6702 /// [`ConditionKind`].
6703 #[test]
6704 fn ephemeral_count_condition_kind_triad_returns_zero_on_empty_spec() {
6705 let spec = empty_ephemeral();
6706 for kind in ConditionKind::ALL {
6707 assert_eq!(
6708 spec.count_precondition_kind(kind),
6709 0,
6710 "empty ephemeral must count 0 on precondition arm for {kind:?}",
6711 );
6712 assert_eq!(
6713 spec.count_postcondition_kind(kind),
6714 0,
6715 "empty ephemeral must count 0 on postcondition arm for {kind:?}",
6716 );
6717 assert_eq!(
6718 spec.count_condition_kind(kind),
6719 0,
6720 "empty ephemeral must count 0 on union arm for {kind:?}",
6721 );
6722 }
6723 }
6724
6725 /// SUBSTRATE-DELEGATION pin (ephemeral count-triad) — the three
6726 /// widened `count_*_kind` methods on [`EphemeralSpec`] delegate
6727 /// verbatim to [`crate::boundary::ConditionSliceExt::count_kind`]
6728 /// on the underlying [`Vec<Condition>`] slices. The
6729 /// `count_condition_kind` union SUMS preconditions and
6730 /// postconditions. Byte-for-byte peer of the point-domain
6731 /// `boundary_count_condition_kind_triad_delegates_and_sums_slice_count_kind`
6732 /// pin; a regression that (a) subtracted rather than summed, (b)
6733 /// collapsed the sum to [`std::cmp::max`], or (c) inlined a
6734 /// divergent count at either half-slice arm on the ephemeral
6735 /// surface only (breaking two-surface parity with [`Boundary`])
6736 /// surfaces HERE.
6737 #[test]
6738 fn ephemeral_count_condition_kind_triad_delegates_and_sums_slice_count_kind() {
6739 for pre_kind in ConditionKind::ALL {
6740 for post_kind in ConditionKind::ALL {
6741 let mut spec = empty_ephemeral();
6742 spec.preconditions.push(cond(pre_kind));
6743 spec.postconditions.push(cond(post_kind));
6744 for query in ConditionKind::ALL {
6745 let via_pre = spec.preconditions.count_kind(query);
6746 let via_post = spec.postconditions.count_kind(query);
6747 assert_eq!(
6748 spec.count_precondition_kind(query),
6749 via_pre,
6750 "ephemeral precondition count arm must delegate: \
6751 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6752 );
6753 assert_eq!(
6754 spec.count_postcondition_kind(query),
6755 via_post,
6756 "ephemeral postcondition count arm must delegate: \
6757 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6758 );
6759 assert_eq!(
6760 spec.count_condition_kind(query),
6761 via_pre + via_post,
6762 "ephemeral union count arm must SUM pre + post: \
6763 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6764 );
6765 }
6766 }
6767 }
6768 }
6769
6770 /// STRUCT-LEVEL DELEGATION pin (count ↔ iter on EphemeralSpec) —
6771 /// the three [`EphemeralSpec`] `count_*_kind` arms equal their
6772 /// widened peers' `.count()` projection at EVERY (pre-populated
6773 /// twice, post-populated, query) triple. Byte-for-byte peer of
6774 /// the point-domain
6775 /// `boundary_count_triad_equals_iter_triad_count_projection`
6776 /// pin. Uses two-preconditions authoring so the union arm's SUM
6777 /// composition witnesses a nontrivial cardinality (rather than
6778 /// coinciding with the presence bit).
6779 #[test]
6780 fn ephemeral_count_triad_equals_iter_triad_count_projection() {
6781 for pre_kind in ConditionKind::ALL {
6782 for post_kind in ConditionKind::ALL {
6783 let mut spec = empty_ephemeral();
6784 spec.preconditions.push(cond(pre_kind));
6785 spec.preconditions.push(cond(pre_kind));
6786 spec.postconditions.push(cond(post_kind));
6787 for query in ConditionKind::ALL {
6788 assert_eq!(
6789 spec.count_precondition_kind(query),
6790 spec.iter_precondition_kind(query).count(),
6791 "ephemeral precondition count/iter bridge drifted: \
6792 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6793 );
6794 assert_eq!(
6795 spec.count_postcondition_kind(query),
6796 spec.iter_postcondition_kind(query).count(),
6797 "ephemeral postcondition count/iter bridge drifted: \
6798 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6799 );
6800 assert_eq!(
6801 spec.count_condition_kind(query),
6802 spec.iter_condition_kind(query).count(),
6803 "ephemeral union count/iter bridge drifted: \
6804 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6805 );
6806 }
6807 }
6808 }
6809 }
6810
6811 // ── EphemeralSpec distinct-set triad — substrate-delegation pin ──
6812 //
6813 // The (precondition, postcondition, condition-union) distinct-set
6814 // triad on [`EphemeralSpec`] delegates to the slice-level substrate
6815 // primitive [`crate::boundary::ConditionSliceExt::distinct_kinds`]
6816 // on each half-slice and composes the union via
6817 // [`Self::has_condition_kind`] over [`ConditionKind::ALL`] — byte-
6818 // for-byte peer of the point-surface distinct-set triad on
6819 // [`crate::boundary::Boundary`]. The two-surface parity contract
6820 // now covers FIVE refinements on the condition axis: the four
6821 // point-probe refinements (has / find / iter / count) AND the ONE
6822 // closed-set-inversion refinement (distinct-set) on both surfaces.
6823
6824 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-kind-count
6825 /// triad) — the three `distinct_*_kind_count` methods on
6826 /// [`EphemeralSpec`] delegate to the slice-level substrate
6827 /// primitive [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
6828 /// over the two `Vec<Condition>` slots and compose the union
6829 /// scalar via `ConditionKind::ALL.filter(|k|
6830 /// has_condition_kind(*k)).count()`. Byte-for-byte peer of the
6831 /// point-surface pin
6832 /// `distinct_condition_kind_count_triad_delegates_to_slice_distinct_kind_count`
6833 /// on [`crate::boundary::Boundary`] — the two-surface parity
6834 /// contract now binds every downstream scalar-cardinality consumer
6835 /// on either surface to the SAME closed-set walk through ONE
6836 /// substrate rather than through per-surface `.distinct_*_kinds().len()`
6837 /// re-materializations that pay for a heap allocation.
6838 #[test]
6839 fn ephemeral_distinct_condition_kind_count_triad_delegates_and_matches_distinct_kinds_len() {
6840 // Empty spec — every arm returns 0.
6841 let spec = empty_ephemeral();
6842 for kind in ConditionKind::ALL {
6843 assert_eq!(
6844 spec.distinct_precondition_kind_count(),
6845 0,
6846 "empty ephemeral spec must return 0 on distinct_precondition_kind_count, kind={kind:?}",
6847 );
6848 assert_eq!(
6849 spec.distinct_postcondition_kind_count(),
6850 0,
6851 "empty ephemeral spec must return 0 on distinct_postcondition_kind_count, kind={kind:?}",
6852 );
6853 assert_eq!(
6854 spec.distinct_condition_kind_count(),
6855 0,
6856 "empty ephemeral spec must return 0 on distinct_condition_kind_count, kind={kind:?}",
6857 );
6858 }
6859
6860 for pre_kind in ConditionKind::ALL {
6861 for post_kind in ConditionKind::ALL {
6862 let mut spec = empty_ephemeral();
6863 spec.preconditions.push(cond(pre_kind));
6864 spec.postconditions.push(cond(post_kind));
6865
6866 assert_eq!(
6867 spec.distinct_precondition_kind_count(),
6868 spec.preconditions.distinct_kind_count(),
6869 "EphemeralSpec::distinct_precondition_kind_count must delegate verbatim to \
6870 preconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6871 );
6872 assert_eq!(
6873 spec.distinct_precondition_kind_count(),
6874 spec.distinct_precondition_kinds().len(),
6875 "EphemeralSpec::distinct_precondition_kind_count must equal \
6876 distinct_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6877 );
6878 assert_eq!(
6879 spec.distinct_postcondition_kind_count(),
6880 spec.postconditions.distinct_kind_count(),
6881 "EphemeralSpec::distinct_postcondition_kind_count must delegate verbatim to \
6882 postconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6883 );
6884 assert_eq!(
6885 spec.distinct_postcondition_kind_count(),
6886 spec.distinct_postcondition_kinds().len(),
6887 "EphemeralSpec::distinct_postcondition_kind_count must equal \
6888 distinct_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6889 );
6890 let expected_union_count = if pre_kind == post_kind { 1 } else { 2 };
6891 assert_eq!(
6892 spec.distinct_condition_kind_count(),
6893 expected_union_count,
6894 "EphemeralSpec::distinct_condition_kind_count must count distinct union kinds \
6895 for pre={pre_kind:?} post={post_kind:?}",
6896 );
6897 assert_eq!(
6898 spec.distinct_condition_kind_count(),
6899 spec.distinct_condition_kinds().len(),
6900 "EphemeralSpec::distinct_condition_kind_count must equal \
6901 distinct_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6902 );
6903 }
6904 }
6905 }
6906
6907 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-set triad)
6908 /// — the three `distinct_*_kinds` methods on [`EphemeralSpec`]
6909 /// delegate to the slice-level substrate primitive over the two
6910 /// `Vec<Condition>` slots and compose the union via
6911 /// `ConditionKind::ALL.filter(|k| has_condition_kind(*k))`. Byte-
6912 /// for-byte peer of the point-surface pin
6913 /// `distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds`
6914 /// on [`crate::boundary::Boundary`] — the two-surface parity
6915 /// contract binds every downstream distinct-set consumer on either
6916 /// surface to the SAME closed-set-inversion primitive through ONE
6917 /// substrate rather than through per-surface re-authored sweeps.
6918 #[test]
6919 fn ephemeral_distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds() {
6920 for pre_kind in ConditionKind::ALL {
6921 for post_kind in ConditionKind::ALL {
6922 let mut spec = empty_ephemeral();
6923 spec.preconditions.push(cond(pre_kind));
6924 spec.postconditions.push(cond(post_kind));
6925
6926 assert_eq!(
6927 spec.distinct_precondition_kinds(),
6928 spec.preconditions.distinct_kinds(),
6929 "EphemeralSpec::distinct_precondition_kinds must delegate verbatim to \
6930 preconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
6931 );
6932 assert_eq!(
6933 spec.distinct_postcondition_kinds(),
6934 spec.postconditions.distinct_kinds(),
6935 "EphemeralSpec::distinct_postcondition_kinds must delegate verbatim to \
6936 postconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
6937 );
6938 let expected_union: Vec<_> = ConditionKind::ALL
6939 .into_iter()
6940 .filter(|k| pre_kind == *k || post_kind == *k)
6941 .collect();
6942 assert_eq!(
6943 spec.distinct_condition_kinds(),
6944 expected_union,
6945 "EphemeralSpec::distinct_condition_kinds must equal ConditionKind::ALL-ordered \
6946 set-union of the two half-slice distinct-sets for pre={pre_kind:?} post={post_kind:?}",
6947 );
6948 }
6949 }
6950 }
6951
6952 /// SUBSTRATE-DELEGATION pin (EphemeralSpec distinct-set ITERATOR
6953 /// triad) — the three `iter_distinct_*_condition_kinds` methods on
6954 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
6955 /// [`crate::boundary::ConditionSliceExt::iter_distinct_kinds`] over
6956 /// the two `Vec<Condition>` slots and compose the union via
6957 /// `ConditionKind::ALL.iter().copied().filter(|&k|
6958 /// has_condition_kind(k))`. Byte-for-byte peer of
6959 /// `iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
6960 /// on the point-domain [`crate::boundary::Boundary`] surface — both
6961 /// peers compose against the SAME slice-level iterator substrate.
6962 #[test]
6963 fn ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds() {
6964 for pre_kind in ConditionKind::ALL {
6965 for post_kind in ConditionKind::ALL {
6966 let mut spec = empty_ephemeral();
6967 spec.preconditions.push(cond(pre_kind));
6968 spec.postconditions.push(cond(post_kind));
6969
6970 let pre_via_iter: Vec<_> = spec.iter_distinct_precondition_kinds().collect();
6971 assert_eq!(
6972 pre_via_iter,
6973 spec.distinct_precondition_kinds(),
6974 "EphemeralSpec::iter_distinct_precondition_kinds().collect() drifted from \
6975 distinct_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
6976 );
6977 let post_via_iter: Vec<_> = spec.iter_distinct_postcondition_kinds().collect();
6978 assert_eq!(
6979 post_via_iter,
6980 spec.distinct_postcondition_kinds(),
6981 "EphemeralSpec::iter_distinct_postcondition_kinds().collect() drifted from \
6982 distinct_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
6983 );
6984 let union_via_iter: Vec<_> = spec.iter_distinct_condition_kinds().collect();
6985 assert_eq!(
6986 union_via_iter,
6987 spec.distinct_condition_kinds(),
6988 "EphemeralSpec::iter_distinct_condition_kinds().collect() drifted from \
6989 distinct_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
6990 );
6991 }
6992 }
6993 }
6994
6995 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set ITERATOR
6996 /// triad) — the three `iter_missing_*_condition_kinds` methods on
6997 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
6998 /// [`crate::boundary::ConditionSliceExt::iter_missing_kinds`] over
6999 /// the two `Vec<Condition>` slots and compose the union via
7000 /// `ConditionKind::ALL.iter().copied().filter(|&k|
7001 /// !has_condition_kind(k))`. Peer of
7002 /// `ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
7003 /// on the missing side under a NEGATED point-probe.
7004 #[test]
7005 fn ephemeral_iter_missing_condition_kinds_triad_delegates_to_slice_iter_missing_kinds() {
7006 let empty = empty_ephemeral();
7007 let all: Vec<_> = ConditionKind::ALL.to_vec();
7008 assert_eq!(
7009 empty.iter_missing_precondition_kinds().collect::<Vec<_>>(),
7010 all,
7011 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_precondition_kinds",
7012 );
7013 assert_eq!(
7014 empty.iter_missing_postcondition_kinds().collect::<Vec<_>>(),
7015 all,
7016 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_postcondition_kinds",
7017 );
7018 assert_eq!(
7019 empty.iter_missing_condition_kinds().collect::<Vec<_>>(),
7020 all,
7021 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_condition_kinds",
7022 );
7023
7024 for pre_kind in ConditionKind::ALL {
7025 for post_kind in ConditionKind::ALL {
7026 let mut spec = empty_ephemeral();
7027 spec.preconditions.push(cond(pre_kind));
7028 spec.postconditions.push(cond(post_kind));
7029
7030 let pre_via_iter: Vec<_> = spec.iter_missing_precondition_kinds().collect();
7031 assert_eq!(
7032 pre_via_iter,
7033 spec.missing_precondition_kinds(),
7034 "EphemeralSpec::iter_missing_precondition_kinds().collect() drifted from \
7035 missing_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7036 );
7037 let post_via_iter: Vec<_> = spec.iter_missing_postcondition_kinds().collect();
7038 assert_eq!(
7039 post_via_iter,
7040 spec.missing_postcondition_kinds(),
7041 "EphemeralSpec::iter_missing_postcondition_kinds().collect() drifted from \
7042 missing_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7043 );
7044 let union_via_iter: Vec<_> = spec.iter_missing_condition_kinds().collect();
7045 assert_eq!(
7046 union_via_iter,
7047 spec.missing_condition_kinds(),
7048 "EphemeralSpec::iter_missing_condition_kinds().collect() drifted from \
7049 missing_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7050 );
7051 }
7052 }
7053 }
7054
7055 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set triad) —
7056 /// the three `missing_*_kinds` methods on [`EphemeralSpec`]
7057 /// delegate to the slice-level substrate primitive
7058 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over the
7059 /// two `Vec<Condition>` slots and compose the union via
7060 /// `ConditionKind::ALL.filter(|k| !has_condition_kind(*k))`. Sweep
7061 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
7062 /// `missing_condition_kinds_triad_delegates_to_slice_missing_kinds`
7063 /// on the point-domain [`crate::boundary::Boundary`] surface —
7064 /// both peers compose against the SAME slice-level substrate
7065 /// primitive so a regression at the per-slice complement walk
7066 /// fails at that primitive's tests rather than as silent drift at
7067 /// either struct-level arm.
7068 #[test]
7069 fn ephemeral_missing_condition_kinds_triad_delegates_to_slice_missing_kinds() {
7070 // Empty ephemeral spec — every arm returns ConditionKind::ALL.
7071 let empty = empty_ephemeral();
7072 let all_kinds = ConditionKind::ALL.to_vec();
7073 assert_eq!(
7074 empty.missing_precondition_kinds(),
7075 all_kinds,
7076 "empty ephemeral spec must return ConditionKind::ALL on missing_precondition_kinds",
7077 );
7078 assert_eq!(
7079 empty.missing_postcondition_kinds(),
7080 all_kinds,
7081 "empty ephemeral spec must return ConditionKind::ALL on missing_postcondition_kinds",
7082 );
7083 assert_eq!(
7084 empty.missing_condition_kinds(),
7085 all_kinds,
7086 "empty ephemeral spec must return ConditionKind::ALL on missing_condition_kinds",
7087 );
7088
7089 for pre_kind in ConditionKind::ALL {
7090 for post_kind in ConditionKind::ALL {
7091 let mut spec = empty_ephemeral();
7092 spec.preconditions.push(cond(pre_kind));
7093 spec.postconditions.push(cond(post_kind));
7094
7095 assert_eq!(
7096 spec.missing_precondition_kinds(),
7097 spec.preconditions.missing_kinds(),
7098 "EphemeralSpec::missing_precondition_kinds must delegate verbatim to \
7099 preconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7100 );
7101 assert_eq!(
7102 spec.missing_postcondition_kinds(),
7103 spec.postconditions.missing_kinds(),
7104 "EphemeralSpec::missing_postcondition_kinds must delegate verbatim to \
7105 postconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7106 );
7107 // Union: a kind is missing from the union iff it is
7108 // missing from BOTH half-slices (SET-INTERSECTION).
7109 let expected_union: Vec<_> = ConditionKind::ALL
7110 .into_iter()
7111 .filter(|k| pre_kind != *k && post_kind != *k)
7112 .collect();
7113 assert_eq!(
7114 spec.missing_condition_kinds(),
7115 expected_union,
7116 "EphemeralSpec::missing_condition_kinds must equal ConditionKind::ALL-ordered \
7117 set-INTERSECTION of the two half-slice missing-sets for pre={pre_kind:?} post={post_kind:?}",
7118 );
7119 // Partition invariant (distinct ∪ missing == ALL, disjoint).
7120 let distinct = spec.distinct_condition_kinds();
7121 let missing = spec.missing_condition_kinds();
7122 for kind in ConditionKind::ALL {
7123 assert!(
7124 distinct.contains(&kind) ^ missing.contains(&kind),
7125 "EphemeralSpec (distinct, missing) partition violated on {kind:?} for pre={pre_kind:?} post={post_kind:?}",
7126 );
7127 }
7128 assert_eq!(
7129 distinct.len() + missing.len(),
7130 ConditionKind::ALL.len(),
7131 "EphemeralSpec (distinct, missing) cardinality partition drift for pre={pre_kind:?} post={post_kind:?}",
7132 );
7133 }
7134 }
7135 }
7136
7137 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-kind-count triad)
7138 /// — the three `missing_*_kind_count` methods on [`EphemeralSpec`]
7139 /// delegate to the slice-level substrate primitive
7140 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
7141 /// the two `Vec<Condition>` slots and compose the union scalar via
7142 /// `ConditionKind::ALL.iter().filter(|k|
7143 /// !has_condition_kind(**k)).count()`. Sweep
7144 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
7145 /// `missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count`
7146 /// on the point-domain [`crate::boundary::Boundary`] surface —
7147 /// both peers compose against the SAME slice-level substrate
7148 /// primitive so a regression at the per-slice negated closed-set
7149 /// walk fails at that primitive's tests rather than as silent drift
7150 /// at either struct-level scalar-cardinality arm. Also pins the
7151 /// scalar-partition invariant `distinct_kind_count +
7152 /// missing_kind_count == ConditionKind::ALL.len()` per arrangement.
7153 #[test]
7154 fn ephemeral_missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count() {
7155 // Empty ephemeral spec — every arm returns ConditionKind::ALL.len().
7156 let empty = empty_ephemeral();
7157 let total = ConditionKind::ALL.len();
7158 assert_eq!(
7159 empty.missing_precondition_kind_count(),
7160 total,
7161 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_precondition_kind_count",
7162 );
7163 assert_eq!(
7164 empty.missing_postcondition_kind_count(),
7165 total,
7166 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_postcondition_kind_count",
7167 );
7168 assert_eq!(
7169 empty.missing_condition_kind_count(),
7170 total,
7171 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_condition_kind_count",
7172 );
7173
7174 for pre_kind in ConditionKind::ALL {
7175 for post_kind in ConditionKind::ALL {
7176 let mut spec = empty_ephemeral();
7177 spec.preconditions.push(cond(pre_kind));
7178 spec.postconditions.push(cond(post_kind));
7179
7180 // Half-slice arms delegate byte-for-byte to the slice
7181 // substrate primitive.
7182 assert_eq!(
7183 spec.missing_precondition_kind_count(),
7184 spec.preconditions.missing_kind_count(),
7185 "EphemeralSpec::missing_precondition_kind_count must delegate verbatim to \
7186 preconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7187 );
7188 assert_eq!(
7189 spec.missing_precondition_kind_count(),
7190 spec.missing_precondition_kinds().len(),
7191 "EphemeralSpec::missing_precondition_kind_count must equal \
7192 missing_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7193 );
7194 assert_eq!(
7195 spec.missing_postcondition_kind_count(),
7196 spec.postconditions.missing_kind_count(),
7197 "EphemeralSpec::missing_postcondition_kind_count must delegate verbatim to \
7198 postconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7199 );
7200 assert_eq!(
7201 spec.missing_postcondition_kind_count(),
7202 spec.missing_postcondition_kinds().len(),
7203 "EphemeralSpec::missing_postcondition_kind_count must equal \
7204 missing_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7205 );
7206 // Union arm equals missing_condition_kinds().len().
7207 assert_eq!(
7208 spec.missing_condition_kind_count(),
7209 spec.missing_condition_kinds().len(),
7210 "EphemeralSpec::missing_condition_kind_count must equal \
7211 missing_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7212 );
7213 // Scalar-partition invariant: distinct + missing == ALL.
7214 assert_eq!(
7215 spec.distinct_condition_kind_count() + spec.missing_condition_kind_count(),
7216 ConditionKind::ALL.len(),
7217 "EphemeralSpec (distinct, missing) scalar partition drift for pre={pre_kind:?} post={post_kind:?}",
7218 );
7219 }
7220 }
7221 }
7222
7223 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-distinct-kind
7224 /// triad) — the three `first_distinct_*_kind` methods on
7225 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7226 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] over
7227 /// the two `Vec<Condition>` slots and compose the union via
7228 /// `ConditionKind::ALL.iter().copied().find(|k|
7229 /// has_condition_kind(*k))`. Byte-for-byte peer of
7230 /// `first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind`
7231 /// on the point-domain [`crate::boundary::Boundary`] surface — both
7232 /// peers compose against the SAME slice-level substrate primitive
7233 /// so a regression at the per-slice short-circuit walk fails at
7234 /// that primitive's tests rather than as silent drift at either
7235 /// struct-level earliest-element arm.
7236 #[test]
7237 fn ephemeral_first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind() {
7238 // Empty ephemeral spec — every arm returns None.
7239 let empty = empty_ephemeral();
7240 assert_eq!(
7241 empty.first_distinct_precondition_kind(),
7242 None,
7243 "empty ephemeral spec must return None on first_distinct_precondition_kind",
7244 );
7245 assert_eq!(
7246 empty.first_distinct_postcondition_kind(),
7247 None,
7248 "empty ephemeral spec must return None on first_distinct_postcondition_kind",
7249 );
7250 assert_eq!(
7251 empty.first_distinct_condition_kind(),
7252 None,
7253 "empty ephemeral spec must return None on first_distinct_condition_kind",
7254 );
7255
7256 for pre_kind in ConditionKind::ALL {
7257 for post_kind in ConditionKind::ALL {
7258 let mut spec = empty_ephemeral();
7259 spec.preconditions.push(cond(pre_kind));
7260 spec.postconditions.push(cond(post_kind));
7261
7262 assert_eq!(
7263 spec.first_distinct_precondition_kind(),
7264 spec.preconditions.first_distinct_kind(),
7265 "EphemeralSpec::first_distinct_precondition_kind must delegate verbatim to \
7266 preconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7267 );
7268 assert_eq!(
7269 spec.first_distinct_precondition_kind(),
7270 spec.distinct_precondition_kinds().first().copied(),
7271 "EphemeralSpec::first_distinct_precondition_kind must equal \
7272 distinct_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7273 );
7274 assert_eq!(
7275 spec.first_distinct_postcondition_kind(),
7276 spec.postconditions.first_distinct_kind(),
7277 "EphemeralSpec::first_distinct_postcondition_kind must delegate verbatim to \
7278 postconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7279 );
7280 assert_eq!(
7281 spec.first_distinct_postcondition_kind(),
7282 spec.distinct_postcondition_kinds().first().copied(),
7283 "EphemeralSpec::first_distinct_postcondition_kind must equal \
7284 distinct_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7285 );
7286 let expected_union = ConditionKind::ALL
7287 .into_iter()
7288 .find(|k| pre_kind == *k || post_kind == *k);
7289 assert_eq!(
7290 spec.first_distinct_condition_kind(),
7291 expected_union,
7292 "EphemeralSpec::first_distinct_condition_kind must equal earliest ALL entry \
7293 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7294 );
7295 assert_eq!(
7296 spec.first_distinct_condition_kind(),
7297 spec.distinct_condition_kinds().first().copied(),
7298 "EphemeralSpec::first_distinct_condition_kind must equal \
7299 distinct_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7300 );
7301 }
7302 }
7303 }
7304
7305 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-missing-kind triad)
7306 /// — the three `first_missing_*_kind` methods on [`EphemeralSpec`]
7307 /// delegate to the slice-level substrate primitive
7308 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`] over
7309 /// the two `Vec<Condition>` slots and compose the union via
7310 /// `ConditionKind::ALL.iter().copied().find(|k|
7311 /// !has_condition_kind(*k))`. Byte-for-byte peer of
7312 /// `first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind`
7313 /// on the point-domain [`crate::boundary::Boundary`] surface.
7314 #[test]
7315 fn ephemeral_first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind() {
7316 // Empty ephemeral spec — every arm returns Some(ConditionKind::ALL[0]).
7317 let empty = empty_ephemeral();
7318 let first = Some(ConditionKind::ALL[0]);
7319 assert_eq!(
7320 empty.first_missing_precondition_kind(),
7321 first,
7322 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_precondition_kind",
7323 );
7324 assert_eq!(
7325 empty.first_missing_postcondition_kind(),
7326 first,
7327 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_postcondition_kind",
7328 );
7329 assert_eq!(
7330 empty.first_missing_condition_kind(),
7331 first,
7332 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_condition_kind",
7333 );
7334
7335 for pre_kind in ConditionKind::ALL {
7336 for post_kind in ConditionKind::ALL {
7337 let mut spec = empty_ephemeral();
7338 spec.preconditions.push(cond(pre_kind));
7339 spec.postconditions.push(cond(post_kind));
7340
7341 assert_eq!(
7342 spec.first_missing_precondition_kind(),
7343 spec.preconditions.first_missing_kind(),
7344 "EphemeralSpec::first_missing_precondition_kind must delegate verbatim to \
7345 preconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7346 );
7347 assert_eq!(
7348 spec.first_missing_precondition_kind(),
7349 spec.missing_precondition_kinds().first().copied(),
7350 "EphemeralSpec::first_missing_precondition_kind must equal \
7351 missing_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7352 );
7353 assert_eq!(
7354 spec.first_missing_postcondition_kind(),
7355 spec.postconditions.first_missing_kind(),
7356 "EphemeralSpec::first_missing_postcondition_kind must delegate verbatim to \
7357 postconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7358 );
7359 assert_eq!(
7360 spec.first_missing_postcondition_kind(),
7361 spec.missing_postcondition_kinds().first().copied(),
7362 "EphemeralSpec::first_missing_postcondition_kind must equal \
7363 missing_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7364 );
7365 let expected_union = ConditionKind::ALL
7366 .into_iter()
7367 .find(|k| pre_kind != *k && post_kind != *k);
7368 assert_eq!(
7369 spec.first_missing_condition_kind(),
7370 expected_union,
7371 "EphemeralSpec::first_missing_condition_kind must equal earliest ALL entry \
7372 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7373 );
7374 assert_eq!(
7375 spec.first_missing_condition_kind(),
7376 spec.missing_condition_kinds().first().copied(),
7377 "EphemeralSpec::first_missing_condition_kind must equal \
7378 missing_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
7379 );
7380 }
7381 }
7382 }
7383
7384 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-distinct-kind
7385 /// triad) — the three `last_distinct_*_kind` methods on
7386 /// [`EphemeralSpec`] delegate to the slice-level substrate
7387 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
7388 /// over the two `Vec<Condition>` slots and compose the union via
7389 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
7390 /// has_condition_kind(*k))`. Byte-for-byte peer of
7391 /// `last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind`
7392 /// on the point-domain [`crate::boundary::Boundary`] surface —
7393 /// both peers compose against the SAME slice-level substrate
7394 /// primitive so a regression at the per-slice REVERSED short-
7395 /// circuit walk fails at that primitive's tests rather than as
7396 /// silent drift at either struct-level latest-element arm.
7397 #[test]
7398 fn ephemeral_last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind() {
7399 // Empty ephemeral spec — every arm returns None.
7400 let empty = empty_ephemeral();
7401 assert_eq!(
7402 empty.last_distinct_precondition_kind(),
7403 None,
7404 "empty ephemeral spec must return None on last_distinct_precondition_kind",
7405 );
7406 assert_eq!(
7407 empty.last_distinct_postcondition_kind(),
7408 None,
7409 "empty ephemeral spec must return None on last_distinct_postcondition_kind",
7410 );
7411 assert_eq!(
7412 empty.last_distinct_condition_kind(),
7413 None,
7414 "empty ephemeral spec must return None on last_distinct_condition_kind",
7415 );
7416
7417 for pre_kind in ConditionKind::ALL {
7418 for post_kind in ConditionKind::ALL {
7419 let mut spec = empty_ephemeral();
7420 spec.preconditions.push(cond(pre_kind));
7421 spec.postconditions.push(cond(post_kind));
7422
7423 assert_eq!(
7424 spec.last_distinct_precondition_kind(),
7425 spec.preconditions.last_distinct_kind(),
7426 "EphemeralSpec::last_distinct_precondition_kind must delegate verbatim to \
7427 preconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7428 );
7429 assert_eq!(
7430 spec.last_distinct_precondition_kind(),
7431 spec.distinct_precondition_kinds().last().copied(),
7432 "EphemeralSpec::last_distinct_precondition_kind must equal \
7433 distinct_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7434 );
7435 assert_eq!(
7436 spec.last_distinct_postcondition_kind(),
7437 spec.postconditions.last_distinct_kind(),
7438 "EphemeralSpec::last_distinct_postcondition_kind must delegate verbatim to \
7439 postconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
7440 );
7441 assert_eq!(
7442 spec.last_distinct_postcondition_kind(),
7443 spec.distinct_postcondition_kinds().last().copied(),
7444 "EphemeralSpec::last_distinct_postcondition_kind must equal \
7445 distinct_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7446 );
7447 let expected_union = ConditionKind::ALL
7448 .into_iter()
7449 .rev()
7450 .find(|k| pre_kind == *k || post_kind == *k);
7451 assert_eq!(
7452 spec.last_distinct_condition_kind(),
7453 expected_union,
7454 "EphemeralSpec::last_distinct_condition_kind must equal latest ALL entry \
7455 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7456 );
7457 assert_eq!(
7458 spec.last_distinct_condition_kind(),
7459 spec.distinct_condition_kinds().last().copied(),
7460 "EphemeralSpec::last_distinct_condition_kind must equal \
7461 distinct_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7462 );
7463 }
7464 }
7465 }
7466
7467 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-missing-kind triad)
7468 /// — the three `last_missing_*_kind` methods on [`EphemeralSpec`]
7469 /// delegate to the slice-level substrate primitive
7470 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] over
7471 /// the two `Vec<Condition>` slots and compose the union via
7472 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
7473 /// !has_condition_kind(*k))`. Byte-for-byte peer of
7474 /// `last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind`
7475 /// on the point-domain [`crate::boundary::Boundary`] surface.
7476 #[test]
7477 fn ephemeral_last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind() {
7478 // Empty ephemeral spec — every arm returns Some(*ConditionKind::ALL.last().unwrap()).
7479 let empty = empty_ephemeral();
7480 let last = ConditionKind::ALL.last().copied();
7481 assert_eq!(
7482 empty.last_missing_precondition_kind(),
7483 last,
7484 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_precondition_kind",
7485 );
7486 assert_eq!(
7487 empty.last_missing_postcondition_kind(),
7488 last,
7489 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_postcondition_kind",
7490 );
7491 assert_eq!(
7492 empty.last_missing_condition_kind(),
7493 last,
7494 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_condition_kind",
7495 );
7496
7497 for pre_kind in ConditionKind::ALL {
7498 for post_kind in ConditionKind::ALL {
7499 let mut spec = empty_ephemeral();
7500 spec.preconditions.push(cond(pre_kind));
7501 spec.postconditions.push(cond(post_kind));
7502
7503 assert_eq!(
7504 spec.last_missing_precondition_kind(),
7505 spec.preconditions.last_missing_kind(),
7506 "EphemeralSpec::last_missing_precondition_kind must delegate verbatim to \
7507 preconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7508 );
7509 assert_eq!(
7510 spec.last_missing_precondition_kind(),
7511 spec.missing_precondition_kinds().last().copied(),
7512 "EphemeralSpec::last_missing_precondition_kind must equal \
7513 missing_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7514 );
7515 assert_eq!(
7516 spec.last_missing_postcondition_kind(),
7517 spec.postconditions.last_missing_kind(),
7518 "EphemeralSpec::last_missing_postcondition_kind must delegate verbatim to \
7519 postconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
7520 );
7521 assert_eq!(
7522 spec.last_missing_postcondition_kind(),
7523 spec.missing_postcondition_kinds().last().copied(),
7524 "EphemeralSpec::last_missing_postcondition_kind must equal \
7525 missing_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7526 );
7527 let expected_union = ConditionKind::ALL
7528 .into_iter()
7529 .rev()
7530 .find(|k| pre_kind != *k && post_kind != *k);
7531 assert_eq!(
7532 spec.last_missing_condition_kind(),
7533 expected_union,
7534 "EphemeralSpec::last_missing_condition_kind must equal latest ALL entry \
7535 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
7536 );
7537 assert_eq!(
7538 spec.last_missing_condition_kind(),
7539 spec.missing_condition_kinds().last().copied(),
7540 "EphemeralSpec::last_missing_condition_kind must equal \
7541 missing_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
7542 );
7543 }
7544 }
7545 }
7546
7547 // ── assert_slice_refinement_composition_laws — mirror invocations ──
7548 //
7549 // The substrate testkit primitive
7550 // [`crate::boundary::assert_slice_refinement_composition_laws`]
7551 // pins the FOUR composition laws that bind the
7552 // [`crate::boundary::ConditionSliceExt`] refinement algebra
7553 // (find ↔ iter, count ↔ iter, has ↔ find, has ↔ count) at ONE
7554 // call site per authored arrangement, sweeping
7555 // [`ConditionKind::ALL`]. The two ephemeral-surface tests below
7556 // dispatch the primitive against the two `Vec<Condition>` slots
7557 // ([`EphemeralSpec::preconditions`] +
7558 // [`EphemeralSpec::postconditions`]) authored through the
7559 // ephemeral-surface test-fixture — byte-for-byte peer of the
7560 // point-surface `slice_refinement_composition_laws_hold_across_authored_arrangements`
7561 // + `slice_refinement_composition_laws_hold_on_interleaved_duplicates`
7562 // pins on the [`crate::boundary::Boundary`] surface. Two-surface
7563 // parity contract: the substrate primitive holds on every slice
7564 // reachable through either the point-surface `.preconditions` /
7565 // `.postconditions` fields OR the ephemeral-surface's
7566 // eponymous field pair.
7567
7568 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate
7569 /// primitive [`assert_slice_refinement_composition_laws`] holds
7570 /// on both [`EphemeralSpec::preconditions`] and
7571 /// [`EphemeralSpec::postconditions`] slices for every populated-
7572 /// pair authored through the ephemeral-surface test-fixture.
7573 /// Byte-for-byte peer of
7574 /// `slice_refinement_composition_laws_hold_across_authored_arrangements`
7575 /// on the point surface.
7576 #[test]
7577 fn ephemeral_slice_refinement_composition_laws_hold_across_authored_arrangements() {
7578 let empty = empty_ephemeral();
7579 assert_slice_refinement_composition_laws(empty.preconditions.as_slice());
7580 assert_slice_refinement_composition_laws(empty.postconditions.as_slice());
7581
7582 for pre_kind in ConditionKind::ALL {
7583 for post_kind in ConditionKind::ALL {
7584 let mut spec = empty_ephemeral();
7585 spec.preconditions.push(cond(pre_kind));
7586 spec.postconditions.push(cond(post_kind));
7587 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
7588 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
7589 }
7590 }
7591
7592 for populated in ConditionKind::ALL {
7593 let mut spec = empty_ephemeral();
7594 spec.preconditions.push(cond(populated));
7595 spec.preconditions.push(cond(populated));
7596 spec.preconditions.push(cond(populated));
7597 spec.postconditions.push(cond(populated));
7598 spec.postconditions.push(cond(populated));
7599 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
7600 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
7601 }
7602 }
7603
7604 // ── assert_surface_union_composition_laws — ephemeral surface ────
7605 //
7606 // The substrate testkit macro
7607 // [`crate::assert_surface_union_composition_laws`] pins the FOUR
7608 // union composition laws (has: OR, find: or_else, iter: chain,
7609 // count: SUM) that bind the (pre, post, union) refinement triads
7610 // on the [`EphemeralSpec`] sugar-surface at ONE call site per
7611 // authored arrangement, sweeping [`ConditionKind::ALL`]. Byte-for-
7612 // byte peer of the point-surface
7613 // `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
7614 // / `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
7615 // pins on the [`crate::boundary::Boundary`] surface — the two-
7616 // surface parity contract binds every downstream `condition-<K>`
7617 // / `precondition-<K>` / `postcondition-<K>` require-tag classifier
7618 // on either surface to the SAME four union-composition operators
7619 // through ONE substrate primitive rather than through per-surface
7620 // author-time re-authored sweeps.
7621
7622 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate macro
7623 /// [`crate::assert_surface_union_composition_laws`] passes on
7624 /// [`EphemeralSpec`] for the four canonical authored arrangements
7625 /// (empty spec, precondition-only populated, postcondition-only
7626 /// populated, dual-populated sweep over `ALL × ALL`). Byte-for-byte
7627 /// peer of the point-surface
7628 /// `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
7629 /// pin — the two-surface parity contract binds every union
7630 /// composition law on both surfaces to the SAME substrate
7631 /// primitive.
7632 #[test]
7633 fn ephemeral_surface_union_composition_laws_hold_across_authored_arrangements() {
7634 let empty = empty_ephemeral();
7635 crate::assert_surface_union_composition_laws!(empty);
7636
7637 for populated in ConditionKind::ALL {
7638 let mut pre_only = empty_ephemeral();
7639 pre_only.preconditions.push(cond(populated));
7640 crate::assert_surface_union_composition_laws!(pre_only);
7641
7642 let mut post_only = empty_ephemeral();
7643 post_only.postconditions.push(cond(populated));
7644 crate::assert_surface_union_composition_laws!(post_only);
7645 }
7646
7647 for pre_kind in ConditionKind::ALL {
7648 for post_kind in ConditionKind::ALL {
7649 let mut dual = empty_ephemeral();
7650 dual.preconditions.push(cond(pre_kind));
7651 dual.postconditions.push(cond(post_kind));
7652 crate::assert_surface_union_composition_laws!(dual);
7653 }
7654 }
7655 }
7656
7657 /// SUBSTRATE PANEL pin (ephemeral surface, params-distinguishable
7658 /// duplicates) — the substrate macro holds on an [`EphemeralSpec`]
7659 /// whose two half-slices each carry duplicates of the same kind at
7660 /// multiple positions interleaved with a distinct kind. Byte-for-
7661 /// byte peer of the point-surface
7662 /// `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
7663 /// pin — the non-degenerate composition of every union arm on the
7664 /// sugar-surface binds against the SAME four monoid operators as
7665 /// the point-surface peer. A regression on the ephemeral surface
7666 /// only that (a) collapsed `find`'s `or_else` to `and_then`, (b)
7667 /// collapsed `iter`'s `chain` to `zip`, or (c) collapsed `count`'s
7668 /// SUM to `max` surfaces HERE, breaking two-surface parity.
7669 #[test]
7670 fn ephemeral_surface_union_composition_laws_hold_on_interleaved_duplicates() {
7671 let mut spec = empty_ephemeral();
7672 spec.preconditions.push(Condition {
7673 kind: ConditionKind::ClosedLoopAuth,
7674 params: serde_json::json!({ "side": "pre-1" }),
7675 });
7676 spec.preconditions.push(Condition {
7677 kind: ConditionKind::PromQL,
7678 params: serde_json::json!({ "query": "up" }),
7679 });
7680 spec.preconditions.push(Condition {
7681 kind: ConditionKind::ClosedLoopAuth,
7682 params: serde_json::json!({ "side": "pre-2" }),
7683 });
7684 spec.postconditions.push(Condition {
7685 kind: ConditionKind::PromQL,
7686 params: serde_json::json!({ "query": "healthy" }),
7687 });
7688 spec.postconditions.push(Condition {
7689 kind: ConditionKind::ClosedLoopAuth,
7690 params: serde_json::json!({ "side": "post-1" }),
7691 });
7692 crate::assert_surface_union_composition_laws!(spec);
7693 }
7694
7695 #[test]
7696 fn from_impl_clears_other_intent_variants() {
7697 // Even if someone constructs an EphemeralSpec by hand and the
7698 // resulting ProcessSpec is later mutated, the From bridge sets
7699 // every non-Aplicacao slot to None explicitly.
7700 let e = EphemeralSpec {
7701 aplicacao: demo_overlay(),
7702 ttl: "10m".into(),
7703 teardown: TeardownPolicy::Never,
7704 max_concurrent: 0,
7705 postconditions: vec![],
7706 preconditions: vec![],
7707 verify_timeout: None,
7708 classification: None,
7709 parent: Some("seph.1".into()),
7710 exports: vec![],
7711 routing: None,
7712 };
7713 let ps: ProcessSpec = e.into();
7714 assert!(ps.intent.nix.is_none());
7715 assert!(ps.intent.flux.is_none());
7716 assert!(ps.intent.lisp.is_none());
7717 assert!(ps.intent.container.is_none());
7718 assert!(ps.intent.guest.is_none());
7719 assert!(ps.intent.aplicacao.is_some());
7720 assert_eq!(ps.identity.parent.as_deref(), Some("seph.1"));
7721 }
7722
7723 // ── EphemeralSpec::has_teardown_policy substrate pins ────────────
7724 //
7725 // Fail-before-pass-after granularity:
7726 // `EphemeralSpec::has_teardown_policy` did not exist before this
7727 // commit — the (`self.teardown == kind`) scalar-carrier probe on
7728 // the sugar-surface [`EphemeralSpec`] lived only implicitly via
7729 // hand-authored comparisons at potential future call sites, with
7730 // no analogue to the peer
7731 // [`crate::lifetime::EphemeralLifetime::has_teardown_policy`] on
7732 // the point-surface carrier. The lift adds the peer inherent
7733 // method on the [`EphemeralSpec`] sugar-surface so both surfaces'
7734 // `teardown-policy-<kind>` require-tag families in
7735 // `tatara-reconciler::bin::tatara-check` compose against the SAME
7736 // scalar `==` shape in lockstep. A regression that (a) hard-coded
7737 // the arm to a single kind, (b) inverted the closed-set match
7738 // (silently returning `true` on non-matching variants), or (c)
7739 // probed the wrong slot (a stray comparison against `ttl` /
7740 // `max_concurrent`) fails HERE at the substrate primitive rather
7741 // than as silent operator-facing drift at the ephemeral
7742 // `teardown-policy-<kind>` require-tag surface.
7743
7744 /// STORED-slot pin — an ephemeral spec that carries a given
7745 /// [`TeardownPolicy`] returns `true` for that kind, `false` for
7746 /// every other variant. Sweep the [`TeardownPolicy::ALL`] × ALL
7747 /// cross so a regression that hard-coded the arm to a single kind
7748 /// or wired the closure to a fixed unrelated field fails HERE at
7749 /// the substrate primitive. Byte-for-byte peer of
7750 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_returns_true_iff_variant_matches`]
7751 /// on the point-surface [`crate::lifetime::EphemeralLifetime`]
7752 /// carrier — the two surfaces publish identical `==` scalar
7753 /// semantics on their respective `teardown` / `teardown_policy`
7754 /// slots.
7755 #[test]
7756 fn has_teardown_policy_returns_true_iff_ephemeral_teardown_matches_per_kind() {
7757 for populated in TeardownPolicy::ALL {
7758 let mut spec = empty_ephemeral();
7759 spec.teardown = populated;
7760 for query in TeardownPolicy::ALL {
7761 let expected = query == populated;
7762 assert_eq!(
7763 spec.has_teardown_policy(query),
7764 expected,
7765 "ephemeral teardown={populated:?}: query {query:?} drifted",
7766 );
7767 }
7768 }
7769 }
7770
7771 /// DEFAULT-SLOT pin — an [`EphemeralSpec`] whose `teardown` slot
7772 /// is [`TeardownPolicy::default`] (`Always`) returns `true` for
7773 /// `Always` and `false` for every other variant. The
7774 /// (required-scalar-child) corner has no absent state — a
7775 /// hand-authored spec that omits `:teardown` from the
7776 /// `(defephemeral …)` form IS configured for `Always`, and this
7777 /// pin locks the corner's default-arm short-circuit as identical
7778 /// to the (Option-parent × defaulted-scalar-child) corner's
7779 /// reachable arm on the point surface (both return `true` on
7780 /// `Always` only). Byte-for-byte peer of
7781 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_default_probes_always_only`]
7782 /// on the point-surface carrier.
7783 #[test]
7784 fn has_teardown_policy_default_probes_always_only_on_ephemeral() {
7785 let spec = EphemeralSpec {
7786 teardown: TeardownPolicy::default(),
7787 ..empty_ephemeral()
7788 };
7789 for kind in TeardownPolicy::ALL {
7790 let expected = kind == TeardownPolicy::Always;
7791 assert_eq!(
7792 spec.has_teardown_policy(kind),
7793 expected,
7794 "default ephemeral (teardown=Always) baseline: query {kind:?} must be {expected}",
7795 );
7796 }
7797 }
7798
7799 // ── derived-bool-predicate presence probe on EphemeralSpec ×
7800 // TeardownPolicy × ProcessPhase ──
7801 //
7802 // Fail-before-pass-after granularity:
7803 // [`EphemeralSpec::has_teardown_firing_on`] did not exist before
7804 // this commit — the ephemeral sugar surface's require-tag algebra
7805 // discriminated the teardown axis only by the RAW authored variant
7806 // (via `teardown-policy-<kind>`), never by the derived
7807 // [`ProcessPhase`] transition the stored policy fires on
7808 // ([`TeardownPolicy::should_teardown_on`]). Post-lift the shape
7809 // lives at ONE inherent method that byte-for-byte parallels
7810 // [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
7811 // on the point-surface carrier, and both surfaces' require-tag
7812 // classifiers publish a symmetric `teardown-fires-on-<phase>`
7813 // family through the SAME predicate.
7814
7815 /// TRUTH-TABLE DIAGONAL — for every [`TeardownPolicy`] variant,
7816 /// an [`EphemeralSpec`] whose `teardown` slot is set to that
7817 /// variant returns `has_teardown_firing_on(phase)` in agreement
7818 /// with [`TeardownPolicy::should_teardown_on`] for every
7819 /// [`ProcessPhase`] variant. Sweep [`TeardownPolicy::ALL`] ×
7820 /// [`ProcessPhase::ALL`] full cross so a regression that hard-
7821 /// coded the arm to a single policy, wired to the wrong field, or
7822 /// inverted the predicate direction fails HERE at the substrate
7823 /// primitive on the sugar surface (byte-for-byte peer of
7824 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase`]
7825 /// on the point carrier).
7826 #[test]
7827 fn has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase_on_ephemeral() {
7828 for populated in TeardownPolicy::ALL {
7829 let spec = EphemeralSpec {
7830 teardown: populated,
7831 ..empty_ephemeral()
7832 };
7833 for phase in ProcessPhase::ALL {
7834 assert_eq!(
7835 spec.has_teardown_firing_on(phase),
7836 populated.should_teardown_on(phase),
7837 "teardown={populated:?}, phase={phase:?}: predicate drift from \
7838 should_teardown_on projection",
7839 );
7840 }
7841 }
7842 }
7843
7844 /// TWO-SURFACE PARITY PIN — for every [`TeardownPolicy`] variant
7845 /// and every [`ProcessPhase`] variant, the sugar-surface probe
7846 /// and the lowered point-surface probe agree. The `EphemeralSpec
7847 /// → ProcessSpec` lowering routes the stored `teardown` slot
7848 /// through the SAME [`TeardownPolicy::should_teardown_on`]
7849 /// projection on both sides, so the sugar caller and the lowered
7850 /// caller can never disagree — a regression that (a) drifted
7851 /// [`Self::teardown`] between sugar and lowered, (b) rewired
7852 /// either probe body to bypass the shared substrate primitive, or
7853 /// (c) skewed the (policy, phase) truth table between the two
7854 /// surfaces fails HERE at the two-surface boundary rather than at
7855 /// the operator-facing require-tag classifier.
7856 #[test]
7857 fn has_teardown_firing_on_matches_point_peer_through_lowered_teardown_policy() {
7858 for populated in TeardownPolicy::ALL {
7859 let sugar = EphemeralSpec {
7860 teardown: populated,
7861 ..empty_ephemeral()
7862 };
7863 let lowered: ProcessSpec = sugar.clone().into();
7864 let lowered_eph = lowered
7865 .lifetime
7866 .resolved_ephemeral()
7867 .expect("lowered spec must be ephemeral");
7868 for phase in ProcessPhase::ALL {
7869 assert_eq!(
7870 sugar.has_teardown_firing_on(phase),
7871 lowered_eph.has_teardown_firing_on(phase),
7872 "sugar-vs-lowered predicate drift for teardown={populated:?}, phase={phase:?}",
7873 );
7874 }
7875 }
7876 }
7877
7878 // ── EphemeralSpec::resolved_classification + has_point_type pins ─────
7879 //
7880 // Fail-before-pass-after granularity: `resolved_classification` and
7881 // `has_point_type` did not exist pre-lift on `impl EphemeralSpec` — every
7882 // caller wanting the resolved [`Classification`] on the ephemeral
7883 // sugar-surface (currently zero; future ephemeral-surface classification-
7884 // axis require-tag families in `tatara-reconciler::bin::tatara-check`,
7885 // typed audit hooks, documentation generators listing the ephemeral
7886 // surface's known require-tag vocabulary) restated the two-line
7887 // `self.classification.as_ref().unwrap_or(&default_ephemeral_class())`
7888 // resolver body at their site. Post-lift both callers of the resolver
7889 // (`Self::has_point_type` and every future classification-axis peer)
7890 // route through ONE inherent method that shares the fill-through with
7891 // the sibling `From<EphemeralSpec> for ProcessSpec` lowering
7892 // byte-for-byte. A regression that (a) inverted the arm (`Some` filled
7893 // through the default), (b) drifted the default from the sibling
7894 // primitive `Classification::gate_compute()`, or (c) shifted the
7895 // `Cow<'_, Classification>` return shape (a stray `.clone()` on the
7896 // populated arm) fails HERE at the substrate primitive rather than as
7897 // silent operator-facing drift at a future
7898 // `point-type-<kind>` ephemeral require-tag surface.
7899
7900 /// AUTHORED-slot pin — an [`EphemeralSpec`] whose
7901 /// [`EphemeralSpec::classification`] slot names a concrete
7902 /// [`Classification`] returns [`Cow::Borrowed`] pointing at that
7903 /// authored value from [`Self::resolved_classification`]. Pins the
7904 /// populated-arm zero-allocation contract: a caller reading past
7905 /// the resolver sees the SAME byte address the operator authored,
7906 /// so the resolver does not silently clone the authored slot on
7907 /// the populated arm.
7908 #[test]
7909 fn resolved_classification_borrows_authored_slot() {
7910 let mut spec = empty_ephemeral();
7911 let mut authored = Classification::gate_compute();
7912 authored.point_type = ConvergencePointType::Fork;
7913 spec.classification = Some(authored.clone());
7914 let resolved = spec.resolved_classification();
7915 assert!(matches!(resolved, Cow::Borrowed(_)));
7916 assert_eq!(&*resolved, &authored);
7917 }
7918
7919 /// ABSENT-slot pin — an [`EphemeralSpec`] whose
7920 /// [`EphemeralSpec::classification`] slot is `None` returns
7921 /// [`Cow::Owned`] with the SAME value the sibling
7922 /// [`default_ephemeral_class`] baseline produces. Pins the
7923 /// two-surface parity contract with `From<EphemeralSpec> for
7924 /// ProcessSpec`: both sites fill through the SAME baseline on
7925 /// `None`, so the ephemeral require-tag surface's future
7926 /// `point-type-<kind>` family reads identically on the authored
7927 /// spec and on the mechanically lowered `ProcessSpec`.
7928 #[test]
7929 fn resolved_classification_fills_default_on_absent_slot() {
7930 let spec = empty_ephemeral();
7931 assert!(spec.classification.is_none());
7932 let resolved = spec.resolved_classification();
7933 assert!(matches!(resolved, Cow::Owned(_)));
7934 assert_eq!(&*resolved, &default_ephemeral_class());
7935 }
7936
7937 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7938 /// [`EphemeralSpec::classification`] slot names a concrete
7939 /// [`Classification`] returns `true` from
7940 /// [`Self::has_point_type`] on the authored
7941 /// [`ConvergencePointType`] slot and `false` for every other
7942 /// variant. Sweep the [`ConvergencePointType::ALL`] × ALL cross so
7943 /// a regression that hard-coded the arm to a single kind or wired
7944 /// the closure to a fixed unrelated slot fails HERE at the
7945 /// substrate primitive. Byte-for-byte peer of
7946 /// [`crate::classification::tests`]'s point-surface
7947 /// [`Classification::has_point_type`] populated-slot sweep on the
7948 /// SAME closed-set primitive.
7949 #[test]
7950 fn has_point_type_returns_true_iff_authored_classification_matches_per_kind() {
7951 for populated in ConvergencePointType::ALL {
7952 let mut classification = Classification::gate_compute();
7953 classification.point_type = populated;
7954 let mut spec = empty_ephemeral();
7955 spec.classification = Some(classification);
7956 for query in ConvergencePointType::ALL {
7957 let expected = query == populated;
7958 assert_eq!(
7959 spec.has_point_type(query),
7960 expected,
7961 "ephemeral classification.point_type={populated:?}: query {query:?} drifted",
7962 );
7963 }
7964 }
7965 }
7966
7967 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7968 /// [`EphemeralSpec::classification`] slot is `None` returns
7969 /// `true` from [`Self::has_point_type`] on
7970 /// [`ConvergencePointType::Gate`] (the `default_ephemeral_class`
7971 /// baseline's `point_type`) and `false` on every other variant.
7972 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
7973 /// default-arm short-circuit: on the ephemeral sugar surface the
7974 /// parent Option is filled through the workspace baseline rather
7975 /// than reading `false` on every variant like the encapsulation-
7976 /// mode / encapsulation-target / routing-form Option-parent
7977 /// corners.
7978 #[test]
7979 fn has_point_type_probes_gate_only_on_absent_classification() {
7980 let spec = empty_ephemeral();
7981 assert!(spec.classification.is_none());
7982 for kind in ConvergencePointType::ALL {
7983 let expected = kind == ConvergencePointType::Gate;
7984 assert_eq!(
7985 spec.has_point_type(kind),
7986 expected,
7987 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7988 );
7989 }
7990 }
7991
7992 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7993 /// identically through [`Self::has_point_type`] AND through
7994 /// `<eph.clone().into::<ProcessSpec>>()`
7995 /// `.classification.has_point_type(kind)` on the mechanically-
7996 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7997 /// classification on every [`ConvergencePointType::ALL`] variant)
7998 /// × ALL queries so a future regression on either side of the
7999 /// resolver (a shift in the ephemeral resolver's default, a
8000 /// shift in the `From<EphemeralSpec>` lowering's fill-through)
8001 /// fails HERE at the parity boundary.
8002 #[test]
8003 fn has_point_type_matches_point_peer_through_lowered_classification() {
8004 // Absent classification: both surfaces resolve through the SAME
8005 // default and agree on every variant.
8006 let eph = empty_ephemeral();
8007 let lowered: ProcessSpec = eph.clone().into();
8008 for query in ConvergencePointType::ALL {
8009 assert_eq!(
8010 eph.has_point_type(query),
8011 lowered.classification.has_point_type(query),
8012 "None-classification parity drift on query {query:?}",
8013 );
8014 }
8015 // Authored classification: both surfaces read the same authored
8016 // value verbatim.
8017 for populated in ConvergencePointType::ALL {
8018 let mut classification = Classification::gate_compute();
8019 classification.point_type = populated;
8020 let mut eph = empty_ephemeral();
8021 eph.classification = Some(classification);
8022 let lowered: ProcessSpec = eph.clone().into();
8023 for query in ConvergencePointType::ALL {
8024 assert_eq!(
8025 eph.has_point_type(query),
8026 lowered.classification.has_point_type(query),
8027 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8028 );
8029 }
8030 }
8031 }
8032
8033 // ── EphemeralSpec::has_substrate pins ────────────────────────────
8034 //
8035 // Fail-before-pass-after granularity: [`Self::has_substrate`] did
8036 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8037 // through `.resolved_classification().substrate == kind` or through
8038 // the lowered `ProcessSpec`'s `spec.classification.has_substrate`.
8039 // Post-lift the SECOND classification-axis peer on the ephemeral
8040 // sugar surface routes through the SAME
8041 // [`Self::resolved_classification`] resolver + the sibling closed-
8042 // set primitive [`Classification::has_substrate`], so a regression
8043 // that dropped the resolver hop, inverted the `Some`/`None`
8044 // fill-through, or wired the closure to a fixed unrelated slot
8045 // fails HERE.
8046
8047 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8048 /// [`EphemeralSpec::classification`] slot names a concrete
8049 /// [`Classification`] returns `true` from
8050 /// [`Self::has_substrate`] on the authored [`SubstrateType`] slot
8051 /// and `false` for every other variant. Sweep the
8052 /// [`SubstrateType::ALL`] × ALL cross so a regression that
8053 /// hard-coded the arm to a single kind or wired the closure to a
8054 /// fixed unrelated slot fails HERE at the substrate primitive.
8055 /// Byte-for-byte peer of the point-surface
8056 /// [`Classification::has_substrate`] populated-slot sweep on the
8057 /// SAME closed-set primitive.
8058 #[test]
8059 fn has_substrate_returns_true_iff_authored_classification_matches_per_kind() {
8060 for populated in SubstrateType::ALL {
8061 let mut classification = Classification::gate_compute();
8062 classification.substrate = populated;
8063 let mut spec = empty_ephemeral();
8064 spec.classification = Some(classification);
8065 for query in SubstrateType::ALL {
8066 let expected = query == populated;
8067 assert_eq!(
8068 spec.has_substrate(query),
8069 expected,
8070 "ephemeral classification.substrate={populated:?}: query {query:?} drifted",
8071 );
8072 }
8073 }
8074 }
8075
8076 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8077 /// [`EphemeralSpec::classification`] slot is `None` returns
8078 /// `true` from [`Self::has_substrate`] on
8079 /// [`SubstrateType::Compute`] (the `default_ephemeral_class`
8080 /// baseline's `substrate`) and `false` on every other variant.
8081 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
8082 /// default-arm short-circuit on the SECOND classification-axis
8083 /// peer: on the ephemeral sugar surface the parent Option is
8084 /// filled through the workspace baseline rather than reading
8085 /// `false` on every variant like the Option-parent encapsulates /
8086 /// routing corners.
8087 #[test]
8088 fn has_substrate_probes_compute_only_on_absent_classification() {
8089 let spec = empty_ephemeral();
8090 assert!(spec.classification.is_none());
8091 for kind in SubstrateType::ALL {
8092 let expected = kind == SubstrateType::Compute;
8093 assert_eq!(
8094 spec.has_substrate(kind),
8095 expected,
8096 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8097 );
8098 }
8099 }
8100
8101 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8102 /// identically through [`Self::has_substrate`] AND through
8103 /// `<eph.clone().into::<ProcessSpec>>()`
8104 /// `.classification.has_substrate(kind)` on the mechanically-
8105 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8106 /// classification on every [`SubstrateType::ALL`] variant) × ALL
8107 /// queries so a future regression on either side of the resolver
8108 /// (a shift in the ephemeral resolver's default, a shift in the
8109 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8110 /// the parity boundary. Byte-for-byte peer of the sibling
8111 /// [`Self::has_point_type`] two-surface parity pin on the SAME
8112 /// `Cow`-resolver carrier — the SECOND classification-axis
8113 /// two-surface parity contract on the ephemeral surface.
8114 #[test]
8115 fn has_substrate_matches_point_peer_through_lowered_classification() {
8116 // Absent classification: both surfaces resolve through the SAME
8117 // default and agree on every variant.
8118 let eph = empty_ephemeral();
8119 let lowered: ProcessSpec = eph.clone().into();
8120 for query in SubstrateType::ALL {
8121 assert_eq!(
8122 eph.has_substrate(query),
8123 lowered.classification.has_substrate(query),
8124 "None-classification parity drift on query {query:?}",
8125 );
8126 }
8127 // Authored classification: both surfaces read the same authored
8128 // value verbatim.
8129 for populated in SubstrateType::ALL {
8130 let mut classification = Classification::gate_compute();
8131 classification.substrate = populated;
8132 let mut eph = empty_ephemeral();
8133 eph.classification = Some(classification);
8134 let lowered: ProcessSpec = eph.clone().into();
8135 for query in SubstrateType::ALL {
8136 assert_eq!(
8137 eph.has_substrate(query),
8138 lowered.classification.has_substrate(query),
8139 "authored classification.substrate={populated:?}: parity drift on query {query:?}",
8140 );
8141 }
8142 }
8143 }
8144
8145 // ── EphemeralSpec::has_calm pins ─────────────────────────────────
8146 //
8147 // Fail-before-pass-after granularity: [`Self::has_calm`] did not
8148 // exist pre-lift on `impl EphemeralSpec` — every callsite went
8149 // through `.resolved_classification().calm == kind` or through the
8150 // lowered `ProcessSpec`'s `spec.classification.has_calm`. Post-
8151 // lift the THIRD classification-axis peer on the ephemeral sugar
8152 // surface routes through the SAME
8153 // [`Self::resolved_classification`] resolver + the sibling closed-
8154 // set primitive [`Classification::has_calm`], so a regression that
8155 // dropped the resolver hop, inverted the `Some`/`None` fill-
8156 // through, or wired the closure to a fixed unrelated slot fails
8157 // HERE. Distinct from the FIRST + SECOND peers on the (Option-
8158 // parent × NON-DEFAULT-scalar-child) corner: the (Option-parent ×
8159 // DEFAULTED-scalar-child) corner this peer opens has BOTH the
8160 // parent fill-through baseline (`default_ephemeral_class`) AND the
8161 // child's own `#[default]` land on the SAME variant
8162 // ([`CalmClassification::Monotone`]), a two-defaults composition
8163 // property the three pins below all exercise.
8164
8165 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8166 /// [`EphemeralSpec::classification`] slot names a concrete
8167 /// [`Classification`] returns `true` from [`Self::has_calm`] on
8168 /// the authored [`CalmClassification`] slot and `false` for every
8169 /// other variant. Sweep the [`CalmClassification::ALL`] × ALL
8170 /// cross so a regression that hard-coded the arm to a single
8171 /// kind or wired the closure to a fixed unrelated slot fails HERE
8172 /// at the substrate primitive. Byte-for-byte peer of the point-
8173 /// surface [`Classification::has_calm`] populated-slot sweep on
8174 /// the SAME closed-set primitive.
8175 #[test]
8176 fn has_calm_returns_true_iff_authored_classification_matches_per_kind() {
8177 for populated in CalmClassification::ALL {
8178 let mut classification = Classification::gate_compute();
8179 classification.calm = populated;
8180 let mut spec = empty_ephemeral();
8181 spec.classification = Some(classification);
8182 for query in CalmClassification::ALL {
8183 let expected = query == populated;
8184 assert_eq!(
8185 spec.has_calm(query),
8186 expected,
8187 "ephemeral classification.calm={populated:?}: query {query:?} drifted",
8188 );
8189 }
8190 }
8191 }
8192
8193 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8194 /// [`EphemeralSpec::classification`] slot is `None` returns
8195 /// `true` from [`Self::has_calm`] on
8196 /// [`CalmClassification::Monotone`] (the `default_ephemeral_class`
8197 /// baseline's `calm` axis AND the [`CalmClassification`] child's
8198 /// own `#[default]` variant) and `false` on every other variant.
8199 /// Pins the (Option-parent × DEFAULTED-scalar-child ×
8200 /// operator-resolvable-baseline) corner's default-arm short-
8201 /// circuit on the THIRD classification-axis peer — distinct from
8202 /// the FIRST + SECOND peers on the (Option-parent × NON-DEFAULT-
8203 /// scalar-child) corner which default through a specific chosen
8204 /// baseline ([`ConvergencePointType::Gate`],
8205 /// [`SubstrateType::Compute`]) rather than through the child's
8206 /// own `#[default]`. Two-defaults composition property: both the
8207 /// parent fill-through and the child's `#[default]` land on the
8208 /// SAME variant, so the ephemeral sugar surface's `calm-Monotone`
8209 /// require-tag reads `true` on every operator-authored spec that
8210 /// omits both the `:classification` slot AND the `:calm` sub-slot,
8211 /// pinning the workspace's monotone-by-default posture.
8212 #[test]
8213 fn has_calm_probes_monotone_only_on_absent_classification() {
8214 let spec = empty_ephemeral();
8215 assert!(spec.classification.is_none());
8216 for kind in CalmClassification::ALL {
8217 let expected = kind == CalmClassification::Monotone;
8218 assert_eq!(
8219 spec.has_calm(kind),
8220 expected,
8221 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8222 );
8223 }
8224 }
8225
8226 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8227 /// identically through [`Self::has_calm`] AND through
8228 /// `<eph.clone().into::<ProcessSpec>>()`
8229 /// `.classification.has_calm(kind)` on the mechanically-
8230 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8231 /// classification on every [`CalmClassification::ALL`] variant) ×
8232 /// ALL queries so a future regression on either side of the
8233 /// resolver (a shift in the ephemeral resolver's default, a shift
8234 /// in the `From<EphemeralSpec>` lowering's fill-through) fails
8235 /// HERE at the parity boundary. Byte-for-byte peer of the sibling
8236 /// [`Self::has_point_type`] + [`Self::has_substrate`] two-surface
8237 /// parity pins on the SAME `Cow`-resolver carrier — the THIRD
8238 /// classification-axis two-surface parity contract on the
8239 /// ephemeral surface, and the FIRST on the (Option-parent ×
8240 /// DEFAULTED-scalar-child) corner.
8241 #[test]
8242 fn has_calm_matches_point_peer_through_lowered_classification() {
8243 // Absent classification: both surfaces resolve through the SAME
8244 // default and agree on every variant.
8245 let eph = empty_ephemeral();
8246 let lowered: ProcessSpec = eph.clone().into();
8247 for query in CalmClassification::ALL {
8248 assert_eq!(
8249 eph.has_calm(query),
8250 lowered.classification.has_calm(query),
8251 "None-classification parity drift on query {query:?}",
8252 );
8253 }
8254 // Authored classification: both surfaces read the same authored
8255 // value verbatim.
8256 for populated in CalmClassification::ALL {
8257 let mut classification = Classification::gate_compute();
8258 classification.calm = populated;
8259 let mut eph = empty_ephemeral();
8260 eph.classification = Some(classification);
8261 let lowered: ProcessSpec = eph.clone().into();
8262 for query in CalmClassification::ALL {
8263 assert_eq!(
8264 eph.has_calm(query),
8265 lowered.classification.has_calm(query),
8266 "authored classification.calm={populated:?}: parity drift on query {query:?}",
8267 );
8268 }
8269 }
8270 }
8271
8272 // ── EphemeralSpec::has_data_classification pins ──────────────────
8273 //
8274 // Fail-before-pass-after granularity: [`Self::has_data_classification`]
8275 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
8276 // went through `.resolved_classification().data_classification ==
8277 // kind` or through the lowered `ProcessSpec`'s
8278 // `spec.classification.has_data_classification`. Post-lift the
8279 // FOURTH classification-axis peer on the ephemeral sugar surface
8280 // routes through the SAME [`Self::resolved_classification`]
8281 // resolver + the sibling closed-set primitive
8282 // [`crate::classification::Classification::has_data_classification`],
8283 // so a regression that dropped the resolver hop, inverted the
8284 // `Some`/`None` fill-through, or wired the closure to a fixed
8285 // unrelated slot fails HERE. SECOND occupant on the (Option-parent
8286 // × DEFAULTED-scalar-child × operator-resolvable-baseline) corner
8287 // alongside [`Self::has_calm`]: both the parent fill-through
8288 // baseline (`default_ephemeral_class`) AND the child's own
8289 // `#[default]` land on the SAME variant
8290 // ([`DataClassification::Internal`]), a two-defaults composition
8291 // property the three pins below all exercise.
8292
8293 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8294 /// [`EphemeralSpec::classification`] slot names a concrete
8295 /// [`Classification`] returns `true` from
8296 /// [`Self::has_data_classification`] on the authored
8297 /// [`DataClassification`] slot and `false` for every other
8298 /// variant. Sweep the [`DataClassification::ALL`] × ALL cross so
8299 /// a regression that hard-coded the arm to a single kind or
8300 /// wired the closure to a fixed unrelated slot fails HERE at the
8301 /// substrate primitive. Byte-for-byte peer of the point-surface
8302 /// [`Classification::has_data_classification`] populated-slot
8303 /// sweep on the SAME closed-set primitive.
8304 #[test]
8305 fn has_data_classification_returns_true_iff_authored_classification_matches_per_kind() {
8306 for populated in DataClassification::ALL {
8307 let mut classification = Classification::gate_compute();
8308 classification.data_classification = populated;
8309 let mut spec = empty_ephemeral();
8310 spec.classification = Some(classification);
8311 for query in DataClassification::ALL {
8312 let expected = query == populated;
8313 assert_eq!(
8314 spec.has_data_classification(query),
8315 expected,
8316 "ephemeral classification.data_classification={populated:?}: query {query:?} drifted",
8317 );
8318 }
8319 }
8320 }
8321
8322 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8323 /// [`EphemeralSpec::classification`] slot is `None` returns
8324 /// `true` from [`Self::has_data_classification`] on
8325 /// [`DataClassification::Internal`] (the `default_ephemeral_class`
8326 /// baseline's `data_classification` axis AND the
8327 /// [`DataClassification`] child's own `#[default]` variant) and
8328 /// `false` on every other variant. Pins the (Option-parent ×
8329 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner's
8330 /// default-arm short-circuit on the FOURTH classification-axis
8331 /// peer — SECOND occupant on that corner after [`Self::has_calm`]
8332 /// opened it. Two-defaults composition property: both the parent
8333 /// fill-through and the child's `#[default]` land on the SAME
8334 /// variant, so the ephemeral sugar surface's
8335 /// `data-classification-Internal` require-tag reads `true` on
8336 /// every operator-authored spec that omits both the
8337 /// `:classification` slot AND the `:data-classification` sub-slot,
8338 /// pinning the workspace's internal-by-default sensitivity posture.
8339 #[test]
8340 fn has_data_classification_probes_internal_only_on_absent_classification() {
8341 let spec = empty_ephemeral();
8342 assert!(spec.classification.is_none());
8343 for kind in DataClassification::ALL {
8344 let expected = kind == DataClassification::Internal;
8345 assert_eq!(
8346 spec.has_data_classification(kind),
8347 expected,
8348 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8349 );
8350 }
8351 }
8352
8353 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8354 /// identically through [`Self::has_data_classification`] AND
8355 /// through `<eph.clone().into::<ProcessSpec>>()`
8356 /// `.classification.has_data_classification(kind)` on the
8357 /// mechanically-lowered `ProcessSpec`. Sweeps (`None`
8358 /// classification, `Some(_)` classification on every
8359 /// [`DataClassification::ALL`] variant) × ALL queries so a
8360 /// future regression on either side of the resolver (a shift in
8361 /// the ephemeral resolver's default, a shift in the
8362 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8363 /// the parity boundary. Byte-for-byte peer of the sibling
8364 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
8365 /// [`Self::has_calm`] two-surface parity pins on the SAME
8366 /// `Cow`-resolver carrier — the FOURTH classification-axis
8367 /// two-surface parity contract on the ephemeral surface, and the
8368 /// SECOND on the (Option-parent × DEFAULTED-scalar-child) corner.
8369 #[test]
8370 fn has_data_classification_matches_point_peer_through_lowered_classification() {
8371 // Absent classification: both surfaces resolve through the SAME
8372 // default and agree on every variant.
8373 let eph = empty_ephemeral();
8374 let lowered: ProcessSpec = eph.clone().into();
8375 for query in DataClassification::ALL {
8376 assert_eq!(
8377 eph.has_data_classification(query),
8378 lowered.classification.has_data_classification(query),
8379 "None-classification parity drift on query {query:?}",
8380 );
8381 }
8382 // Authored classification: both surfaces read the same authored
8383 // value verbatim.
8384 for populated in DataClassification::ALL {
8385 let mut classification = Classification::gate_compute();
8386 classification.data_classification = populated;
8387 let mut eph = empty_ephemeral();
8388 eph.classification = Some(classification);
8389 let lowered: ProcessSpec = eph.clone().into();
8390 for query in DataClassification::ALL {
8391 assert_eq!(
8392 eph.has_data_classification(query),
8393 lowered.classification.has_data_classification(query),
8394 "authored classification.data_classification={populated:?}: parity drift on query {query:?}",
8395 );
8396 }
8397 }
8398 }
8399
8400 // ── EphemeralSpec::has_horizon_kind pins ─────────────────────────
8401 //
8402 // Fail-before-pass-after granularity: [`Self::has_horizon_kind`]
8403 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
8404 // went through `.resolved_classification().horizon.kind == kind`
8405 // or through the lowered `ProcessSpec`'s
8406 // `spec.classification.has_horizon_kind`. Post-lift the FIFTH
8407 // classification-axis peer on the ephemeral sugar surface routes
8408 // through the SAME [`Self::resolved_classification`] resolver +
8409 // the sibling closed-set primitive
8410 // [`crate::classification::Classification::has_horizon_kind`], so
8411 // a regression that dropped the resolver hop, inverted the
8412 // `Some`/`None` fill-through, or wired the closure to a fixed
8413 // unrelated slot fails HERE. OPENS a fresh (Option-parent ×
8414 // NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
8415 // corner on the ephemeral surface — distinct from the four prior
8416 // scalar-carrier peers on the (Option-parent × NON-DEFAULT-scalar-
8417 // child) and (Option-parent × DEFAULTED-scalar-child) corners, all
8418 // of which reach a discriminator DIRECTLY off a scalar
8419 // [`Classification`] slot. Both the parent Option's fill-through
8420 // baseline (`default_ephemeral_class`, which fills
8421 // `horizon: Horizon::default()`) AND the child's own `#[default]`
8422 // land on the SAME variant ([`HorizonKind::Bounded`]) — a two-
8423 // defaults composition property the three pins below all
8424 // exercise.
8425
8426 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8427 /// [`EphemeralSpec::classification`] slot names a concrete
8428 /// [`Classification`] returns `true` from
8429 /// [`Self::has_horizon_kind`] on the authored [`HorizonKind`] slot
8430 /// and `false` for every other variant. Sweep the
8431 /// [`HorizonKind::ALL`] × ALL cross so a regression that hard-
8432 /// coded the arm to a single kind or wired the closure to a
8433 /// fixed unrelated slot (e.g. reading `self.classification` as if
8434 /// it were a scalar rather than routing through
8435 /// `resolved_classification().horizon.kind`) fails HERE at the
8436 /// substrate primitive. Byte-for-byte peer of the point-surface
8437 /// [`Classification::has_horizon_kind`] populated-slot sweep on
8438 /// the SAME closed-set primitive.
8439 #[test]
8440 fn has_horizon_kind_returns_true_iff_authored_classification_matches_per_kind() {
8441 for populated in HorizonKind::ALL {
8442 let classification = Classification::gate_compute_with_axis(populated);
8443 let mut spec = empty_ephemeral();
8444 spec.classification = Some(classification);
8445 for query in HorizonKind::ALL {
8446 let expected = query == populated;
8447 assert_eq!(
8448 spec.has_horizon_kind(query),
8449 expected,
8450 "ephemeral classification.horizon.kind={populated:?}: query {query:?} drifted",
8451 );
8452 }
8453 }
8454 }
8455
8456 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8457 /// [`EphemeralSpec::classification`] slot is `None` returns
8458 /// `true` from [`Self::has_horizon_kind`] on
8459 /// [`HorizonKind::Bounded`] (the `default_ephemeral_class`
8460 /// baseline's `horizon.kind` axis AND the [`HorizonKind`] child's
8461 /// own `#[default]` variant) and `false` on every other variant.
8462 /// Pins the fresh (Option-parent × NESTED-STRUCT-scalar-child ×
8463 /// operator-resolvable-baseline) corner's default-arm short-
8464 /// circuit on the FIFTH classification-axis peer. Two-defaults
8465 /// composition property through a NESTED-STRUCT hop: both the
8466 /// parent Option's fill-through baseline
8467 /// (`default_ephemeral_class` fills `horizon: Horizon::default()`)
8468 /// AND the child's own `#[default]` (`HorizonKind::Bounded` via
8469 /// `#[default]` on the closed set) land on the SAME variant, so
8470 /// the ephemeral sugar surface's `horizon-Bounded` require-tag
8471 /// reads `true` on every operator-authored spec that omits both
8472 /// the `:classification` slot AND the `:horizon` sub-slot,
8473 /// pinning the workspace's bounded-by-default lifetime posture.
8474 #[test]
8475 fn has_horizon_kind_probes_bounded_only_on_absent_classification() {
8476 let spec = empty_ephemeral();
8477 assert!(spec.classification.is_none());
8478 for kind in HorizonKind::ALL {
8479 let expected = kind == HorizonKind::Bounded;
8480 assert_eq!(
8481 spec.has_horizon_kind(kind),
8482 expected,
8483 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8484 );
8485 }
8486 }
8487
8488 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8489 /// identically through [`Self::has_horizon_kind`] AND through
8490 /// `<eph.clone().into::<ProcessSpec>>()`
8491 /// `.classification.has_horizon_kind(kind)` on the mechanically-
8492 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8493 /// classification on every [`HorizonKind::ALL`] variant) × ALL
8494 /// queries so a future regression on either side of the resolver
8495 /// (a shift in the ephemeral resolver's default, a shift in the
8496 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8497 /// the parity boundary. Byte-for-byte peer of the sibling
8498 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
8499 /// [`Self::has_calm`] + [`Self::has_data_classification`] two-
8500 /// surface parity pins on the SAME `Cow`-resolver carrier — the
8501 /// FIFTH classification-axis two-surface parity contract on the
8502 /// ephemeral surface, and the FIRST on the (Option-parent ×
8503 /// NESTED-STRUCT-scalar-child) corner.
8504 #[test]
8505 fn has_horizon_kind_matches_point_peer_through_lowered_classification() {
8506 // Absent classification: both surfaces resolve through the SAME
8507 // default and agree on every variant.
8508 let eph = empty_ephemeral();
8509 let lowered: ProcessSpec = eph.clone().into();
8510 for query in HorizonKind::ALL {
8511 assert_eq!(
8512 eph.has_horizon_kind(query),
8513 lowered.classification.has_horizon_kind(query),
8514 "None-classification parity drift on query {query:?}",
8515 );
8516 }
8517 // Authored classification: both surfaces read the same authored
8518 // value verbatim.
8519 for populated in HorizonKind::ALL {
8520 let classification = Classification::gate_compute_with_axis(populated);
8521 let mut eph = empty_ephemeral();
8522 eph.classification = Some(classification);
8523 let lowered: ProcessSpec = eph.clone().into();
8524 for query in HorizonKind::ALL {
8525 assert_eq!(
8526 eph.has_horizon_kind(query),
8527 lowered.classification.has_horizon_kind(query),
8528 "authored classification.horizon.kind={populated:?}: parity drift on query {query:?}",
8529 );
8530 }
8531 }
8532 }
8533
8534 // ── EphemeralSpec::has_optimization_direction pins ───────────────
8535 //
8536 // Fail-before-pass-after granularity:
8537 // [`Self::has_optimization_direction`] did not exist pre-lift on
8538 // `impl EphemeralSpec` — every callsite went through
8539 // `.resolved_classification().horizon.direction.unwrap_or_default() == kind`
8540 // or through the lowered `ProcessSpec`'s
8541 // `spec.classification.has_optimization_direction`. Post-lift the
8542 // SIXTH classification-axis peer on the ephemeral sugar surface
8543 // routes through the SAME [`Self::resolved_classification`]
8544 // resolver + the sibling closed-set primitive
8545 // [`crate::classification::Classification::has_optimization_direction`],
8546 // so a regression that dropped the resolver hop, inverted the
8547 // `Some`/`None` fill-through, wired the closure to a fixed
8548 // unrelated slot, or flipped [`OptimizationDirection`]'s
8549 // `#[default]` off `Minimize` fails HERE. SECOND occupant on the
8550 // (Option-parent × NESTED-STRUCT-scalar-child × operator-
8551 // resolvable-baseline) corner alongside
8552 // [`Self::has_horizon_kind`] — pinning the corner as a proven-
8553 // repeatable primitive shape on the ephemeral surface with a
8554 // second nested-struct-child probe, and DEMONSTRATING that the
8555 // corner admits both direct-scalar and Option-scalar traversals
8556 // through the SAME nested [`Horizon`] intermediary via the closed
8557 // set's `Default` on the inner `Option<OptimizationDirection>`
8558 // slot.
8559
8560 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8561 /// [`EphemeralSpec::classification`] slot names a concrete
8562 /// [`Classification`] whose [`crate::classification::Horizon::direction`]
8563 /// slot carries `Some(<direction>)` returns `true` from
8564 /// [`Self::has_optimization_direction`] on the authored
8565 /// [`OptimizationDirection`] variant and `false` for every other
8566 /// variant. Sweep the [`OptimizationDirection::ALL`] × ALL cross
8567 /// so a regression that hard-coded the arm to a single kind, or
8568 /// dropped the `Option::unwrap_or_default` collapse, or wired the
8569 /// closure to a fixed unrelated slot (e.g. reading `self.horizon.kind`)
8570 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
8571 /// point-surface
8572 /// [`Classification::has_optimization_direction`] populated-slot
8573 /// sweep on the SAME closed-set primitive.
8574 #[test]
8575 fn has_optimization_direction_returns_true_iff_authored_direction_matches_per_kind() {
8576 for populated in OptimizationDirection::ALL {
8577 let classification = Classification::gate_compute_with_axis(populated);
8578 let mut spec = empty_ephemeral();
8579 spec.classification = Some(classification);
8580 for query in OptimizationDirection::ALL {
8581 let expected = query == populated;
8582 assert_eq!(
8583 spec.has_optimization_direction(query),
8584 expected,
8585 "ephemeral classification.horizon.direction=Some({populated:?}): query {query:?} drifted",
8586 );
8587 }
8588 }
8589 }
8590
8591 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8592 /// [`EphemeralSpec::classification`] slot is `None` returns
8593 /// `true` from [`Self::has_optimization_direction`] on
8594 /// [`OptimizationDirection::Minimize`] (the `default_ephemeral_class`
8595 /// baseline fills `horizon: Horizon::default()`, which in turn
8596 /// leaves `direction: None`, and the substrate's
8597 /// `Option::unwrap_or_default` collapse then reads
8598 /// [`OptimizationDirection::Minimize`] via the closed set's
8599 /// `#[default]`) and `false` on every other variant. Pins the
8600 /// (Option-parent × NESTED-STRUCT-scalar-child × operator-
8601 /// resolvable-baseline) corner's default-arm short-circuit on the
8602 /// SIXTH classification-axis peer through TWO Option-hops: parent
8603 /// `EphemeralSpec::classification` and inner `Horizon::direction`
8604 /// both `None`, both collapsing to the closed set's `#[default]`
8605 /// [`OptimizationDirection::Minimize`]. A regression that promoted
8606 /// [`OptimizationDirection::Maximize`] to `#[default]` (silently
8607 /// inverting every unadorned Process's rate-window evaluator
8608 /// polarity), dropped `Option::unwrap_or_default`, or wired the arm
8609 /// to a fixed variant answer fails HERE.
8610 #[test]
8611 fn has_optimization_direction_probes_minimize_only_on_absent_classification() {
8612 let spec = empty_ephemeral();
8613 assert!(spec.classification.is_none());
8614 for kind in OptimizationDirection::ALL {
8615 let expected = kind == OptimizationDirection::Minimize;
8616 assert_eq!(
8617 spec.has_optimization_direction(kind),
8618 expected,
8619 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8620 );
8621 }
8622 }
8623
8624 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8625 /// identically through [`Self::has_optimization_direction`] AND
8626 /// through
8627 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
8628 /// on the mechanically-lowered `ProcessSpec`. Sweeps three arms —
8629 /// (`None` classification), (`Some(_)` classification with
8630 /// `direction: None`), and (`Some(_)` classification on every
8631 /// [`OptimizationDirection::ALL`] variant) — × ALL queries so a
8632 /// future regression on either side of the resolver (an ephemeral-
8633 /// side fill-through drift, a lowering-side `From<EphemeralSpec>`
8634 /// `unwrap_or_else(default_ephemeral_class)` drift, an inner
8635 /// `Option::unwrap_or_default` collapse drift on either side)
8636 /// fails HERE at the parity boundary. Byte-for-byte peer of the
8637 /// sibling [`Self::has_point_type`] + [`Self::has_substrate`] +
8638 /// [`Self::has_calm`] + [`Self::has_data_classification`] +
8639 /// [`Self::has_horizon_kind`] two-surface parity pins on the SAME
8640 /// `Cow`-resolver carrier — the SIXTH classification-axis two-
8641 /// surface parity contract on the ephemeral surface, and the
8642 /// SECOND on the (Option-parent × NESTED-STRUCT-scalar-child)
8643 /// corner.
8644 #[test]
8645 fn has_optimization_direction_matches_point_peer_through_lowered_classification() {
8646 // Absent classification: both surfaces resolve through the SAME
8647 // default and agree on every variant.
8648 let eph = empty_ephemeral();
8649 let lowered: ProcessSpec = eph.clone().into();
8650 for query in OptimizationDirection::ALL {
8651 assert_eq!(
8652 eph.has_optimization_direction(query),
8653 lowered.classification.has_optimization_direction(query),
8654 "None-classification parity drift on query {query:?}",
8655 );
8656 }
8657 // Authored classification with `direction: None` — the inner
8658 // Option collapses through `unwrap_or_default` on both sides,
8659 // reading `Minimize`.
8660 let mut classification = Classification::gate_compute();
8661 classification.horizon = Horizon::default();
8662 let mut eph = empty_ephemeral();
8663 eph.classification = Some(classification);
8664 let lowered: ProcessSpec = eph.clone().into();
8665 for query in OptimizationDirection::ALL {
8666 assert_eq!(
8667 eph.has_optimization_direction(query),
8668 lowered.classification.has_optimization_direction(query),
8669 "authored classification with horizon.direction=None: parity drift on query {query:?}",
8670 );
8671 }
8672 // Authored classification with `direction: Some(_)` — both
8673 // surfaces read the same authored value verbatim.
8674 for populated in OptimizationDirection::ALL {
8675 let classification = Classification::gate_compute_with_axis(populated);
8676 let mut eph = empty_ephemeral();
8677 eph.classification = Some(classification);
8678 let lowered: ProcessSpec = eph.clone().into();
8679 for query in OptimizationDirection::ALL {
8680 assert_eq!(
8681 eph.has_optimization_direction(query),
8682 lowered.classification.has_optimization_direction(query),
8683 "authored classification.horizon.direction=Some({populated:?}): parity drift on query {query:?}",
8684 );
8685 }
8686 }
8687 }
8688
8689 // ── EphemeralSpec::has_input_arity pins ──────────────────────────
8690 //
8691 // Fail-before-pass-after granularity: [`Self::has_input_arity`] did
8692 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8693 // through `.resolved_classification().point_type.input_arity() ==
8694 // kind` or through the lowered `ProcessSpec`'s
8695 // `spec.classification.has_input_arity`. Post-lift the SEVENTH
8696 // classification-axis peer on the ephemeral sugar surface routes
8697 // through the SAME [`Self::resolved_classification`] resolver + the
8698 // sibling closed-set primitive
8699 // [`crate::classification::Classification::has_input_arity`], so a
8700 // regression that dropped the resolver hop, dropped the
8701 // `.input_arity()` projection call, inverted the projection (`One
8702 // ↔ Many`), or crossed the wires with the sibling
8703 // [`ConvergencePointType::output_arity`] projection fails HERE.
8704 // OPENS the (Option-parent × NESTED-STRUCT-scalar-child ×
8705 // derived-typed-projection) corner on the ephemeral surface —
8706 // distinct from the two prior nested-scalar peers on the corner
8707 // (`has_horizon_kind` reads `horizon.kind` directly;
8708 // `has_optimization_direction` reads `horizon.direction` through an
8709 // Option collapse), both of which reach a discriminator DIRECTLY off
8710 // a scalar. This peer instead threads through a many-to-one closed-
8711 // set typed projection so the child's closed set is REACHED THROUGH
8712 // a projection layer, pinning the corner as admitting three
8713 // ephemeral-surface traversal shapes (direct-scalar, Option-scalar-
8714 // with-default, derived-typed-projection) through the SAME resolver
8715 // walk.
8716
8717 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
8718 /// [`EphemeralSpec::classification`] slot names a concrete
8719 /// [`Classification`] with an authored [`ConvergencePointType`]
8720 /// returns `true` from [`Self::has_input_arity`] on the [`Arity`]
8721 /// value the projection [`ConvergencePointType::input_arity`] maps
8722 /// the authored point-type to and `false` for every other variant.
8723 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
8724 /// a regression that (a) dropped the projection call, (b) inverted
8725 /// the projection, (c) probed [`ConvergencePointType`] directly, or
8726 /// (d) crossed wires with [`ConvergencePointType::output_arity`]
8727 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
8728 /// point-surface [`Classification::has_input_arity`] populated-slot
8729 /// sweep on the SAME closed-set primitive routed through the SAME
8730 /// projection.
8731 #[test]
8732 fn has_input_arity_returns_true_iff_authored_point_type_projects_per_kind() {
8733 for populated in ConvergencePointType::ALL {
8734 let mut classification = Classification::gate_compute();
8735 classification.point_type = populated;
8736 let mut spec = empty_ephemeral();
8737 spec.classification = Some(classification);
8738 let projected = populated.input_arity();
8739 for query in Arity::ALL {
8740 let expected = query == projected;
8741 assert_eq!(
8742 spec.has_input_arity(query),
8743 expected,
8744 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
8745 );
8746 }
8747 }
8748 }
8749
8750 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
8751 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
8752 /// from [`Self::has_input_arity`] on [`Arity::Many`] (the
8753 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
8754 /// and [`ConvergencePointType::input_arity`] projects
8755 /// `Gate → Arity::Many`) and `false` on [`Arity::One`]. Pins the
8756 /// (Option-parent × NESTED-STRUCT-scalar-child × derived-typed-
8757 /// projection) corner's baseline projection on the SEVENTH
8758 /// classification-axis peer through a chain of TWO fill-throughs
8759 /// composed with ONE projection: the parent Option's
8760 /// `unwrap_or_else(default_ephemeral_class)` picks the substrate
8761 /// baseline, and the projection then collapses the baseline's
8762 /// point-type through the closed-set-driven many-to-one bucket
8763 /// walk. [`Arity`] carries no `#[default]`, so there is NO default-
8764 /// arm short-circuit shortcut here — the answer flows entirely
8765 /// through the projection's bucket-membership decision. A
8766 /// regression that promoted the baseline's `point_type` off `Gate`
8767 /// (silently flipping every unadorned Process's convergent-by-
8768 /// default input-side posture to endomorphic or diffusive), dropped
8769 /// the projection call, inverted the projection, or crossed wires
8770 /// with [`ConvergencePointType::output_arity`] (which would flip
8771 /// the baseline answer from `Many` to `One` for `Gate`) fails HERE.
8772 #[test]
8773 fn has_input_arity_probes_many_only_on_absent_classification() {
8774 let spec = empty_ephemeral();
8775 assert!(spec.classification.is_none());
8776 for kind in Arity::ALL {
8777 let expected = kind == Arity::Many;
8778 assert_eq!(
8779 spec.has_input_arity(kind),
8780 expected,
8781 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many): query {kind:?} must be {expected}",
8782 );
8783 }
8784 }
8785
8786 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8787 /// identically through [`Self::has_input_arity`] AND through
8788 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
8789 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8790 /// classification, `Some(_)` classification on every
8791 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
8792 /// so a future regression on either side of the resolver (a shift
8793 /// in the ephemeral resolver's default, a shift in the
8794 /// `From<EphemeralSpec>` lowering's fill-through, a projection
8795 /// drift on either side) fails HERE at the parity boundary. Byte-
8796 /// for-byte peer of the sibling [`Self::has_point_type`] +
8797 /// [`Self::has_substrate`] + [`Self::has_calm`] +
8798 /// [`Self::has_data_classification`] + [`Self::has_horizon_kind`] +
8799 /// [`Self::has_optimization_direction`] two-surface parity pins on
8800 /// the SAME `Cow`-resolver carrier — the SEVENTH classification-
8801 /// axis two-surface parity contract on the ephemeral surface, and
8802 /// the FIRST on the (Option-parent × NESTED-STRUCT-scalar-child ×
8803 /// derived-typed-projection) corner.
8804 #[test]
8805 fn has_input_arity_matches_point_peer_through_lowered_classification() {
8806 // Absent classification: both surfaces resolve through the SAME
8807 // default and agree on every variant.
8808 let eph = empty_ephemeral();
8809 let lowered: ProcessSpec = eph.clone().into();
8810 for query in Arity::ALL {
8811 assert_eq!(
8812 eph.has_input_arity(query),
8813 lowered.classification.has_input_arity(query),
8814 "None-classification parity drift on query {query:?}",
8815 );
8816 }
8817 // Authored classification: both surfaces read the same authored
8818 // point_type and route through the same projection.
8819 for populated in ConvergencePointType::ALL {
8820 let mut classification = Classification::gate_compute();
8821 classification.point_type = populated;
8822 let mut eph = empty_ephemeral();
8823 eph.classification = Some(classification);
8824 let lowered: ProcessSpec = eph.clone().into();
8825 for query in Arity::ALL {
8826 assert_eq!(
8827 eph.has_input_arity(query),
8828 lowered.classification.has_input_arity(query),
8829 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8830 );
8831 }
8832 }
8833 }
8834
8835 // ── EphemeralSpec::has_output_arity pins ─────────────────────────
8836 //
8837 // Fail-before-pass-after granularity: [`Self::has_output_arity`] did
8838 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8839 // through `.resolved_classification().point_type.output_arity() ==
8840 // kind` or through the lowered `ProcessSpec`'s
8841 // `spec.classification.has_output_arity`. Post-lift the EIGHTH
8842 // classification-axis peer on the ephemeral sugar surface routes
8843 // through the SAME [`Self::resolved_classification`] resolver + the
8844 // sibling closed-set primitive
8845 // [`crate::classification::Classification::has_output_arity`], so a
8846 // regression that dropped the resolver hop, dropped the
8847 // `.output_arity()` projection call, inverted the projection (`One
8848 // ↔ Many`), or crossed the wires with the sibling
8849 // [`ConvergencePointType::input_arity`] projection fails HERE.
8850 // CLOSES the (Option-parent × NESTED-STRUCT-scalar-child ×
8851 // derived-typed-projection) corner on the ephemeral surface as the
8852 // SECOND occupant — co-tenant with [`Self::has_input_arity`] on the
8853 // SAME `point_type` scalar carrier through the SAME [`Arity`] closed
8854 // set but through the sibling many-to-one projection, closing the
8855 // DAG-composition arity pair on the ephemeral side.
8856
8857 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
8858 /// [`EphemeralSpec::classification`] slot names a concrete
8859 /// [`Classification`] with an authored [`ConvergencePointType`]
8860 /// returns `true` from [`Self::has_output_arity`] on the [`Arity`]
8861 /// value the projection [`ConvergencePointType::output_arity`] maps
8862 /// the authored point-type to and `false` for every other variant.
8863 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
8864 /// a regression that (a) dropped the projection call, (b) inverted
8865 /// the projection, (c) probed [`ConvergencePointType`] directly, or
8866 /// (d) crossed wires with [`ConvergencePointType::input_arity`]
8867 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
8868 /// point-surface [`Classification::has_output_arity`] populated-slot
8869 /// sweep on the SAME closed-set primitive routed through the SAME
8870 /// projection.
8871 #[test]
8872 fn has_output_arity_returns_true_iff_authored_point_type_projects_per_kind() {
8873 for populated in ConvergencePointType::ALL {
8874 let mut classification = Classification::gate_compute();
8875 classification.point_type = populated;
8876 let mut spec = empty_ephemeral();
8877 spec.classification = Some(classification);
8878 let projected = populated.output_arity();
8879 for query in Arity::ALL {
8880 let expected = query == projected;
8881 assert_eq!(
8882 spec.has_output_arity(query),
8883 expected,
8884 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
8885 );
8886 }
8887 }
8888 }
8889
8890 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
8891 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
8892 /// from [`Self::has_output_arity`] on [`Arity::One`] (the
8893 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
8894 /// and [`ConvergencePointType::output_arity`] projects
8895 /// `Gate → Arity::One`) and `false` on [`Arity::Many`]. MIRROR of
8896 /// the [`Self::has_input_arity`] baseline (`Gate → input_arity =
8897 /// Many`) — the DAG-composition arity pair projects the same `Gate`
8898 /// baseline through the two projections to opposite [`Arity`] arms,
8899 /// so this pin locks the output-side half of that pair against a
8900 /// regression that (a) promoted the baseline's `point_type` off
8901 /// `Gate` (silently flipping every unadorned Process's convergent-
8902 /// by-default output-side posture to diffusive), (b) dropped the
8903 /// projection call, (c) inverted the projection, or (d) crossed
8904 /// wires with [`ConvergencePointType::input_arity`] (which would
8905 /// flip the baseline answer from `One` to `Many` for `Gate`).
8906 #[test]
8907 fn has_output_arity_probes_one_only_on_absent_classification() {
8908 let spec = empty_ephemeral();
8909 assert!(spec.classification.is_none());
8910 for kind in Arity::ALL {
8911 let expected = kind == Arity::One;
8912 assert_eq!(
8913 spec.has_output_arity(kind),
8914 expected,
8915 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One): query {kind:?} must be {expected}",
8916 );
8917 }
8918 }
8919
8920 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8921 /// identically through [`Self::has_output_arity`] AND through
8922 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
8923 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8924 /// classification, `Some(_)` classification on every
8925 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
8926 /// so a future regression on either side of the resolver fails HERE
8927 /// at the parity boundary. Byte-for-byte peer of the seven sibling
8928 /// two-surface parity pins on the SAME `Cow`-resolver carrier — the
8929 /// EIGHTH classification-axis two-surface parity contract on the
8930 /// ephemeral surface, closing the SECOND occupant of the (Option-
8931 /// parent × NESTED-STRUCT-scalar-child × derived-typed-projection)
8932 /// corner.
8933 #[test]
8934 fn has_output_arity_matches_point_peer_through_lowered_classification() {
8935 // Absent classification: both surfaces resolve through the SAME
8936 // default and agree on every variant.
8937 let eph = empty_ephemeral();
8938 let lowered: ProcessSpec = eph.clone().into();
8939 for query in Arity::ALL {
8940 assert_eq!(
8941 eph.has_output_arity(query),
8942 lowered.classification.has_output_arity(query),
8943 "None-classification parity drift on query {query:?}",
8944 );
8945 }
8946 // Authored classification: both surfaces read the same authored
8947 // point_type and route through the same projection.
8948 for populated in ConvergencePointType::ALL {
8949 let mut classification = Classification::gate_compute();
8950 classification.point_type = populated;
8951 let mut eph = empty_ephemeral();
8952 eph.classification = Some(classification);
8953 let lowered: ProcessSpec = eph.clone().into();
8954 for query in Arity::ALL {
8955 assert_eq!(
8956 eph.has_output_arity(query),
8957 lowered.classification.has_output_arity(query),
8958 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8959 );
8960 }
8961 }
8962 }
8963
8964 /// DAG-COMPOSITION ARITY-PAIR pin — the SEVENTH
8965 /// ([`Self::has_input_arity`]) and EIGHTH
8966 /// ([`Self::has_output_arity`]) classification-axis peers on the
8967 /// ephemeral surface walk the SAME `point_type` scalar carrier
8968 /// (routed through the SAME [`Self::resolved_classification`]
8969 /// resolver) through the SAME [`Arity`] closed set but through
8970 /// DIFFERENT typed projections
8971 /// ([`ConvergencePointType::input_arity`] vs.
8972 /// [`ConvergencePointType::output_arity`]). An [`EphemeralSpec`]
8973 /// with `classification.point_type = Fork` (the diffusive `(One,
8974 /// Many)` cell) MUST simultaneously answer `has_input_arity(One)`
8975 /// true AND `has_output_arity(Many)` true AND
8976 /// `has_input_arity(Many)` false AND `has_output_arity(One)` false.
8977 /// An [`EphemeralSpec`] with `point_type = Transform` (endomorphic
8978 /// `(One, One)`) MUST answer BOTH `has_input_arity(One)` and
8979 /// `has_output_arity(One)` true — the two projections AGREE in the
8980 /// endomorphic bucket. The absent-classification baseline (Gate,
8981 /// convergent `(Many, One)`) MUST answer
8982 /// `has_input_arity(Many)` true AND `has_output_arity(One)` true —
8983 /// the mirror of the Fork case. A regression that (a) collapsed
8984 /// `has_output_arity` onto `has_input_arity`, (b) swapped the
8985 /// projection direction, or (c) drifted the topology-bucket
8986 /// contract fails HERE at ONE narrow ephemeral-surface site,
8987 /// symmetric with the point-surface DAG-composition arity-pair pin.
8988 #[test]
8989 fn has_input_arity_and_has_output_arity_pin_dag_composition_pair() {
8990 // Diffusive cell: Fork carries (input, output) = (One, Many)
8991 let mut classification = Classification::gate_compute();
8992 classification.point_type = ConvergencePointType::Fork;
8993 let mut fork = empty_ephemeral();
8994 fork.classification = Some(classification);
8995 assert!(fork.has_input_arity(Arity::One));
8996 assert!(fork.has_output_arity(Arity::Many));
8997 assert!(!fork.has_input_arity(Arity::Many));
8998 assert!(!fork.has_output_arity(Arity::One));
8999
9000 // Endomorphic cell: Transform carries (input, output) = (One, One)
9001 let mut classification = Classification::gate_compute();
9002 classification.point_type = ConvergencePointType::Transform;
9003 let mut transform = empty_ephemeral();
9004 transform.classification = Some(classification);
9005 assert!(transform.has_input_arity(Arity::One));
9006 assert!(transform.has_output_arity(Arity::One));
9007 assert!(!transform.has_input_arity(Arity::Many));
9008 assert!(!transform.has_output_arity(Arity::Many));
9009
9010 // Convergent cell: absent classification defaults to Gate,
9011 // which carries (input, output) = (Many, One).
9012 let gate = empty_ephemeral();
9013 assert!(gate.classification.is_none());
9014 assert!(gate.has_input_arity(Arity::Many));
9015 assert!(gate.has_output_arity(Arity::One));
9016 assert!(!gate.has_input_arity(Arity::One));
9017 assert!(!gate.has_output_arity(Arity::Many));
9018 }
9019
9020 // ── EphemeralSpec::horizon_terminates pins ───────────────────────
9021 //
9022 // Fail-before-pass-after granularity: `horizon_terminates` did not
9023 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9024 // the "does this ephemeral spec's horizon terminate?" question
9025 // went through `.resolved_classification().horizon.kind.terminates()`
9026 // or through the lowered `ProcessSpec`'s
9027 // `spec.classification.horizon.kind.terminates()`. Post-lift the
9028 // NINTH classification-axis peer on the ephemeral surface routes
9029 // through the SAME [`Self::resolved_classification`] resolver +
9030 // the sibling substrate primitive
9031 // [`crate::classification::Classification::horizon_terminates`],
9032 // so the two-surface parity contract holds by construction — a
9033 // regression on either side of the resolver fails at these pins
9034 // before landing at the operator-facing `terminating-horizon`
9035 // fixed tag in `tatara-check`.
9036
9037 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9038 /// [`Classification`] carries a specific [`HorizonKind`] variant
9039 /// answers [`Self::horizon_terminates`] matching the closed
9040 /// set's own [`HorizonKind::terminates`] truth table. Sweep
9041 /// [`HorizonKind::ALL`] so a regression that (a) hard-coded the
9042 /// body to a fixed answer, (b) inverted the projection, or (c)
9043 /// crossed the wires with the antisymmetric partner
9044 /// [`HorizonKind::requires_metric_axes`] fails HERE at the
9045 /// substrate primitive before drifting through the
9046 /// `terminating-horizon` fixed tag or the peer point surface.
9047 #[test]
9048 fn horizon_terminates_returns_horizon_kind_projection_per_kind() {
9049 for populated in HorizonKind::ALL {
9050 let classification = Classification::gate_compute_with_axis(populated);
9051 let mut spec = empty_ephemeral();
9052 spec.classification = Some(classification);
9053 assert_eq!(
9054 spec.horizon_terminates(),
9055 populated.terminates(),
9056 "authored horizon.kind={populated:?}: horizon_terminates() drift",
9057 );
9058 }
9059 }
9060
9061 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9062 /// with `classification: None` routes through the
9063 /// [`Self::resolved_classification`] resolver's substrate default
9064 /// [`Classification::gate_compute`], which uses
9065 /// [`crate::classification::Horizon::default`] whose `kind`
9066 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
9067 /// [`HorizonKind::Bounded::terminates`] projects `true`, so
9068 /// [`Self::horizon_terminates`] returns `true`. Pins the default-
9069 /// arm short-circuit through THREE layers of `Default`
9070 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
9071 /// [`HorizonKind::default`]) reaching this derived-nullary
9072 /// predicate — a regression that dropped the resolver hop
9073 /// (silently answering `false` on an absent classification, as
9074 /// if the operator's absence meant "no horizon at all") fails
9075 /// HERE at ONE narrow ephemeral-surface site.
9076 #[test]
9077 fn horizon_terminates_probes_true_on_absent_classification() {
9078 let spec = empty_ephemeral();
9079 assert!(spec.classification.is_none());
9080 assert!(
9081 spec.horizon_terminates(),
9082 "absent classification (defaults to gate_compute, horizon.kind=Bounded → terminates=true)",
9083 );
9084 }
9085
9086 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9087 /// identically through [`Self::horizon_terminates`] AND through
9088 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_terminates()`
9089 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9090 /// classification, `Some(_)` classification on every
9091 /// [`HorizonKind::ALL`] variant) so a future regression on
9092 /// either side of the resolver fails HERE at the parity
9093 /// boundary. Byte-for-byte peer of the eight sibling two-surface
9094 /// parity pins on the SAME `Cow`-resolver carrier — the NINTH
9095 /// classification-axis two-surface parity contract on the
9096 /// ephemeral surface, and the FIRST via a derived-nullary-
9097 /// boolean predicate rather than a variant-equality probe.
9098 #[test]
9099 fn horizon_terminates_matches_point_peer_through_lowered_classification() {
9100 // Absent classification: both surfaces resolve through the SAME
9101 // default and agree.
9102 let eph = empty_ephemeral();
9103 let lowered: ProcessSpec = eph.clone().into();
9104 assert_eq!(
9105 eph.horizon_terminates(),
9106 lowered.classification.horizon_terminates(),
9107 "None-classification parity drift",
9108 );
9109 // Authored classification: both surfaces read the same authored
9110 // horizon.kind and route through the same projection.
9111 for populated in HorizonKind::ALL {
9112 let classification = Classification::gate_compute_with_axis(populated);
9113 let mut eph = empty_ephemeral();
9114 eph.classification = Some(classification);
9115 let lowered: ProcessSpec = eph.clone().into();
9116 assert_eq!(
9117 eph.horizon_terminates(),
9118 lowered.classification.horizon_terminates(),
9119 "authored horizon.kind={populated:?}: parity drift",
9120 );
9121 }
9122 }
9123
9124 // ── EphemeralSpec::horizon_requires_metric_axes pins ─────────────
9125 //
9126 // Fail-before-pass-after granularity: `horizon_requires_metric_axes`
9127 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9128 // walking the "does this ephemeral spec's horizon require metric
9129 // axes?" question went through
9130 // `.resolved_classification().horizon.kind.requires_metric_axes()`
9131 // or through the lowered `ProcessSpec`'s
9132 // `spec.classification.horizon.kind.requires_metric_axes()`. Post-
9133 // lift the antisymmetric peer of `horizon_terminates` routes
9134 // through the SAME [`Self::resolved_classification`] resolver +
9135 // the sibling substrate primitive
9136 // [`crate::classification::Classification::horizon_requires_metric_axes`],
9137 // so the two-surface parity contract holds by construction — a
9138 // regression on either side of the resolver fails at these pins
9139 // before landing at the operator-facing `metric-axes-required`
9140 // fixed tag in `tatara-check`.
9141
9142 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9143 /// [`Classification`] carries a specific [`HorizonKind`] variant
9144 /// answers [`Self::horizon_requires_metric_axes`] matching the
9145 /// closed set's own [`HorizonKind::requires_metric_axes`] truth
9146 /// table. Sweep [`HorizonKind::ALL`] so a regression that (a)
9147 /// hard-coded the body to a fixed answer, (b) inverted the
9148 /// projection, or (c) crossed the wires with the antisymmetric
9149 /// partner [`HorizonKind::terminates`] fails HERE at the
9150 /// substrate primitive before drifting through the
9151 /// `metric-axes-required` fixed tag or the peer point surface.
9152 #[test]
9153 fn horizon_requires_metric_axes_returns_horizon_kind_projection_per_kind() {
9154 for populated in HorizonKind::ALL {
9155 let classification = Classification::gate_compute_with_axis(populated);
9156 let mut spec = empty_ephemeral();
9157 spec.classification = Some(classification);
9158 assert_eq!(
9159 spec.horizon_requires_metric_axes(),
9160 populated.requires_metric_axes(),
9161 "authored horizon.kind={populated:?}: horizon_requires_metric_axes() drift",
9162 );
9163 }
9164 }
9165
9166 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9167 /// with `classification: None` routes through the
9168 /// [`Self::resolved_classification`] resolver's substrate default
9169 /// [`Classification::gate_compute`], which uses
9170 /// [`crate::classification::Horizon::default`] whose `kind`
9171 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
9172 /// [`HorizonKind::Bounded::requires_metric_axes`] projects
9173 /// `false`, so [`Self::horizon_requires_metric_axes`] returns
9174 /// `false`. Pins the default-arm short-circuit through THREE
9175 /// layers of `Default` ([`Classification::gate_compute`] →
9176 /// [`Horizon::default`] → [`HorizonKind::default`]) reaching this
9177 /// derived-nullary predicate — mirror image of
9178 /// `horizon_terminates_probes_true_on_absent_classification`.
9179 #[test]
9180 fn horizon_requires_metric_axes_probes_false_on_absent_classification() {
9181 let spec = empty_ephemeral();
9182 assert!(spec.classification.is_none());
9183 assert!(
9184 !spec.horizon_requires_metric_axes(),
9185 "absent classification (defaults to gate_compute, horizon.kind=Bounded → requires_metric_axes=false)",
9186 );
9187 }
9188
9189 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9190 /// identically through [`Self::horizon_requires_metric_axes`]
9191 /// AND through
9192 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_requires_metric_axes()`
9193 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9194 /// classification, `Some(_)` classification on every
9195 /// [`HorizonKind::ALL`] variant) so a future regression on
9196 /// either side of the resolver fails HERE at the parity
9197 /// boundary. Byte-for-byte peer of the sibling
9198 /// `horizon_terminates_matches_point_peer_through_lowered_classification`.
9199 #[test]
9200 fn horizon_requires_metric_axes_matches_point_peer_through_lowered_classification() {
9201 // Absent classification.
9202 let eph = empty_ephemeral();
9203 let lowered: ProcessSpec = eph.clone().into();
9204 assert_eq!(
9205 eph.horizon_requires_metric_axes(),
9206 lowered.classification.horizon_requires_metric_axes(),
9207 "None-classification parity drift",
9208 );
9209 // Authored classification.
9210 for populated in HorizonKind::ALL {
9211 let classification = Classification::gate_compute_with_axis(populated);
9212 let mut eph = empty_ephemeral();
9213 eph.classification = Some(classification);
9214 let lowered: ProcessSpec = eph.clone().into();
9215 assert_eq!(
9216 eph.horizon_requires_metric_axes(),
9217 lowered.classification.horizon_requires_metric_axes(),
9218 "authored horizon.kind={populated:?}: parity drift",
9219 );
9220 }
9221 }
9222
9223 // ── EphemeralSpec::calm_requires_coordination pins ───────────────
9224 //
9225 // Fail-before-pass-after granularity: `calm_requires_coordination`
9226 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9227 // walking the "does this ephemeral spec require coordination?"
9228 // question went through
9229 // `.resolved_classification().calm.requires_coordination()` or
9230 // through the lowered `ProcessSpec`'s
9231 // `spec.classification.calm.requires_coordination()`. Post-lift the
9232 // THIRD derived-nullary-boolean peer on the ephemeral surface
9233 // (first on the calm axis, after the two horizon-axis peers)
9234 // routes through the SAME [`Self::resolved_classification`]
9235 // resolver + the sibling substrate primitive
9236 // [`crate::classification::Classification::calm_requires_coordination`],
9237 // so the two-surface parity contract holds by construction — a
9238 // regression on either side of the resolver fails at these pins
9239 // before landing at the operator-facing `coordination-required`
9240 // fixed tag in `tatara-check`.
9241
9242 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9243 /// [`Classification`] carries a specific [`CalmClassification`]
9244 /// variant answers [`Self::calm_requires_coordination`] matching
9245 /// the closed set's own
9246 /// [`CalmClassification::requires_coordination`] truth table.
9247 /// Sweep [`CalmClassification::ALL`] so a regression that (a)
9248 /// hard-coded the body to a fixed answer, (b) inverted the
9249 /// projection, or (c) crossed the wires with a sibling
9250 /// classification-axis probe fails HERE at the substrate primitive
9251 /// before drifting through the `coordination-required` fixed tag
9252 /// or the peer point surface.
9253 #[test]
9254 fn calm_requires_coordination_returns_calm_projection_per_kind() {
9255 for populated in CalmClassification::ALL {
9256 let mut classification = Classification::gate_compute();
9257 classification.calm = populated;
9258 let mut spec = empty_ephemeral();
9259 spec.classification = Some(classification);
9260 assert_eq!(
9261 spec.calm_requires_coordination(),
9262 populated.requires_coordination(),
9263 "authored calm={populated:?}: calm_requires_coordination() drift",
9264 );
9265 }
9266 }
9267
9268 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9269 /// with `classification: None` routes through the
9270 /// [`Self::resolved_classification`] resolver's substrate default
9271 /// [`Classification::gate_compute`], which carries
9272 /// [`CalmClassification::default = Monotone`], and
9273 /// [`CalmClassification::Monotone::requires_coordination`] projects
9274 /// `false`, so [`Self::calm_requires_coordination`] returns
9275 /// `false`. Pins the default-arm short-circuit through TWO layers
9276 /// of `Default` ([`Classification::gate_compute`] →
9277 /// [`CalmClassification::default`]) reaching this derived-nullary
9278 /// predicate — distinct from the sibling `horizon_*` absent-
9279 /// classification pins by ONE structural degree (those walk THREE
9280 /// layers of `Default` because horizon has a nested-struct wrapper;
9281 /// this walks TWO because `calm` is a direct scalar). A regression
9282 /// that dropped the resolver hop (silently answering `true` on an
9283 /// absent classification, as if the operator's absence meant
9284 /// "requires coordination") fails HERE at ONE narrow ephemeral-
9285 /// surface site.
9286 #[test]
9287 fn calm_requires_coordination_probes_false_on_absent_classification() {
9288 let spec = empty_ephemeral();
9289 assert!(spec.classification.is_none());
9290 assert!(
9291 !spec.calm_requires_coordination(),
9292 "absent classification (defaults to gate_compute, calm=Monotone → requires_coordination=false)",
9293 );
9294 }
9295
9296 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9297 /// identically through [`Self::calm_requires_coordination`] AND
9298 /// through
9299 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_requires_coordination()`
9300 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9301 /// classification, `Some(_)` classification on every
9302 /// [`CalmClassification::ALL`] variant) so a future regression on
9303 /// either side of the resolver fails HERE at the parity boundary.
9304 /// Byte-for-byte peer of the sibling
9305 /// `horizon_terminates_matches_point_peer_through_lowered_classification`
9306 /// on the calm axis.
9307 #[test]
9308 fn calm_requires_coordination_matches_point_peer_through_lowered_classification() {
9309 // Absent classification.
9310 let eph = empty_ephemeral();
9311 let lowered: ProcessSpec = eph.clone().into();
9312 assert_eq!(
9313 eph.calm_requires_coordination(),
9314 lowered.classification.calm_requires_coordination(),
9315 "None-classification parity drift",
9316 );
9317 // Authored classification.
9318 for populated in CalmClassification::ALL {
9319 let mut classification = Classification::gate_compute();
9320 classification.calm = populated;
9321 let mut eph = empty_ephemeral();
9322 eph.classification = Some(classification);
9323 let lowered: ProcessSpec = eph.clone().into();
9324 assert_eq!(
9325 eph.calm_requires_coordination(),
9326 lowered.classification.calm_requires_coordination(),
9327 "authored calm={populated:?}: parity drift",
9328 );
9329 }
9330 }
9331
9332 // ── EphemeralSpec::data_is_regulated pins ────────────────────────
9333 //
9334 // Fail-before-pass-after granularity: `data_is_regulated` did not
9335 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9336 // the "does this ephemeral spec carry regulated data?" question
9337 // went through
9338 // `.resolved_classification().data_classification.is_regulated()`
9339 // or through the lowered `ProcessSpec`'s
9340 // `spec.classification.data_classification.is_regulated()`. Post-
9341 // lift the FOURTH derived-nullary-boolean peer on the ephemeral
9342 // surface (first on the data axis, after two horizon-axis peers
9343 // and one calm-axis peer) routes through the SAME
9344 // [`Self::resolved_classification`] resolver + the sibling
9345 // substrate primitive
9346 // [`crate::classification::Classification::data_is_regulated`],
9347 // so the two-surface parity contract holds by construction — a
9348 // regression on either side of the resolver fails at these pins
9349 // before landing at the operator-facing `data-regulated` fixed
9350 // tag in `tatara-check`.
9351
9352 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9353 /// [`Classification`] carries a specific [`DataClassification`]
9354 /// variant answers [`Self::data_is_regulated`] matching the
9355 /// closed set's own [`DataClassification::is_regulated`] truth
9356 /// table. Sweep [`DataClassification::ALL`] so a regression that
9357 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9358 /// projection, or (c) crossed the wires with a sibling
9359 /// classification-axis probe fails HERE at the substrate
9360 /// primitive before drifting through the `data-regulated` fixed
9361 /// tag or the peer point surface.
9362 #[test]
9363 fn data_is_regulated_returns_data_classification_projection_per_kind() {
9364 for populated in DataClassification::ALL {
9365 let mut classification = Classification::gate_compute();
9366 classification.data_classification = populated;
9367 let mut spec = empty_ephemeral();
9368 spec.classification = Some(classification);
9369 assert_eq!(
9370 spec.data_is_regulated(),
9371 populated.is_regulated(),
9372 "authored data_classification={populated:?}: data_is_regulated() drift",
9373 );
9374 }
9375 }
9376
9377 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9378 /// with `classification: None` routes through the
9379 /// [`Self::resolved_classification`] resolver's substrate default
9380 /// [`Classification::gate_compute`], which carries
9381 /// [`DataClassification::default = Internal`], and
9382 /// [`DataClassification::Internal::is_regulated`] projects
9383 /// `false`, so [`Self::data_is_regulated`] returns `false`. Pins
9384 /// the default-arm short-circuit through TWO layers of `Default`
9385 /// ([`Classification::gate_compute`] →
9386 /// [`DataClassification::default`]) reaching this derived-nullary
9387 /// predicate — byte-for-byte structural peer of the sibling
9388 /// `calm_requires_coordination_probes_false_on_absent_classification`
9389 /// on the classification-data axis, distinct from the two
9390 /// `horizon_*` absent-classification pins by ONE structural
9391 /// degree (those walk THREE layers because horizon has a nested-
9392 /// struct wrapper; this walks TWO because `data_classification`
9393 /// is a direct scalar). A regression that dropped the resolver
9394 /// hop (silently answering `true` on an absent classification,
9395 /// as if the operator's absence meant "regulated data") fails
9396 /// HERE at ONE narrow ephemeral-surface site.
9397 #[test]
9398 fn data_is_regulated_probes_false_on_absent_classification() {
9399 let spec = empty_ephemeral();
9400 assert!(spec.classification.is_none());
9401 assert!(
9402 !spec.data_is_regulated(),
9403 "absent classification (defaults to gate_compute, data_classification=Internal → is_regulated=false)",
9404 );
9405 }
9406
9407 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9408 /// identically through [`Self::data_is_regulated`] AND through
9409 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_regulated()`
9410 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9411 /// classification, `Some(_)` classification on every
9412 /// [`DataClassification::ALL`] variant) so a future regression on
9413 /// either side of the resolver fails HERE at the parity boundary.
9414 /// Byte-for-byte peer of the sibling
9415 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
9416 /// on the data axis.
9417 #[test]
9418 fn data_is_regulated_matches_point_peer_through_lowered_classification() {
9419 // Absent classification.
9420 let eph = empty_ephemeral();
9421 let lowered: ProcessSpec = eph.clone().into();
9422 assert_eq!(
9423 eph.data_is_regulated(),
9424 lowered.classification.data_is_regulated(),
9425 "None-classification parity drift",
9426 );
9427 // Authored classification.
9428 for populated in DataClassification::ALL {
9429 let mut classification = Classification::gate_compute();
9430 classification.data_classification = populated;
9431 let mut eph = empty_ephemeral();
9432 eph.classification = Some(classification);
9433 let lowered: ProcessSpec = eph.clone().into();
9434 assert_eq!(
9435 eph.data_is_regulated(),
9436 lowered.classification.data_is_regulated(),
9437 "authored data_classification={populated:?}: parity drift",
9438 );
9439 }
9440 }
9441
9442 // ── EphemeralSpec::data_is_restricted pins ───────────────────────
9443 //
9444 // Fail-before-pass-after granularity: `data_is_restricted` did not
9445 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9446 // the "does this ephemeral spec require access controls?" question
9447 // went through
9448 // `.resolved_classification().data_classification.is_restricted()`
9449 // or through the lowered `ProcessSpec`'s
9450 // `spec.classification.data_classification.is_restricted()`. Post-
9451 // lift the FIFTH derived-nullary-boolean peer on the ephemeral
9452 // surface (second on the data axis, after
9453 // [`Self::data_is_regulated`] opened the axis) routes through the
9454 // SAME [`Self::resolved_classification`] resolver + the sibling
9455 // substrate primitive
9456 // [`crate::classification::Classification::data_is_restricted`],
9457 // so the two-surface parity contract holds by construction — a
9458 // regression on either side of the resolver fails at these pins
9459 // before landing at the operator-facing `data-restricted` fixed
9460 // tag in `tatara-check`. FIRST direct-scalar ephemeral-surface
9461 // peer whose absent-classification baseline projects to `true`
9462 // rather than `false`.
9463
9464 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9465 /// [`Classification`] carries a specific [`DataClassification`]
9466 /// variant answers [`Self::data_is_restricted`] matching the
9467 /// closed set's own [`DataClassification::is_restricted`] truth
9468 /// table. Sweep [`DataClassification::ALL`] so a regression that
9469 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9470 /// projection, or (c) crossed the wires with the sibling
9471 /// [`DataClassification::is_regulated`] projection fails HERE at
9472 /// the substrate primitive before drifting through the
9473 /// `data-restricted` fixed tag or the peer point surface.
9474 #[test]
9475 fn data_is_restricted_returns_data_classification_projection_per_kind() {
9476 for populated in DataClassification::ALL {
9477 let mut classification = Classification::gate_compute();
9478 classification.data_classification = populated;
9479 let mut spec = empty_ephemeral();
9480 spec.classification = Some(classification);
9481 assert_eq!(
9482 spec.data_is_restricted(),
9483 populated.is_restricted(),
9484 "authored data_classification={populated:?}: data_is_restricted() drift",
9485 );
9486 }
9487 }
9488
9489 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9490 /// with `classification: None` routes through the
9491 /// [`Self::resolved_classification`] resolver's substrate default
9492 /// [`Classification::gate_compute`], which carries
9493 /// [`DataClassification::default = Internal`], and
9494 /// [`DataClassification::Internal::is_restricted`] projects
9495 /// `true`, so [`Self::data_is_restricted`] returns `true`. Pins
9496 /// the default-arm short-circuit through TWO layers of `Default`
9497 /// ([`Classification::gate_compute`] →
9498 /// [`DataClassification::default`]) reaching this derived-nullary
9499 /// predicate. FIRST direct-scalar ephemeral-surface peer whose
9500 /// absent-classification baseline answers `true`, not `false`
9501 /// (the four earlier direct-scalar peers on this surface —
9502 /// `data_is_regulated`, `calm_requires_coordination`, plus the
9503 /// nested-struct `horizon_requires_metric_axes` — all project
9504 /// `false` on the same absent classification, and only the
9505 /// sibling nested-struct `horizon_terminates` projects `true`).
9506 /// A regression that dropped the resolver hop (silently answering
9507 /// `false` on an absent classification, as if the operator's
9508 /// absence meant "freely distributable"), or that inverted the
9509 /// projection while the closed-set primitive stayed intact,
9510 /// fails HERE at ONE narrow ephemeral-surface site.
9511 #[test]
9512 fn data_is_restricted_probes_true_on_absent_classification() {
9513 let spec = empty_ephemeral();
9514 assert!(spec.classification.is_none());
9515 assert!(
9516 spec.data_is_restricted(),
9517 "absent classification (defaults to gate_compute, data_classification=Internal → is_restricted=true)",
9518 );
9519 }
9520
9521 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9522 /// identically through [`Self::data_is_restricted`] AND through
9523 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_restricted()`
9524 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9525 /// classification, `Some(_)` classification on every
9526 /// [`DataClassification::ALL`] variant) so a future regression on
9527 /// either side of the resolver fails HERE at the parity boundary.
9528 /// Byte-for-byte peer of the sibling
9529 /// `data_is_regulated_matches_point_peer_through_lowered_classification`
9530 /// on the same classification-data axis, published a second time
9531 /// through the antisymmetric closed-set projection.
9532 #[test]
9533 fn data_is_restricted_matches_point_peer_through_lowered_classification() {
9534 // Absent classification.
9535 let eph = empty_ephemeral();
9536 let lowered: ProcessSpec = eph.clone().into();
9537 assert_eq!(
9538 eph.data_is_restricted(),
9539 lowered.classification.data_is_restricted(),
9540 "None-classification parity drift",
9541 );
9542 // Authored classification.
9543 for populated in DataClassification::ALL {
9544 let mut classification = Classification::gate_compute();
9545 classification.data_classification = populated;
9546 let mut eph = empty_ephemeral();
9547 eph.classification = Some(classification);
9548 let lowered: ProcessSpec = eph.clone().into();
9549 assert_eq!(
9550 eph.data_is_restricted(),
9551 lowered.classification.data_is_restricted(),
9552 "authored data_classification={populated:?}: parity drift",
9553 );
9554 }
9555 }
9556
9557 /// COMPOSED IMPLICATION pin — the ephemeral-surface counterpart of
9558 /// the closed-set-internal
9559 /// `data_classification_regulated_implies_restricted` and its
9560 /// parent-composed peer
9561 /// `classification_data_is_regulated_implies_data_is_restricted_over_all`:
9562 /// for every ([`EphemeralSpec`] with authored classification
9563 /// carrying every [`DataClassification`] variant, plus the
9564 /// absent-classification case), the resolver-hop probe pair
9565 /// satisfies `data_is_regulated() ⇒ data_is_restricted()`. Pins
9566 /// the implication contract at the ephemeral-surface site so a
9567 /// regression that (a) inverted the ephemeral
9568 /// [`Self::data_is_regulated`] resolver hop, (b) inverted the
9569 /// ephemeral [`Self::data_is_restricted`] resolver hop, or (c)
9570 /// crossed their wires while the underlying substrate primitives
9571 /// stayed intact fails HERE. FIRST ephemeral-surface corner-peer
9572 /// pair whose two projections carry a non-trivial closed-set-
9573 /// internal implication relationship.
9574 #[test]
9575 fn ephemeral_data_is_regulated_implies_data_is_restricted_over_all() {
9576 // Absent classification.
9577 let eph = empty_ephemeral();
9578 assert!(
9579 !eph.data_is_regulated() || eph.data_is_restricted(),
9580 "None-classification: data_is_regulated ⇒ data_is_restricted violated",
9581 );
9582 // Authored classification.
9583 for populated in DataClassification::ALL {
9584 let mut classification = Classification::gate_compute();
9585 classification.data_classification = populated;
9586 let mut eph = empty_ephemeral();
9587 eph.classification = Some(classification);
9588 assert!(
9589 !eph.data_is_regulated() || eph.data_is_restricted(),
9590 "authored data_classification={populated:?}: data_is_regulated ⇒ data_is_restricted violated",
9591 );
9592 }
9593 }
9594
9595 // ── EphemeralSpec::point_is_endomorphic pins ─────────────────────
9596 //
9597 // Fail-before-pass-after granularity: `point_is_endomorphic` did
9598 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9599 // walking the "does this ephemeral spec's point-type project to
9600 // the 1→1 endomorphic bucket?" question went through
9601 // `.resolved_classification().point_type.is_endomorphic()` or the
9602 // lowered `ProcessSpec`'s
9603 // `spec.classification.point_type.is_endomorphic()`. Post-lift the
9604 // SIXTH derived-nullary-boolean peer on the ephemeral surface
9605 // (first on the `point_type` axis) routes through the SAME
9606 // [`Self::resolved_classification`] resolver + the sibling
9607 // substrate primitive
9608 // [`crate::classification::Classification::point_is_endomorphic`],
9609 // so the two-surface parity contract holds by construction — a
9610 // regression on either side of the resolver fails at these pins
9611 // before landing at the operator-facing `endomorphic-point` fixed
9612 // tag in `tatara-check`.
9613
9614 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9615 /// [`Classification`] carries a specific [`ConvergencePointType`]
9616 /// variant answers [`Self::point_is_endomorphic`] matching the
9617 /// closed set's own [`ConvergencePointType::is_endomorphic`] truth
9618 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9619 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9620 /// projection, or (c) crossed the wires with the sibling
9621 /// [`ConvergencePointType::is_diffusive`] /
9622 /// [`ConvergencePointType::is_convergent`] projections fails
9623 /// HERE at the substrate primitive before drifting through the
9624 /// `endomorphic-point` fixed tag or the peer point surface.
9625 #[test]
9626 fn point_is_endomorphic_returns_point_type_projection_per_kind() {
9627 for populated in ConvergencePointType::ALL {
9628 let mut classification = Classification::gate_compute();
9629 classification.point_type = populated;
9630 let mut spec = empty_ephemeral();
9631 spec.classification = Some(classification);
9632 assert_eq!(
9633 spec.point_is_endomorphic(),
9634 populated.is_endomorphic(),
9635 "authored point_type={populated:?}: point_is_endomorphic() drift",
9636 );
9637 }
9638 }
9639
9640 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9641 /// with `classification: None` routes through the
9642 /// [`Self::resolved_classification`] resolver's substrate default
9643 /// [`Classification::gate_compute`], which carries
9644 /// [`ConvergencePointType::Gate`] (a convergent barrier, not an
9645 /// endomorphism), and
9646 /// [`ConvergencePointType::Gate::is_endomorphic`] projects `false`,
9647 /// so [`Self::point_is_endomorphic`] returns `false`. Pins the
9648 /// resolver's chosen-field baseline at ONE narrow site — a
9649 /// regression that dropped the resolver hop, or that promoted
9650 /// [`ConvergencePointType::Transform`] to the gate-compute
9651 /// baseline (silently retargeting every unadorned ephemeral
9652 /// spec's topology bucket), fails HERE at ONE narrow ephemeral-
9653 /// surface site. FIRST direct-scalar ephemeral-surface peer whose
9654 /// absent-classification baseline is a chosen-field answer on the
9655 /// resolver's [`Classification::gate_compute`] default rather
9656 /// than a substrate-`#[default]` short-circuit on the closed-set
9657 /// side ([`ConvergencePointType`] has no `impl Default`).
9658 #[test]
9659 fn point_is_endomorphic_probes_false_on_absent_classification() {
9660 let spec = empty_ephemeral();
9661 assert!(spec.classification.is_none());
9662 assert!(
9663 !spec.point_is_endomorphic(),
9664 "absent classification (defaults to gate_compute, point_type=Gate → is_endomorphic=false)",
9665 );
9666 }
9667
9668 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9669 /// identically through [`Self::point_is_endomorphic`] AND through
9670 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_endomorphic()`
9671 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9672 /// classification, `Some(_)` classification on every
9673 /// [`ConvergencePointType::ALL`] variant) so a future regression
9674 /// on either side of the resolver fails HERE at the parity
9675 /// boundary. Byte-for-byte peer of the sibling
9676 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
9677 /// on a DIFFERENT closed-set axis, published a first time through
9678 /// the `point_type` closed-set projection.
9679 #[test]
9680 fn point_is_endomorphic_matches_point_peer_through_lowered_classification() {
9681 // Absent classification.
9682 let eph = empty_ephemeral();
9683 let lowered: ProcessSpec = eph.clone().into();
9684 assert_eq!(
9685 eph.point_is_endomorphic(),
9686 lowered.classification.point_is_endomorphic(),
9687 "None-classification parity drift",
9688 );
9689 // Authored classification.
9690 for populated in ConvergencePointType::ALL {
9691 let mut classification = Classification::gate_compute();
9692 classification.point_type = populated;
9693 let mut eph = empty_ephemeral();
9694 eph.classification = Some(classification);
9695 let lowered: ProcessSpec = eph.clone().into();
9696 assert_eq!(
9697 eph.point_is_endomorphic(),
9698 lowered.classification.point_is_endomorphic(),
9699 "authored point_type={populated:?}: parity drift",
9700 );
9701 }
9702 }
9703
9704 // ── EphemeralSpec::point_is_diffusive pins ───────────────────────
9705 //
9706 // Fail-before-pass-after granularity: `point_is_diffusive` did not
9707 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9708 // the "does this ephemeral spec's point-type project to the 1→N
9709 // diffusive fan-out bucket?" question went through
9710 // `.resolved_classification().point_type.is_diffusive()` or the
9711 // lowered `ProcessSpec`'s
9712 // `spec.classification.point_type.is_diffusive()`. Post-lift the
9713 // SEVENTH derived-nullary-boolean peer on the ephemeral surface
9714 // (SECOND on the `point_type` axis) routes through the SAME
9715 // [`Self::resolved_classification`] resolver + the sibling
9716 // substrate primitive
9717 // [`crate::classification::Classification::point_is_diffusive`],
9718 // so the two-surface parity contract holds by construction.
9719
9720 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9721 /// [`Classification`] carries a specific [`ConvergencePointType`]
9722 /// variant answers [`Self::point_is_diffusive`] matching the
9723 /// closed set's own [`ConvergencePointType::is_diffusive`] truth
9724 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9725 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9726 /// projection, or (c) crossed the wires with the sibling
9727 /// [`ConvergencePointType::is_endomorphic`] /
9728 /// [`ConvergencePointType::is_convergent`] projections fails HERE
9729 /// at the substrate primitive before drifting through the
9730 /// `diffusive-point` fixed tag or the peer point surface.
9731 #[test]
9732 fn point_is_diffusive_returns_point_type_projection_per_kind() {
9733 for populated in ConvergencePointType::ALL {
9734 let mut classification = Classification::gate_compute();
9735 classification.point_type = populated;
9736 let mut spec = empty_ephemeral();
9737 spec.classification = Some(classification);
9738 assert_eq!(
9739 spec.point_is_diffusive(),
9740 populated.is_diffusive(),
9741 "authored point_type={populated:?}: point_is_diffusive() drift",
9742 );
9743 }
9744 }
9745
9746 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9747 /// with `classification: None` routes through the
9748 /// [`Self::resolved_classification`] resolver's substrate default
9749 /// [`Classification::gate_compute`], which carries
9750 /// [`ConvergencePointType::Gate`] (a convergent barrier, not a
9751 /// diffusive fan-out), and
9752 /// [`ConvergencePointType::Gate::is_diffusive`] projects `false`,
9753 /// so [`Self::point_is_diffusive`] returns `false`. Pins the
9754 /// resolver's chosen-field baseline at ONE narrow site.
9755 #[test]
9756 fn point_is_diffusive_probes_false_on_absent_classification() {
9757 let spec = empty_ephemeral();
9758 assert!(spec.classification.is_none());
9759 assert!(
9760 !spec.point_is_diffusive(),
9761 "absent classification (defaults to gate_compute, point_type=Gate → is_diffusive=false)",
9762 );
9763 }
9764
9765 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9766 /// identically through [`Self::point_is_diffusive`] AND through
9767 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_diffusive()`
9768 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9769 /// classification, `Some(_)` classification on every
9770 /// [`ConvergencePointType::ALL`] variant) so a future regression
9771 /// on either side of the resolver fails HERE at the parity
9772 /// boundary. Byte-for-byte peer of
9773 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
9774 /// on the SAME closed-set axis via a sibling projection.
9775 #[test]
9776 fn point_is_diffusive_matches_point_peer_through_lowered_classification() {
9777 // Absent classification.
9778 let eph = empty_ephemeral();
9779 let lowered: ProcessSpec = eph.clone().into();
9780 assert_eq!(
9781 eph.point_is_diffusive(),
9782 lowered.classification.point_is_diffusive(),
9783 "None-classification parity drift",
9784 );
9785 // Authored classification.
9786 for populated in ConvergencePointType::ALL {
9787 let mut classification = Classification::gate_compute();
9788 classification.point_type = populated;
9789 let mut eph = empty_ephemeral();
9790 eph.classification = Some(classification);
9791 let lowered: ProcessSpec = eph.clone().into();
9792 assert_eq!(
9793 eph.point_is_diffusive(),
9794 lowered.classification.point_is_diffusive(),
9795 "authored point_type={populated:?}: parity drift",
9796 );
9797 }
9798 }
9799
9800 /// MUTEX pin — [`Self::point_is_endomorphic`] AND
9801 /// [`Self::point_is_diffusive`] are NEVER simultaneously true for
9802 /// ANY [`EphemeralSpec`] (authored or defaulted), since the
9803 /// underlying [`ConvergencePointType`] closed set carves its
9804 /// eight variants into THREE disjoint buckets. Sweep the absent-
9805 /// classification case + every [`ConvergencePointType::ALL`]
9806 /// variant so a regression that crossed the wires between the
9807 /// two ephemeral-surface corner peers (one probe silently
9808 /// composing the wrong closed-set arm at the resolver-hop layer)
9809 /// fails HERE rather than at every downstream consumer that
9810 /// trusts the two probes partition the resolver's output into
9811 /// disjoint buckets. FIRST ephemeral-surface corner-peer pair on
9812 /// the `point_type` axis whose two projections carry a non-
9813 /// trivial closed-set-internal MUTEX relationship (distinct from
9814 /// the sibling `data`-axis pair whose two projections carry a
9815 /// non-trivial IMPLICATION relationship, sealed by
9816 /// `ephemeral_data_is_regulated_implies_data_is_restricted_over_all`).
9817 #[test]
9818 fn ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all() {
9819 // Absent classification.
9820 let eph = empty_ephemeral();
9821 assert!(
9822 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
9823 "None-classification: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
9824 );
9825 // Authored classification.
9826 for populated in ConvergencePointType::ALL {
9827 let mut classification = Classification::gate_compute();
9828 classification.point_type = populated;
9829 let mut eph = empty_ephemeral();
9830 eph.classification = Some(classification);
9831 assert!(
9832 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
9833 "authored point_type={populated:?}: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
9834 );
9835 }
9836 }
9837
9838 // ── EphemeralSpec::point_is_convergent pins ──────────────────────
9839 //
9840 // Fail-before-pass-after granularity: `point_is_convergent` did
9841 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9842 // walking the "does this ephemeral spec's point-type project to
9843 // the N→1 convergent fan-in bucket?" question went through
9844 // `.resolved_classification().point_type.is_convergent()` or the
9845 // lowered `ProcessSpec`'s
9846 // `spec.classification.point_type.is_convergent()`. Post-lift the
9847 // EIGHTH derived-nullary-boolean peer on the ephemeral surface
9848 // (THIRD on the `point_type` axis) routes through the SAME
9849 // [`Self::resolved_classification`] resolver + the sibling
9850 // substrate primitive
9851 // [`crate::classification::Classification::point_is_convergent`],
9852 // so the two-surface parity contract holds by construction, AND
9853 // the THREE `point_type`-axis peers on this surface close into
9854 // the FULL three-way XOR partition contract.
9855
9856 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9857 /// [`Classification`] carries a specific [`ConvergencePointType`]
9858 /// variant answers [`Self::point_is_convergent`] matching the
9859 /// closed set's own [`ConvergencePointType::is_convergent`] truth
9860 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9861 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9862 /// projection, or (c) crossed the wires with the sibling
9863 /// [`ConvergencePointType::is_endomorphic`] /
9864 /// [`ConvergencePointType::is_diffusive`] projections fails HERE
9865 /// at the substrate primitive before drifting through the
9866 /// `convergent-point` fixed tag or the peer point surface.
9867 #[test]
9868 fn point_is_convergent_returns_point_type_projection_per_kind() {
9869 for populated in ConvergencePointType::ALL {
9870 let mut classification = Classification::gate_compute();
9871 classification.point_type = populated;
9872 let mut spec = empty_ephemeral();
9873 spec.classification = Some(classification);
9874 assert_eq!(
9875 spec.point_is_convergent(),
9876 populated.is_convergent(),
9877 "authored point_type={populated:?}: point_is_convergent() drift",
9878 );
9879 }
9880 }
9881
9882 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9883 /// with `classification: None` routes through the
9884 /// [`Self::resolved_classification`] resolver's substrate default
9885 /// [`Classification::gate_compute`], which carries
9886 /// [`ConvergencePointType::Gate`] (the canonical convergent
9887 /// barrier), and [`ConvergencePointType::Gate::is_convergent`]
9888 /// projects `true`, so [`Self::point_is_convergent`] returns
9889 /// `true`. Pins the resolver's chosen-field baseline at ONE
9890 /// narrow site — FIRST direct-scalar ephemeral-surface peer whose
9891 /// absent-classification baseline projects `true` through the
9892 /// resolver's chosen-field answer, mirror-inverted from the two
9893 /// sibling `point_is_endomorphic` / `point_is_diffusive`
9894 /// ephemeral-surface baselines which both project `false`.
9895 #[test]
9896 fn point_is_convergent_probes_true_on_absent_classification() {
9897 let spec = empty_ephemeral();
9898 assert!(spec.classification.is_none());
9899 assert!(
9900 spec.point_is_convergent(),
9901 "absent classification (defaults to gate_compute, point_type=Gate → is_convergent=true)",
9902 );
9903 }
9904
9905 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9906 /// identically through [`Self::point_is_convergent`] AND through
9907 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_convergent()`
9908 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9909 /// classification, `Some(_)` classification on every
9910 /// [`ConvergencePointType::ALL`] variant) so a future regression
9911 /// on either side of the resolver fails HERE at the parity
9912 /// boundary. Byte-for-byte peer of
9913 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
9914 /// and
9915 /// `point_is_diffusive_matches_point_peer_through_lowered_classification`
9916 /// on the SAME closed-set axis via a sibling projection.
9917 #[test]
9918 fn point_is_convergent_matches_point_peer_through_lowered_classification() {
9919 // Absent classification.
9920 let eph = empty_ephemeral();
9921 let lowered: ProcessSpec = eph.clone().into();
9922 assert_eq!(
9923 eph.point_is_convergent(),
9924 lowered.classification.point_is_convergent(),
9925 "None-classification parity drift",
9926 );
9927 // Authored classification.
9928 for populated in ConvergencePointType::ALL {
9929 let mut classification = Classification::gate_compute();
9930 classification.point_type = populated;
9931 let mut eph = empty_ephemeral();
9932 eph.classification = Some(classification);
9933 let lowered: ProcessSpec = eph.clone().into();
9934 assert_eq!(
9935 eph.point_is_convergent(),
9936 lowered.classification.point_is_convergent(),
9937 "authored point_type={populated:?}: parity drift",
9938 );
9939 }
9940 }
9941
9942 /// THREE-WAY XOR PARTITION pin — for the absent-classification
9943 /// baseline AND every [`ConvergencePointType::ALL`] variant,
9944 /// EXACTLY ONE of [`Self::point_is_endomorphic`],
9945 /// [`Self::point_is_diffusive`], and [`Self::point_is_convergent`]
9946 /// returns `true`. Closes the mutex pair
9947 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`
9948 /// into the FULL ternary XOR partition contract on the ephemeral
9949 /// surface — the resolver-hop peer of the parent-composed
9950 /// `classification_point_type_probes_form_three_way_xor_partition_over_all`
9951 /// test. Guarantees the absent-classification case lands in the
9952 /// convergent bucket (`gate_compute` → Gate → is_convergent =
9953 /// true), so every unadorned `(defephemeral …)` audits under a
9954 /// definite non-empty topology bucket.
9955 #[test]
9956 fn ephemeral_point_type_probes_form_three_way_xor_partition_over_all() {
9957 // Absent classification.
9958 let eph = empty_ephemeral();
9959 let buckets = [
9960 eph.point_is_endomorphic(),
9961 eph.point_is_diffusive(),
9962 eph.point_is_convergent(),
9963 ];
9964 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9965 assert_eq!(
9966 hits, 1,
9967 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9968 );
9969 // Authored classification.
9970 for populated in ConvergencePointType::ALL {
9971 let mut classification = Classification::gate_compute();
9972 classification.point_type = populated;
9973 let mut eph = empty_ephemeral();
9974 eph.classification = Some(classification);
9975 let buckets = [
9976 eph.point_is_endomorphic(),
9977 eph.point_is_diffusive(),
9978 eph.point_is_convergent(),
9979 ];
9980 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9981 assert_eq!(
9982 hits, 1,
9983 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9984 );
9985 }
9986 }
9987
9988 // ── EphemeralSpec::substrate_is_resource pins ────────────────────
9989 //
9990 // Fail-before-pass-after granularity: `substrate_is_resource` did
9991 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9992 // walking the "does this ephemeral spec's substrate project to
9993 // the resource plane?" question went through
9994 // `.resolved_classification().substrate.is_resource()` or the
9995 // lowered `ProcessSpec`'s
9996 // `spec.classification.substrate.is_resource()`. Post-lift the
9997 // NINTH derived-nullary-boolean peer on the ephemeral surface
9998 // (FIRST on the `substrate` axis) routes through the SAME
9999 // [`Self::resolved_classification`] resolver + the sibling
10000 // substrate primitive
10001 // [`crate::classification::Classification::substrate_is_resource`],
10002 // so the two-surface parity contract holds by construction.
10003
10004 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10005 /// [`Classification`] carries a specific
10006 /// [`crate::classification::SubstrateType`] variant answers
10007 /// [`Self::substrate_is_resource`] matching the closed set's own
10008 /// [`crate::classification::SubstrateType::is_resource`] truth
10009 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10010 /// so a regression that (a) hard-coded the body to a fixed
10011 /// answer, (b) inverted the projection, or (c) crossed the wires
10012 /// with the sibling
10013 /// [`crate::classification::SubstrateType::is_policy`] /
10014 /// [`crate::classification::SubstrateType::is_telemetry`]
10015 /// projections fails HERE at the substrate primitive before
10016 /// drifting through the `resource-substrate` fixed tag or the
10017 /// peer point surface.
10018 #[test]
10019 fn substrate_is_resource_returns_substrate_projection_per_kind() {
10020 for populated in SubstrateType::ALL {
10021 let mut classification = Classification::gate_compute();
10022 classification.substrate = populated;
10023 let mut spec = empty_ephemeral();
10024 spec.classification = Some(classification);
10025 assert_eq!(
10026 spec.substrate_is_resource(),
10027 populated.is_resource(),
10028 "authored substrate={populated:?}: substrate_is_resource() drift",
10029 );
10030 }
10031 }
10032
10033 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10034 /// with `classification: None` routes through the
10035 /// [`Self::resolved_classification`] resolver's substrate default
10036 /// [`Classification::gate_compute`], which carries
10037 /// [`crate::classification::SubstrateType::Compute`] (the
10038 /// canonical resource-plane substrate), and
10039 /// [`crate::classification::SubstrateType::Compute::is_resource`]
10040 /// projects `true`, so [`Self::substrate_is_resource`] returns
10041 /// `true`. Pins the resolver's chosen-field baseline at ONE
10042 /// narrow site — mirror-aligned with the sibling
10043 /// `point_is_convergent_probes_true_on_absent_classification`
10044 /// baseline (both projections on `gate_compute` chosen fields
10045 /// answer `true`).
10046 #[test]
10047 fn substrate_is_resource_probes_true_on_absent_classification() {
10048 let spec = empty_ephemeral();
10049 assert!(spec.classification.is_none());
10050 assert!(
10051 spec.substrate_is_resource(),
10052 "absent classification (defaults to gate_compute, substrate=Compute → is_resource=true)",
10053 );
10054 }
10055
10056 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10057 /// identically through [`Self::substrate_is_resource`] AND through
10058 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_resource()`
10059 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10060 /// classification, `Some(_)` classification on every
10061 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10062 /// future regression on either side of the resolver fails HERE
10063 /// at the parity boundary. Byte-for-byte peer of
10064 /// `point_is_convergent_matches_point_peer_through_lowered_classification`
10065 /// on a sibling classification axis.
10066 #[test]
10067 fn substrate_is_resource_matches_point_peer_through_lowered_classification() {
10068 // Absent classification.
10069 let eph = empty_ephemeral();
10070 let lowered: ProcessSpec = eph.clone().into();
10071 assert_eq!(
10072 eph.substrate_is_resource(),
10073 lowered.classification.substrate_is_resource(),
10074 "None-classification parity drift",
10075 );
10076 // Authored classification.
10077 for populated in SubstrateType::ALL {
10078 let mut classification = Classification::gate_compute();
10079 classification.substrate = populated;
10080 let mut eph = empty_ephemeral();
10081 eph.classification = Some(classification);
10082 let lowered: ProcessSpec = eph.clone().into();
10083 assert_eq!(
10084 eph.substrate_is_resource(),
10085 lowered.classification.substrate_is_resource(),
10086 "authored substrate={populated:?}: parity drift",
10087 );
10088 }
10089 }
10090
10091 // ── EphemeralSpec::substrate_is_policy pins ──────────────────────
10092 //
10093 // Fail-before-pass-after granularity: `substrate_is_policy` did
10094 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10095 // walking the "does this ephemeral spec's substrate project to
10096 // the policy plane?" question went through
10097 // `.resolved_classification().substrate.is_policy()` or the
10098 // lowered `ProcessSpec`'s
10099 // `spec.classification.substrate.is_policy()`. Post-lift the
10100 // TENTH derived-nullary-boolean peer on the ephemeral surface
10101 // (SECOND on the `substrate` axis) routes through the SAME
10102 // [`Self::resolved_classification`] resolver + the sibling
10103 // substrate primitive
10104 // [`crate::classification::Classification::substrate_is_policy`],
10105 // so the two-surface parity contract holds by construction, AND
10106 // the two `substrate`-axis peers on this surface open the
10107 // MUTEX pair on the axis via
10108 // `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`.
10109
10110 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10111 /// [`Classification`] carries a specific
10112 /// [`crate::classification::SubstrateType`] variant answers
10113 /// [`Self::substrate_is_policy`] matching the closed set's own
10114 /// [`crate::classification::SubstrateType::is_policy`] truth
10115 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10116 /// so a regression that (a) hard-coded the body to a fixed
10117 /// answer, (b) inverted the projection, or (c) crossed the wires
10118 /// with the sibling
10119 /// [`crate::classification::SubstrateType::is_resource`] /
10120 /// [`crate::classification::SubstrateType::is_telemetry`]
10121 /// projections fails HERE at the substrate primitive before
10122 /// drifting through the `policy-substrate` fixed tag or the
10123 /// peer point surface.
10124 #[test]
10125 fn substrate_is_policy_returns_substrate_projection_per_kind() {
10126 for populated in SubstrateType::ALL {
10127 let mut classification = Classification::gate_compute();
10128 classification.substrate = populated;
10129 let mut spec = empty_ephemeral();
10130 spec.classification = Some(classification);
10131 assert_eq!(
10132 spec.substrate_is_policy(),
10133 populated.is_policy(),
10134 "authored substrate={populated:?}: substrate_is_policy() drift",
10135 );
10136 }
10137 }
10138
10139 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10140 /// with `classification: None` routes through the
10141 /// [`Self::resolved_classification`] resolver's substrate default
10142 /// [`Classification::gate_compute`], which carries
10143 /// [`crate::classification::SubstrateType::Compute`] (the
10144 /// canonical resource-plane substrate, NOT a policy plane), and
10145 /// [`crate::classification::SubstrateType::Compute::is_policy`]
10146 /// projects `false`, so [`Self::substrate_is_policy`] returns
10147 /// `false`. Pins the resolver's chosen-field baseline at ONE
10148 /// narrow site — mirror-inverted from the sibling
10149 /// `substrate_is_resource_probes_true_on_absent_classification`
10150 /// (both projections on `gate_compute`'s chosen `substrate`
10151 /// field, but the sibling answers `true` where this one
10152 /// answers `false` — the closed set's disjoint plane partition
10153 /// forbids both being true).
10154 #[test]
10155 fn substrate_is_policy_probes_false_on_absent_classification() {
10156 let spec = empty_ephemeral();
10157 assert!(spec.classification.is_none());
10158 assert!(
10159 !spec.substrate_is_policy(),
10160 "absent classification (defaults to gate_compute, substrate=Compute → is_policy=false)",
10161 );
10162 }
10163
10164 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10165 /// identically through [`Self::substrate_is_policy`] AND through
10166 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_policy()`
10167 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10168 /// classification, `Some(_)` classification on every
10169 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10170 /// future regression on either side of the resolver fails HERE
10171 /// at the parity boundary. Byte-for-byte peer of
10172 /// `substrate_is_resource_matches_point_peer_through_lowered_classification`
10173 /// on the SAME closed-set axis via a sibling projection.
10174 #[test]
10175 fn substrate_is_policy_matches_point_peer_through_lowered_classification() {
10176 // Absent classification.
10177 let eph = empty_ephemeral();
10178 let lowered: ProcessSpec = eph.clone().into();
10179 assert_eq!(
10180 eph.substrate_is_policy(),
10181 lowered.classification.substrate_is_policy(),
10182 "None-classification parity drift",
10183 );
10184 // Authored classification.
10185 for populated in SubstrateType::ALL {
10186 let mut classification = Classification::gate_compute();
10187 classification.substrate = populated;
10188 let mut eph = empty_ephemeral();
10189 eph.classification = Some(classification);
10190 let lowered: ProcessSpec = eph.clone().into();
10191 assert_eq!(
10192 eph.substrate_is_policy(),
10193 lowered.classification.substrate_is_policy(),
10194 "authored substrate={populated:?}: parity drift",
10195 );
10196 }
10197 }
10198
10199 /// MUTEX pin — [`Self::substrate_is_resource`] AND
10200 /// [`Self::substrate_is_policy`] are NEVER simultaneously true
10201 /// for ANY [`EphemeralSpec`] (authored or defaulted), since the
10202 /// underlying [`crate::classification::SubstrateType`] closed set
10203 /// carves its eight variants into THREE disjoint buckets. Sweep
10204 /// the absent-classification case + every
10205 /// [`crate::classification::SubstrateType::ALL`] variant so a
10206 /// regression that crossed the wires between the two ephemeral-
10207 /// surface corner peers (one probe silently composing the wrong
10208 /// closed-set arm at the resolver-hop layer) fails HERE rather
10209 /// than at every downstream consumer that trusts the two probes
10210 /// partition the resolver's output into disjoint buckets.
10211 /// FIRST ephemeral-surface `substrate`-axis corner-peer pair
10212 /// carrying a non-trivial MUTEX relationship — structural twin
10213 /// of the sibling `point_type`-axis MUTEX pair sealed on this
10214 /// surface by
10215 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
10216 #[test]
10217 fn ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all() {
10218 // Absent classification.
10219 let eph = empty_ephemeral();
10220 assert!(
10221 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
10222 "None-classification: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
10223 );
10224 // Authored classification.
10225 for populated in SubstrateType::ALL {
10226 let mut classification = Classification::gate_compute();
10227 classification.substrate = populated;
10228 let mut eph = empty_ephemeral();
10229 eph.classification = Some(classification);
10230 assert!(
10231 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
10232 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
10233 );
10234 }
10235 }
10236
10237 // ── EphemeralSpec::substrate_is_telemetry pins ───────────────────
10238 //
10239 // Fail-before-pass-after granularity: `substrate_is_telemetry`
10240 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10241 // walking the "does this ephemeral spec's substrate project to
10242 // the telemetry plane?" question went through
10243 // `.resolved_classification().substrate.is_telemetry()` or the
10244 // lowered `ProcessSpec`'s
10245 // `spec.classification.substrate.is_telemetry()`. Post-lift the
10246 // ELEVENTH derived-nullary-boolean peer on the ephemeral surface
10247 // (THIRD on the `substrate` axis) routes through the SAME
10248 // [`Self::resolved_classification`] resolver + the sibling
10249 // substrate primitive
10250 // [`crate::classification::Classification::substrate_is_telemetry`],
10251 // so the two-surface parity contract holds by construction, AND
10252 // the three `substrate`-axis peers on this surface CLOSE the
10253 // axis into the FULL three-way XOR partition contract via
10254 // `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
10255
10256 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10257 /// [`Classification`] carries a specific
10258 /// [`crate::classification::SubstrateType`] variant answers
10259 /// [`Self::substrate_is_telemetry`] matching the closed set's own
10260 /// [`crate::classification::SubstrateType::is_telemetry`] truth
10261 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10262 /// so a regression that (a) hard-coded the body to a fixed
10263 /// answer, (b) inverted the projection, or (c) crossed the wires
10264 /// with the sibling
10265 /// [`crate::classification::SubstrateType::is_resource`] /
10266 /// [`crate::classification::SubstrateType::is_policy`]
10267 /// projections fails HERE at the substrate primitive before
10268 /// drifting through the `telemetry-substrate` fixed tag or the
10269 /// peer point surface.
10270 #[test]
10271 fn substrate_is_telemetry_returns_substrate_projection_per_kind() {
10272 for populated in SubstrateType::ALL {
10273 let mut classification = Classification::gate_compute();
10274 classification.substrate = populated;
10275 let mut spec = empty_ephemeral();
10276 spec.classification = Some(classification);
10277 assert_eq!(
10278 spec.substrate_is_telemetry(),
10279 populated.is_telemetry(),
10280 "authored substrate={populated:?}: substrate_is_telemetry() drift",
10281 );
10282 }
10283 }
10284
10285 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10286 /// with `classification: None` routes through the
10287 /// [`Self::resolved_classification`] resolver's substrate default
10288 /// [`Classification::gate_compute`], which carries
10289 /// [`crate::classification::SubstrateType::Compute`] (the
10290 /// canonical resource-plane substrate, NOT a telemetry plane),
10291 /// and
10292 /// [`crate::classification::SubstrateType::Compute::is_telemetry`]
10293 /// projects `false`, so [`Self::substrate_is_telemetry`] returns
10294 /// `false`. Pins the resolver's chosen-field baseline at ONE
10295 /// narrow site — aligned with the sibling
10296 /// `substrate_is_policy_probes_false_on_absent_classification`
10297 /// (both projections on `gate_compute`'s chosen `substrate`
10298 /// field project `false` since `Compute` lives in the resource
10299 /// plane), mirror-inverted from
10300 /// `substrate_is_resource_probes_true_on_absent_classification`.
10301 #[test]
10302 fn substrate_is_telemetry_probes_false_on_absent_classification() {
10303 let spec = empty_ephemeral();
10304 assert!(spec.classification.is_none());
10305 assert!(
10306 !spec.substrate_is_telemetry(),
10307 "absent classification (defaults to gate_compute, substrate=Compute → is_telemetry=false)",
10308 );
10309 }
10310
10311 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10312 /// identically through [`Self::substrate_is_telemetry`] AND
10313 /// through
10314 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_telemetry()`
10315 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10316 /// classification, `Some(_)` classification on every
10317 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10318 /// future regression on either side of the resolver fails HERE
10319 /// at the parity boundary. Byte-for-byte peer of
10320 /// `substrate_is_policy_matches_point_peer_through_lowered_classification`
10321 /// on the SAME closed-set axis via a sibling projection.
10322 #[test]
10323 fn substrate_is_telemetry_matches_point_peer_through_lowered_classification() {
10324 // Absent classification.
10325 let eph = empty_ephemeral();
10326 let lowered: ProcessSpec = eph.clone().into();
10327 assert_eq!(
10328 eph.substrate_is_telemetry(),
10329 lowered.classification.substrate_is_telemetry(),
10330 "None-classification parity drift",
10331 );
10332 // Authored classification.
10333 for populated in SubstrateType::ALL {
10334 let mut classification = Classification::gate_compute();
10335 classification.substrate = populated;
10336 let mut eph = empty_ephemeral();
10337 eph.classification = Some(classification);
10338 let lowered: ProcessSpec = eph.clone().into();
10339 assert_eq!(
10340 eph.substrate_is_telemetry(),
10341 lowered.classification.substrate_is_telemetry(),
10342 "authored substrate={populated:?}: parity drift",
10343 );
10344 }
10345 }
10346
10347 /// MUTEX pin — [`Self::substrate_is_resource`] AND
10348 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
10349 /// for ANY [`EphemeralSpec`] (authored or defaulted). Second
10350 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
10351 /// peer of
10352 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
10353 /// on a sibling closed-set projection.
10354 #[test]
10355 fn ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all() {
10356 // Absent classification.
10357 let eph = empty_ephemeral();
10358 assert!(
10359 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
10360 "None-classification: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
10361 );
10362 // Authored classification.
10363 for populated in SubstrateType::ALL {
10364 let mut classification = Classification::gate_compute();
10365 classification.substrate = populated;
10366 let mut eph = empty_ephemeral();
10367 eph.classification = Some(classification);
10368 assert!(
10369 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
10370 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
10371 );
10372 }
10373 }
10374
10375 /// MUTEX pin — [`Self::substrate_is_policy`] AND
10376 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
10377 /// for ANY [`EphemeralSpec`] (authored or defaulted). Third
10378 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
10379 /// completes the three pairwise MUTEX relations alongside
10380 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
10381 /// and
10382 /// `ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all`.
10383 #[test]
10384 fn ephemeral_substrate_is_policy_and_substrate_is_telemetry_are_mutex_over_all() {
10385 // Absent classification.
10386 let eph = empty_ephemeral();
10387 assert!(
10388 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
10389 "None-classification: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
10390 );
10391 // Authored classification.
10392 for populated in SubstrateType::ALL {
10393 let mut classification = Classification::gate_compute();
10394 classification.substrate = populated;
10395 let mut eph = empty_ephemeral();
10396 eph.classification = Some(classification);
10397 assert!(
10398 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
10399 "authored substrate={populated:?}: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
10400 );
10401 }
10402 }
10403
10404 /// THREE-WAY XOR PARTITION pin — for the absent-classification
10405 /// baseline AND every [`crate::classification::SubstrateType::ALL`]
10406 /// variant, EXACTLY ONE of [`Self::substrate_is_resource`],
10407 /// [`Self::substrate_is_policy`], and
10408 /// [`Self::substrate_is_telemetry`] returns `true`. CLOSES the
10409 /// three pairwise MUTEX pins on the substrate axis
10410 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`,
10411 /// `substrate_is_resource ⇒ ¬substrate_is_telemetry`,
10412 /// `substrate_is_policy ⇒ ¬substrate_is_telemetry`) into the
10413 /// FULL ternary XOR partition contract on the ephemeral surface
10414 /// — the resolver-hop peer of the parent-composed
10415 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`
10416 /// test. Structural twin of the sibling `point_type`-axis
10417 /// ternary lift sealed on this surface by
10418 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
10419 /// Guarantees the absent-classification case lands in the
10420 /// resource bucket (`gate_compute` → Compute → is_resource =
10421 /// true), so every unadorned `(defephemeral …)` audits under a
10422 /// definite non-empty plane bucket.
10423 #[test]
10424 fn ephemeral_substrate_probes_form_three_way_xor_partition_over_all() {
10425 // Absent classification.
10426 let eph = empty_ephemeral();
10427 let buckets = [
10428 eph.substrate_is_resource(),
10429 eph.substrate_is_policy(),
10430 eph.substrate_is_telemetry(),
10431 ];
10432 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10433 assert_eq!(
10434 hits, 1,
10435 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10436 );
10437 // Authored classification.
10438 for populated in SubstrateType::ALL {
10439 let mut classification = Classification::gate_compute();
10440 classification.substrate = populated;
10441 let mut eph = empty_ephemeral();
10442 eph.classification = Some(classification);
10443 let buckets = [
10444 eph.substrate_is_resource(),
10445 eph.substrate_is_policy(),
10446 eph.substrate_is_telemetry(),
10447 ];
10448 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10449 assert_eq!(
10450 hits, 1,
10451 "authored substrate={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10452 );
10453 }
10454 }
10455
10456 // ── EphemeralSpec::calm_is_monotone pins ─────────────────────────
10457 //
10458 // Fail-before-pass-after granularity: `calm_is_monotone` did not
10459 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10460 // the "can this ephemeral spec participate in gossip-only writes?"
10461 // question went through the antisymmetric
10462 // `!self.calm_requires_coordination()` or through
10463 // `.resolved_classification().calm.is_monotone()`. Post-lift the
10464 // TWELFTH derived-nullary-boolean peer on the ephemeral surface
10465 // (SECOND on the calm axis, closing that axis into a binary XOR
10466 // partition on this surface) routes through the SAME
10467 // [`Self::resolved_classification`] resolver + the sibling
10468 // substrate primitive
10469 // [`crate::classification::Classification::calm_is_monotone`], so
10470 // the two-surface parity contract holds by construction, AND the
10471 // two calm-axis peers on this surface CLOSE the axis into the
10472 // FULL binary XOR partition contract via
10473 // `ephemeral_calm_probes_form_binary_xor_partition_over_all`.
10474
10475 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10476 /// [`Classification`] carries a specific
10477 /// [`crate::classification::CalmClassification`] variant answers
10478 /// [`Self::calm_is_monotone`] matching the closed set's own
10479 /// [`crate::classification::CalmClassification::is_monotone`]
10480 /// truth table. Sweep
10481 /// [`crate::classification::CalmClassification::ALL`] so a
10482 /// regression that (a) hard-coded the body to a fixed answer,
10483 /// (b) inverted the projection, or (c) crossed the wires with
10484 /// the sibling
10485 /// [`crate::classification::CalmClassification::requires_coordination`]
10486 /// projection fails HERE at the substrate primitive before
10487 /// drifting through the `monotone-calm` fixed tag or the peer
10488 /// point surface.
10489 #[test]
10490 fn calm_is_monotone_returns_calm_projection_per_kind() {
10491 for populated in CalmClassification::ALL {
10492 let mut classification = Classification::gate_compute();
10493 classification.calm = populated;
10494 let mut spec = empty_ephemeral();
10495 spec.classification = Some(classification);
10496 assert_eq!(
10497 spec.calm_is_monotone(),
10498 populated.is_monotone(),
10499 "authored calm={populated:?}: calm_is_monotone() drift",
10500 );
10501 }
10502 }
10503
10504 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10505 /// with `classification: None` routes through the
10506 /// [`Self::resolved_classification`] resolver's substrate default
10507 /// [`Classification::gate_compute`], which carries
10508 /// [`crate::classification::CalmClassification::default = Monotone`]
10509 /// via `#[default]`, and
10510 /// [`crate::classification::CalmClassification::Monotone::is_monotone`]
10511 /// projects `true`, so [`Self::calm_is_monotone`] returns
10512 /// `true`. Pins the resolver's default-arm short-circuit through
10513 /// TWO layers of `Default` ([`Classification::gate_compute`] →
10514 /// [`crate::classification::CalmClassification::default`])
10515 /// reaching this derived-nullary predicate. Mirror-inverted from
10516 /// the sibling
10517 /// `calm_requires_coordination_probes_false_on_absent_classification`
10518 /// (both walk the SAME defaulted `calm` field, so
10519 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
10520 /// closed set's disjoint XOR partition). Guarantees every
10521 /// unadorned `(defephemeral …)` reads as gossip-eligible under
10522 /// the positive CALM framing.
10523 #[test]
10524 fn calm_is_monotone_probes_true_on_absent_classification() {
10525 let spec = empty_ephemeral();
10526 assert!(spec.classification.is_none());
10527 assert!(
10528 spec.calm_is_monotone(),
10529 "absent classification (defaults to gate_compute, calm=Monotone → is_monotone=true)",
10530 );
10531 }
10532
10533 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10534 /// identically through [`Self::calm_is_monotone`] AND through
10535 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_is_monotone()`
10536 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10537 /// classification, `Some(_)` classification on every
10538 /// [`crate::classification::CalmClassification::ALL`] variant) so
10539 /// a future regression on either side of the resolver fails HERE
10540 /// at the parity boundary. Byte-for-byte peer of
10541 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
10542 /// on the SAME closed-set axis via the antisymmetric projection.
10543 #[test]
10544 fn calm_is_monotone_matches_point_peer_through_lowered_classification() {
10545 // Absent classification.
10546 let eph = empty_ephemeral();
10547 let lowered: ProcessSpec = eph.clone().into();
10548 assert_eq!(
10549 eph.calm_is_monotone(),
10550 lowered.classification.calm_is_monotone(),
10551 "None-classification parity drift",
10552 );
10553 // Authored classification.
10554 for populated in CalmClassification::ALL {
10555 let mut classification = Classification::gate_compute();
10556 classification.calm = populated;
10557 let mut eph = empty_ephemeral();
10558 eph.classification = Some(classification);
10559 let lowered: ProcessSpec = eph.clone().into();
10560 assert_eq!(
10561 eph.calm_is_monotone(),
10562 lowered.classification.calm_is_monotone(),
10563 "authored calm={populated:?}: parity drift",
10564 );
10565 }
10566 }
10567
10568 /// MUTEX pin — [`Self::calm_requires_coordination`] AND
10569 /// [`Self::calm_is_monotone`] are NEVER simultaneously true for
10570 /// ANY [`EphemeralSpec`] (authored or defaulted). FIRST
10571 /// ephemeral-surface `calm`-axis corner-peer MUTEX pin — the
10572 /// calm axis's counterpart to the sibling substrate-axis
10573 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
10574 /// on a binary (rather than ternary) closed set.
10575 #[test]
10576 fn ephemeral_calm_requires_coordination_and_calm_is_monotone_are_mutex_over_all() {
10577 // Absent classification.
10578 let eph = empty_ephemeral();
10579 assert!(
10580 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
10581 "None-classification: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
10582 );
10583 // Authored classification.
10584 for populated in CalmClassification::ALL {
10585 let mut classification = Classification::gate_compute();
10586 classification.calm = populated;
10587 let mut eph = empty_ephemeral();
10588 eph.classification = Some(classification);
10589 assert!(
10590 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
10591 "authored calm={populated:?}: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
10592 );
10593 }
10594 }
10595
10596 /// BINARY XOR PARTITION pin — for the absent-classification
10597 /// baseline AND every
10598 /// [`crate::classification::CalmClassification::ALL`] variant,
10599 /// EXACTLY ONE of [`Self::calm_is_monotone`] and
10600 /// [`Self::calm_requires_coordination`] returns `true`. CLOSES
10601 /// the calm-axis MUTEX pin
10602 /// (`calm_requires_coordination ⇒ ¬calm_is_monotone`) into the
10603 /// FULL binary XOR partition contract on the ephemeral surface
10604 /// — the resolver-hop peer of the parent-composed
10605 /// `classification_calm_probes_form_binary_xor_partition_over_all`
10606 /// test. Binary counterpart of the ternary XOR partitions sealed
10607 /// on the sibling `point_type` and `substrate` axes by
10608 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10609 /// and
10610 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
10611 /// Guarantees the absent-classification case lands in the
10612 /// monotone bucket (`gate_compute` → CalmClassification::Monotone
10613 /// → is_monotone = true), so every unadorned `(defephemeral …)`
10614 /// audits under a definite non-empty CALM bucket.
10615 #[test]
10616 fn ephemeral_calm_probes_form_binary_xor_partition_over_all() {
10617 // Absent classification.
10618 let eph = empty_ephemeral();
10619 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
10620 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10621 assert_eq!(
10622 hits, 1,
10623 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10624 );
10625 // Authored classification.
10626 for populated in CalmClassification::ALL {
10627 let mut classification = Classification::gate_compute();
10628 classification.calm = populated;
10629 let mut eph = empty_ephemeral();
10630 eph.classification = Some(classification);
10631 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
10632 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10633 assert_eq!(
10634 hits, 1,
10635 "authored calm={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10636 );
10637 }
10638 }
10639
10640 // ── EphemeralSpec::data_is_public pins ───────────────────────────
10641 //
10642 // Fail-before-pass-after granularity: `data_is_public` did not
10643 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10644 // the "is this ephemeral spec's dataset publicly distributable?"
10645 // question went through the antisymmetric
10646 // `!self.data_is_restricted()` or through
10647 // `.resolved_classification().data_classification.is_public()`.
10648 // Post-lift the THIRTEENTH derived-nullary-boolean peer on the
10649 // ephemeral surface (THIRD on the data axis, closing that axis
10650 // into a binary XOR partition on this surface) routes through the
10651 // SAME [`Self::resolved_classification`] resolver + the sibling
10652 // substrate primitive
10653 // [`crate::classification::Classification::data_is_public`], so
10654 // the two-surface parity contract holds by construction, AND the
10655 // two-way public/restricted split on this surface CLOSES the
10656 // data axis into the FULL binary XOR partition contract via
10657 // `ephemeral_data_probes_form_binary_xor_partition_over_all`.
10658
10659 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10660 /// [`Classification`] carries a specific
10661 /// [`crate::classification::DataClassification`] variant answers
10662 /// [`Self::data_is_public`] matching the closed set's own
10663 /// [`crate::classification::DataClassification::is_public`] truth
10664 /// table. Sweep
10665 /// [`crate::classification::DataClassification::ALL`] so a
10666 /// regression that (a) hard-coded the body to a fixed answer,
10667 /// (b) inverted the projection, or (c) crossed the wires with
10668 /// the sibling
10669 /// [`crate::classification::DataClassification::is_restricted`]
10670 /// projection fails HERE at the substrate primitive before
10671 /// drifting through the `public-data` fixed tag or the peer
10672 /// point surface.
10673 #[test]
10674 fn data_is_public_returns_data_projection_per_kind() {
10675 for populated in DataClassification::ALL {
10676 let mut classification = Classification::gate_compute();
10677 classification.data_classification = populated;
10678 let mut spec = empty_ephemeral();
10679 spec.classification = Some(classification);
10680 assert_eq!(
10681 spec.data_is_public(),
10682 populated.is_public(),
10683 "authored data_classification={populated:?}: data_is_public() drift",
10684 );
10685 }
10686 }
10687
10688 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10689 /// with `classification: None` routes through the
10690 /// [`Self::resolved_classification`] resolver's substrate default
10691 /// [`Classification::gate_compute`], which carries
10692 /// [`crate::classification::DataClassification::default = Internal`]
10693 /// via `#[default]`, and
10694 /// [`crate::classification::DataClassification::Internal::is_public`]
10695 /// projects `false`, so [`Self::data_is_public`] returns `false`.
10696 /// Pins the resolver's default-arm short-circuit through TWO
10697 /// layers of `Default` ([`Classification::gate_compute`] →
10698 /// [`crate::classification::DataClassification::default`])
10699 /// reaching this derived-nullary predicate. Mirror-inverted from
10700 /// the sibling
10701 /// `data_is_restricted_probes_true_on_absent_classification`
10702 /// (both walk the SAME defaulted `data_classification` field, so
10703 /// `is_restricted = true` ⇒ `is_public = false` on the closed
10704 /// set's disjoint XOR partition). Guarantees every unadorned
10705 /// `(defephemeral …)` audits under the access-controlled default
10706 /// rather than silently promoting an unadorned dataset onto the
10707 /// freely-distributable path.
10708 #[test]
10709 fn data_is_public_probes_false_on_absent_classification() {
10710 let spec = empty_ephemeral();
10711 assert!(spec.classification.is_none());
10712 assert!(
10713 !spec.data_is_public(),
10714 "absent classification (defaults to gate_compute, data_classification=Internal → is_public=false)",
10715 );
10716 }
10717
10718 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10719 /// identically through [`Self::data_is_public`] AND through
10720 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_public()`
10721 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10722 /// classification, `Some(_)` classification on every
10723 /// [`crate::classification::DataClassification::ALL`] variant) so
10724 /// a future regression on either side of the resolver fails HERE
10725 /// at the parity boundary. Byte-for-byte peer of
10726 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
10727 /// on the SAME closed-set axis via the antisymmetric projection.
10728 #[test]
10729 fn data_is_public_matches_point_peer_through_lowered_classification() {
10730 // Absent classification.
10731 let eph = empty_ephemeral();
10732 let lowered: ProcessSpec = eph.clone().into();
10733 assert_eq!(
10734 eph.data_is_public(),
10735 lowered.classification.data_is_public(),
10736 "None-classification parity drift",
10737 );
10738 // Authored classification.
10739 for populated in DataClassification::ALL {
10740 let mut classification = Classification::gate_compute();
10741 classification.data_classification = populated;
10742 let mut eph = empty_ephemeral();
10743 eph.classification = Some(classification);
10744 let lowered: ProcessSpec = eph.clone().into();
10745 assert_eq!(
10746 eph.data_is_public(),
10747 lowered.classification.data_is_public(),
10748 "authored data_classification={populated:?}: parity drift",
10749 );
10750 }
10751 }
10752
10753 /// MUTEX pin — [`Self::data_is_regulated`] AND
10754 /// [`Self::data_is_public`] are NEVER simultaneously true for ANY
10755 /// [`EphemeralSpec`] (authored or defaulted). FIRST ephemeral-
10756 /// surface data-axis antisymmetric MUTEX pin against the
10757 /// positive-distribution framing: sealed on the closed set by
10758 /// `data_classification_regulated_implies_not_public` and lifted
10759 /// through the resolver hop as a substrate-wide contract on this
10760 /// surface.
10761 #[test]
10762 fn ephemeral_data_is_regulated_and_data_is_public_are_mutex_over_all() {
10763 // Absent classification.
10764 let eph = empty_ephemeral();
10765 assert!(
10766 !(eph.data_is_regulated() && eph.data_is_public()),
10767 "None-classification: data_is_regulated AND data_is_public both true (mutex violated)",
10768 );
10769 // Authored classification.
10770 for populated in DataClassification::ALL {
10771 let mut classification = Classification::gate_compute();
10772 classification.data_classification = populated;
10773 let mut eph = empty_ephemeral();
10774 eph.classification = Some(classification);
10775 assert!(
10776 !(eph.data_is_regulated() && eph.data_is_public()),
10777 "authored data_classification={populated:?}: data_is_regulated AND data_is_public both true (mutex violated)",
10778 );
10779 }
10780 }
10781
10782 /// BINARY XOR PARTITION pin — for the absent-classification
10783 /// baseline AND every
10784 /// [`crate::classification::DataClassification::ALL`] variant,
10785 /// EXACTLY ONE of [`Self::data_is_public`] and
10786 /// [`Self::data_is_restricted`] returns `true`. CLOSES the data-
10787 /// axis MUTEX pin (`data_is_regulated ⇒ ¬data_is_public`) into
10788 /// the FULL binary XOR partition contract on the ephemeral
10789 /// surface — the resolver-hop peer of the parent-composed
10790 /// `classification_data_probes_form_binary_xor_partition_over_all`
10791 /// test. Binary counterpart of the ternary XOR partitions sealed
10792 /// on the sibling `point_type` and `substrate` axes by
10793 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10794 /// and
10795 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
10796 /// Guarantees the absent-classification case lands in the
10797 /// access-controlled bucket (`gate_compute` →
10798 /// DataClassification::Internal → is_public = false,
10799 /// is_restricted = true), so every unadorned `(defephemeral …)`
10800 /// audits under a definite non-empty distribution bucket.
10801 #[test]
10802 fn ephemeral_data_probes_form_binary_xor_partition_over_all() {
10803 // Absent classification.
10804 let eph = empty_ephemeral();
10805 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
10806 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10807 assert_eq!(
10808 hits, 1,
10809 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10810 );
10811 // Authored classification.
10812 for populated in DataClassification::ALL {
10813 let mut classification = Classification::gate_compute();
10814 classification.data_classification = populated;
10815 let mut eph = empty_ephemeral();
10816 eph.classification = Some(classification);
10817 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
10818 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10819 assert_eq!(
10820 hits, 1,
10821 "authored data_classification={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10822 );
10823 }
10824 }
10825
10826 // ── EphemeralSpec::direction_prefers_lower pins ─────────────────
10827 //
10828 // Fail-before-pass-after granularity: `direction_prefers_lower`
10829 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10830 // walking the "does this ephemeral spec's rate-window evaluator
10831 // treat decreasing values as improvement?" question went through
10832 // `.resolved_classification().horizon.direction.unwrap_or_default().prefers_lower()`.
10833 // Post-lift the FOURTEENTH derived-nullary-boolean peer on the
10834 // ephemeral surface (FIRST on the optimization-direction axis,
10835 // opening the SIXTH classification axis into the fixed-tag algebra)
10836 // routes through the SAME [`Self::resolved_classification`] resolver
10837 // + the sibling substrate primitive
10838 // [`crate::classification::Classification::direction_prefers_lower`],
10839 // so the two-surface parity contract holds by construction.
10840
10841 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10842 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
10843 /// answers [`Self::direction_prefers_lower`] matching the closed
10844 /// set's own
10845 /// [`crate::classification::OptimizationDirection::prefers_lower`]
10846 /// truth table. Sweep
10847 /// [`crate::classification::OptimizationDirection::ALL`] so a
10848 /// regression that (a) hard-coded the body to a fixed answer,
10849 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
10850 /// hop, or (d) crossed the wires with a sibling classification-axis
10851 /// probe fails HERE at the substrate primitive before drifting
10852 /// through the `prefers-lower-direction` fixed tag or the peer
10853 /// point surface.
10854 #[test]
10855 fn direction_prefers_lower_returns_direction_projection_per_kind() {
10856 for populated in OptimizationDirection::ALL {
10857 let mut classification = Classification::gate_compute();
10858 classification.horizon.direction = Some(populated);
10859 let mut spec = empty_ephemeral();
10860 spec.classification = Some(classification);
10861 assert_eq!(
10862 spec.direction_prefers_lower(),
10863 populated.prefers_lower(),
10864 "authored horizon.direction={populated:?}: direction_prefers_lower() drift",
10865 );
10866 }
10867 }
10868
10869 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10870 /// with `classification: None` routes through the
10871 /// [`Self::resolved_classification`] resolver's substrate default
10872 /// [`Classification::gate_compute`], which carries
10873 /// `horizon: Horizon::default()` whose `direction` field is `None`,
10874 /// so `unwrap_or_default()` defaults to
10875 /// [`crate::classification::OptimizationDirection::Minimize`] via
10876 /// `#[default]`, and `Minimize.prefers_lower()` projects `true`,
10877 /// so [`Self::direction_prefers_lower`] returns `true`. Pins the
10878 /// resolver's default-arm short-circuit through THREE layers of
10879 /// `Default` ([`Classification::gate_compute`] →
10880 /// [`crate::classification::Horizon::default`] with `direction: None`
10881 /// → [`crate::classification::OptimizationDirection::default =
10882 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
10883 /// every unadorned `(defephemeral …)` reads under the lower-is-
10884 /// better polarity default (safe under the asymptotic-health
10885 /// rate-window evaluator convention: an operator must deliberately
10886 /// opt into Maximize polarity).
10887 #[test]
10888 fn direction_prefers_lower_probes_true_on_absent_classification() {
10889 let spec = empty_ephemeral();
10890 assert!(spec.classification.is_none());
10891 assert!(
10892 spec.direction_prefers_lower(),
10893 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_lower=true)",
10894 );
10895 }
10896
10897 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10898 /// identically through [`Self::direction_prefers_lower`] AND through
10899 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_lower()`
10900 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10901 /// classification, `Some(_)` classification on every
10902 /// [`crate::classification::OptimizationDirection::ALL`] variant) so
10903 /// a future regression on either side of the resolver fails HERE
10904 /// at the parity boundary. Byte-for-byte peer of
10905 /// `calm_is_monotone_matches_point_peer_through_lowered_classification`
10906 /// on the analog closed-set axis via the same resolver-hop shape.
10907 #[test]
10908 fn direction_prefers_lower_matches_point_peer_through_lowered_classification() {
10909 // Absent classification.
10910 let eph = empty_ephemeral();
10911 let lowered: ProcessSpec = eph.clone().into();
10912 assert_eq!(
10913 eph.direction_prefers_lower(),
10914 lowered.classification.direction_prefers_lower(),
10915 "None-classification parity drift",
10916 );
10917 // Authored classification.
10918 for populated in OptimizationDirection::ALL {
10919 let mut classification = Classification::gate_compute();
10920 classification.horizon.direction = Some(populated);
10921 let mut eph = empty_ephemeral();
10922 eph.classification = Some(classification);
10923 let lowered: ProcessSpec = eph.clone().into();
10924 assert_eq!(
10925 eph.direction_prefers_lower(),
10926 lowered.classification.direction_prefers_lower(),
10927 "authored horizon.direction={populated:?}: parity drift",
10928 );
10929 }
10930 }
10931
10932 // ── EphemeralSpec::direction_prefers_higher pins ────────────────
10933 //
10934 // Fail-before-pass-after granularity: `direction_prefers_higher`
10935 // did not exist pre-lift on `impl EphemeralSpec` — the positive
10936 // higher-is-better framing peer of
10937 // [`Self::direction_prefers_lower`] had no ephemeral-surface
10938 // substrate owner. Post-lift the FIFTEENTH derived-nullary-boolean
10939 // peer on the ephemeral surface (SECOND on the optimization-
10940 // direction axis, CLOSING the SIXTH classification axis into a
10941 // binary XOR partition on this surface) routes through the SAME
10942 // [`Self::resolved_classification`] resolver + the sibling
10943 // substrate primitive
10944 // [`crate::classification::Classification::direction_prefers_higher`],
10945 // so the two-surface parity contract holds by construction, AND
10946 // the two-way lower/higher split on this surface CLOSES the
10947 // optimization-direction axis into the FULL binary XOR partition
10948 // contract via
10949 // `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
10950
10951 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10952 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
10953 /// answers [`Self::direction_prefers_higher`] matching the closed
10954 /// set's own
10955 /// [`crate::classification::OptimizationDirection::prefers_higher`]
10956 /// truth table. Sweep
10957 /// [`crate::classification::OptimizationDirection::ALL`] so a
10958 /// regression that (a) hard-coded the body to a fixed answer,
10959 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
10960 /// hop, or (d) crossed the wires with a sibling classification-
10961 /// axis probe fails HERE at the substrate primitive before
10962 /// drifting through the `prefers-higher-direction` fixed tag or
10963 /// the peer point surface.
10964 #[test]
10965 fn direction_prefers_higher_returns_direction_projection_per_kind() {
10966 for populated in OptimizationDirection::ALL {
10967 let mut classification = Classification::gate_compute();
10968 classification.horizon.direction = Some(populated);
10969 let mut spec = empty_ephemeral();
10970 spec.classification = Some(classification);
10971 assert_eq!(
10972 spec.direction_prefers_higher(),
10973 populated.prefers_higher(),
10974 "authored horizon.direction={populated:?}: direction_prefers_higher() drift",
10975 );
10976 }
10977 }
10978
10979 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10980 /// with `classification: None` routes through the
10981 /// [`Self::resolved_classification`] resolver's substrate default
10982 /// [`Classification::gate_compute`], which carries
10983 /// `horizon: Horizon::default()` whose `direction` field is `None`,
10984 /// so `unwrap_or_default()` defaults to
10985 /// [`crate::classification::OptimizationDirection::Minimize`] via
10986 /// `#[default]`, and `Minimize.prefers_higher()` projects `false`,
10987 /// so [`Self::direction_prefers_higher`] returns `false`. Pins
10988 /// the resolver's default-arm short-circuit through THREE layers
10989 /// of `Default` ([`Classification::gate_compute`] →
10990 /// [`crate::classification::Horizon::default`] with `direction:
10991 /// None` → [`crate::classification::OptimizationDirection::default =
10992 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
10993 /// every unadorned `(defephemeral …)` reads UNDER the lower-is-
10994 /// better polarity default (safe under the asymptotic-health
10995 /// rate-window evaluator convention: an operator must
10996 /// deliberately opt into Maximize polarity). Mirror-inverted from
10997 /// the sibling `direction_prefers_lower_probes_true_on_absent_classification`
10998 /// baseline on the same resolver walk.
10999 #[test]
11000 fn direction_prefers_higher_probes_false_on_absent_classification() {
11001 let spec = empty_ephemeral();
11002 assert!(spec.classification.is_none());
11003 assert!(
11004 !spec.direction_prefers_higher(),
11005 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_higher=false)",
11006 );
11007 }
11008
11009 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11010 /// identically through [`Self::direction_prefers_higher`] AND
11011 /// through
11012 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_higher()`
11013 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11014 /// classification, `Some(_)` classification on every
11015 /// [`crate::classification::OptimizationDirection::ALL`] variant)
11016 /// so a future regression on either side of the resolver fails
11017 /// HERE at the parity boundary. Byte-for-byte peer of
11018 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
11019 /// on the antisymmetric closed-set arm via the same resolver-hop
11020 /// shape.
11021 #[test]
11022 fn direction_prefers_higher_matches_point_peer_through_lowered_classification() {
11023 // Absent classification.
11024 let eph = empty_ephemeral();
11025 let lowered: ProcessSpec = eph.clone().into();
11026 assert_eq!(
11027 eph.direction_prefers_higher(),
11028 lowered.classification.direction_prefers_higher(),
11029 "None-classification parity drift",
11030 );
11031 // Authored classification.
11032 for populated in OptimizationDirection::ALL {
11033 let mut classification = Classification::gate_compute();
11034 classification.horizon.direction = Some(populated);
11035 let mut eph = empty_ephemeral();
11036 eph.classification = Some(classification);
11037 let lowered: ProcessSpec = eph.clone().into();
11038 assert_eq!(
11039 eph.direction_prefers_higher(),
11040 lowered.classification.direction_prefers_higher(),
11041 "authored horizon.direction={populated:?}: parity drift",
11042 );
11043 }
11044 }
11045
11046 /// BINARY XOR PARTITION pin — for the absent-classification
11047 /// baseline AND every
11048 /// [`crate::classification::OptimizationDirection::ALL`] variant,
11049 /// EXACTLY ONE of [`Self::direction_prefers_lower`] and
11050 /// [`Self::direction_prefers_higher`] returns `true`. CLOSES the
11051 /// optimization-direction axis into the FULL binary XOR partition
11052 /// contract on the ephemeral surface — the resolver-hop peer of
11053 /// the parent-composed
11054 /// `classification_direction_probes_form_binary_xor_partition_over_all`
11055 /// test. Binary counterpart of the ternary XOR partitions sealed
11056 /// on the sibling `point_type` and `substrate` axes by
11057 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11058 /// and
11059 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11060 /// structural twin of the calm/data binary partitions
11061 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all` and
11062 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11063 /// This pin is the SIXTH (and final) classification axis to reach
11064 /// the closed XOR partition landmark on the ephemeral resolver-
11065 /// hop surface — ALL SIX classification axes (horizon, calm,
11066 /// data, point, substrate, optimization-direction) now have
11067 /// their partitions closed on the ephemeral surface at this
11068 /// corner. Guarantees the absent-classification case lands in
11069 /// the definite lower-is-better bucket (`gate_compute` →
11070 /// Horizon::default → direction: None →
11071 /// OptimizationDirection::default = Minimize → prefers_lower =
11072 /// true, prefers_higher = false), so every unadorned
11073 /// `(defephemeral …)` audits under a definite non-empty polarity
11074 /// bucket.
11075 #[test]
11076 fn ephemeral_direction_probes_form_binary_xor_partition_over_all() {
11077 // Absent classification.
11078 let eph = empty_ephemeral();
11079 let buckets = [
11080 eph.direction_prefers_lower(),
11081 eph.direction_prefers_higher(),
11082 ];
11083 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11084 assert_eq!(
11085 hits, 1,
11086 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11087 );
11088 // Authored classification.
11089 for populated in OptimizationDirection::ALL {
11090 let mut classification = Classification::gate_compute();
11091 classification.horizon.direction = Some(populated);
11092 let mut eph = empty_ephemeral();
11093 eph.classification = Some(classification);
11094 let buckets = [
11095 eph.direction_prefers_lower(),
11096 eph.direction_prefers_higher(),
11097 ];
11098 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11099 assert_eq!(
11100 hits, 1,
11101 "authored horizon.direction={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11102 );
11103 }
11104 }
11105
11106 // ── EphemeralSpec::input_arity_is_one pins ──────────────────────
11107 //
11108 // Fail-before-pass-after granularity: `input_arity_is_one` did not
11109 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11110 // the "does this ephemeral spec's DAG-composition input port
11111 // accept a single upstream edge?" question went through
11112 // `.resolved_classification().point_type.input_arity().is_one()`.
11113 // Post-lift the SIXTEENTH derived-nullary-boolean peer on the
11114 // ephemeral surface (FIRST on the input-arity axis, opening the
11115 // SEVENTH classification axis into the fixed-tag algebra + the
11116 // derived-typed-projection stratum on this surface for the first
11117 // time) routes through the SAME [`Self::resolved_classification`]
11118 // resolver + the sibling substrate primitive
11119 // [`crate::classification::Classification::input_arity_is_one`],
11120 // so the two-surface parity contract holds by construction.
11121
11122 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11123 /// [`Classification`] carries `point_type: kind` answers
11124 /// [`Self::input_arity_is_one`] matching the closed set's own
11125 /// [`crate::classification::ConvergencePointType::input_arity`]
11126 /// truth table projected through [`Arity::is_one`]. Sweep
11127 /// [`crate::classification::ConvergencePointType::ALL`] so a
11128 /// regression that (a) hard-coded the body to a fixed answer,
11129 /// (b) inverted the projection, (c) dropped the resolver hop, or
11130 /// (d) crossed the wires with the sibling `output_arity`
11131 /// projection (which disagrees on six of eight variants) fails
11132 /// HERE at the substrate primitive before drifting through the
11133 /// future `single-input-arity` fixed tag or the peer point
11134 /// surface.
11135 #[test]
11136 fn input_arity_is_one_returns_input_arity_projection_per_kind() {
11137 for populated in ConvergencePointType::ALL {
11138 let mut classification = Classification::gate_compute();
11139 classification.point_type = populated;
11140 let mut spec = empty_ephemeral();
11141 spec.classification = Some(classification);
11142 assert_eq!(
11143 spec.input_arity_is_one(),
11144 populated.input_arity().is_one(),
11145 "authored point_type={populated:?}: input_arity_is_one() drift",
11146 );
11147 }
11148 }
11149
11150 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11151 /// with `classification: None` routes through the
11152 /// [`Self::resolved_classification`] resolver's substrate default
11153 /// [`Classification::gate_compute`], which carries `point_type:
11154 /// Gate` and `Gate.input_arity() = Many`, so
11155 /// [`Self::input_arity_is_one`] returns `false`. Pins the
11156 /// resolver's default-arm short-circuit reaching this derived-
11157 /// nullary predicate — every unadorned `(defephemeral …)` lands
11158 /// in the multi-input bucket under the substrate default. Mirror-
11159 /// inverted from the sibling `input_arity_is_many` baseline on
11160 /// the same resolver walk (the XOR partition forces exactly one
11161 /// bucket per baseline).
11162 #[test]
11163 fn input_arity_is_one_probes_false_on_absent_classification() {
11164 let spec = empty_ephemeral();
11165 assert!(spec.classification.is_none());
11166 assert!(
11167 !spec.input_arity_is_one(),
11168 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_one=false)",
11169 );
11170 }
11171
11172 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11173 /// identically through [`Self::input_arity_is_one`] AND through
11174 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_one()`
11175 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11176 /// classification, `Some(_)` classification on every
11177 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11178 /// so a future regression on either side of the resolver fails
11179 /// HERE at the parity boundary. Byte-for-byte peer of
11180 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
11181 /// on the same resolver-hop shape.
11182 #[test]
11183 fn input_arity_is_one_matches_point_peer_through_lowered_classification() {
11184 // Absent classification.
11185 let eph = empty_ephemeral();
11186 let lowered: ProcessSpec = eph.clone().into();
11187 assert_eq!(
11188 eph.input_arity_is_one(),
11189 lowered.classification.input_arity_is_one(),
11190 "None-classification parity drift",
11191 );
11192 // Authored classification.
11193 for populated in ConvergencePointType::ALL {
11194 let mut classification = Classification::gate_compute();
11195 classification.point_type = populated;
11196 let mut eph = empty_ephemeral();
11197 eph.classification = Some(classification);
11198 let lowered: ProcessSpec = eph.clone().into();
11199 assert_eq!(
11200 eph.input_arity_is_one(),
11201 lowered.classification.input_arity_is_one(),
11202 "authored point_type={populated:?}: parity drift",
11203 );
11204 }
11205 }
11206
11207 // ── EphemeralSpec::input_arity_is_many pins ─────────────────────
11208 //
11209 // Fail-before-pass-after granularity: `input_arity_is_many` did
11210 // not exist pre-lift on `impl EphemeralSpec` — the multi-input
11211 // framing peer of [`Self::input_arity_is_one`] had no ephemeral-
11212 // surface substrate owner. Post-lift the SEVENTEENTH derived-
11213 // nullary-boolean peer on the ephemeral surface (SECOND on the
11214 // input-arity axis, CLOSING the SEVENTH classification axis into
11215 // a binary XOR partition on this surface) routes through the SAME
11216 // [`Self::resolved_classification`] resolver + the sibling
11217 // substrate primitive
11218 // [`crate::classification::Classification::input_arity_is_many`],
11219 // so the two-surface parity contract holds by construction, AND
11220 // the two-way single/many split on this surface CLOSES the
11221 // input-arity axis into the FULL binary XOR partition contract
11222 // via `ephemeral_input_arity_probes_form_binary_xor_partition_over_all`.
11223
11224 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11225 /// [`Classification`] carries `point_type: kind` answers
11226 /// [`Self::input_arity_is_many`] matching the closed set's own
11227 /// [`crate::classification::ConvergencePointType::input_arity`]
11228 /// truth table projected through [`Arity::is_many`]. Sweep
11229 /// [`crate::classification::ConvergencePointType::ALL`] so a
11230 /// regression that (a) hard-coded the body to a fixed answer,
11231 /// (b) inverted the projection, (c) dropped the resolver hop, or
11232 /// (d) crossed the wires with the sibling `output_arity`
11233 /// projection fails HERE at the substrate primitive before
11234 /// drifting through the future `multi-input-arity` fixed tag or
11235 /// the peer point surface.
11236 #[test]
11237 fn input_arity_is_many_returns_input_arity_projection_per_kind() {
11238 for populated in ConvergencePointType::ALL {
11239 let mut classification = Classification::gate_compute();
11240 classification.point_type = populated;
11241 let mut spec = empty_ephemeral();
11242 spec.classification = Some(classification);
11243 assert_eq!(
11244 spec.input_arity_is_many(),
11245 populated.input_arity().is_many(),
11246 "authored point_type={populated:?}: input_arity_is_many() drift",
11247 );
11248 }
11249 }
11250
11251 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11252 /// with `classification: None` routes through the
11253 /// [`Self::resolved_classification`] resolver's substrate default
11254 /// [`Classification::gate_compute`], which carries `point_type:
11255 /// Gate` and `Gate.input_arity() = Many`, so
11256 /// [`Self::input_arity_is_many`] returns `true`. Pins the
11257 /// resolver's default-arm short-circuit reaching this derived-
11258 /// nullary predicate — every unadorned `(defephemeral …)` lands
11259 /// in the multi-input bucket under the substrate default. Mirror-
11260 /// inverted from the sibling `input_arity_is_one` baseline on
11261 /// the same resolver walk (the XOR partition forces exactly one
11262 /// bucket per baseline).
11263 #[test]
11264 fn input_arity_is_many_probes_true_on_absent_classification() {
11265 let spec = empty_ephemeral();
11266 assert!(spec.classification.is_none());
11267 assert!(
11268 spec.input_arity_is_many(),
11269 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_many=true)",
11270 );
11271 }
11272
11273 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11274 /// identically through [`Self::input_arity_is_many`] AND through
11275 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_many()`
11276 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11277 /// classification, `Some(_)` classification on every
11278 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11279 /// so a future regression on either side of the resolver fails
11280 /// HERE at the parity boundary. Byte-for-byte peer of
11281 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
11282 /// on the antisymmetric closed-set arm via the same resolver-hop
11283 /// shape.
11284 #[test]
11285 fn input_arity_is_many_matches_point_peer_through_lowered_classification() {
11286 // Absent classification.
11287 let eph = empty_ephemeral();
11288 let lowered: ProcessSpec = eph.clone().into();
11289 assert_eq!(
11290 eph.input_arity_is_many(),
11291 lowered.classification.input_arity_is_many(),
11292 "None-classification parity drift",
11293 );
11294 // Authored classification.
11295 for populated in ConvergencePointType::ALL {
11296 let mut classification = Classification::gate_compute();
11297 classification.point_type = populated;
11298 let mut eph = empty_ephemeral();
11299 eph.classification = Some(classification);
11300 let lowered: ProcessSpec = eph.clone().into();
11301 assert_eq!(
11302 eph.input_arity_is_many(),
11303 lowered.classification.input_arity_is_many(),
11304 "authored point_type={populated:?}: parity drift",
11305 );
11306 }
11307 }
11308
11309 /// BINARY XOR PARTITION pin — for the absent-classification
11310 /// baseline AND every
11311 /// [`crate::classification::ConvergencePointType::ALL`] variant,
11312 /// EXACTLY ONE of [`Self::input_arity_is_one`] and
11313 /// [`Self::input_arity_is_many`] returns `true`. CLOSES the
11314 /// input-arity axis into the FULL binary XOR partition contract
11315 /// on the ephemeral surface — the resolver-hop peer of the
11316 /// parent-composed
11317 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`
11318 /// test. Binary counterpart of the ternary XOR partitions sealed
11319 /// on the sibling `point_type` and `substrate` axes by
11320 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11321 /// and
11322 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11323 /// structural twin of the calm/data/direction binary partitions
11324 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
11325 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`,
11326 /// and
11327 /// `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
11328 /// This pin is the SEVENTH classification axis to reach the
11329 /// closed XOR partition landmark on the ephemeral resolver-hop
11330 /// surface — the FIRST closed axis on the derived-typed-
11331 /// projection stratum of this surface, opening the stratum beyond
11332 /// the six stored classification slots. Guarantees the absent-
11333 /// classification case lands in the definite multi-input bucket
11334 /// (`gate_compute` → point_type=Gate → input_arity=Many →
11335 /// is_one=false, is_many=true), so every unadorned
11336 /// `(defephemeral …)` audits under a definite non-empty input-
11337 /// arity bucket.
11338 #[test]
11339 fn ephemeral_input_arity_probes_form_binary_xor_partition_over_all() {
11340 // Absent classification.
11341 let eph = empty_ephemeral();
11342 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
11343 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11344 assert_eq!(
11345 hits, 1,
11346 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11347 );
11348 // Authored classification.
11349 for populated in ConvergencePointType::ALL {
11350 let mut classification = Classification::gate_compute();
11351 classification.point_type = populated;
11352 let mut eph = empty_ephemeral();
11353 eph.classification = Some(classification);
11354 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
11355 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11356 assert_eq!(
11357 hits, 1,
11358 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11359 );
11360 }
11361 }
11362
11363 // ── EphemeralSpec::output_arity_is_one pins ─────────────────────
11364 //
11365 // Fail-before-pass-after granularity: `output_arity_is_one` did not
11366 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11367 // the "does this ephemeral spec's DAG-composition output port emit
11368 // to a single downstream edge?" question went through
11369 // `.resolved_classification().point_type.output_arity().is_one()`.
11370 // Post-lift the EIGHTEENTH derived-nullary-boolean peer on the
11371 // ephemeral surface (FIRST on the output-arity axis, opening the
11372 // EIGHTH classification axis into the fixed-tag algebra + the
11373 // SECOND peer on the derived-typed-projection stratum after
11374 // [`Self::input_arity_is_one`]) routes through the SAME
11375 // [`Self::resolved_classification`] resolver + the sibling
11376 // substrate primitive
11377 // [`crate::classification::Classification::output_arity_is_one`],
11378 // so the two-surface parity contract holds by construction.
11379
11380 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11381 /// [`Classification`] carries `point_type: kind` answers
11382 /// [`Self::output_arity_is_one`] matching the closed set's own
11383 /// [`crate::classification::ConvergencePointType::output_arity`]
11384 /// truth table projected through [`Arity::is_one`]. Sweep
11385 /// [`crate::classification::ConvergencePointType::ALL`] so a
11386 /// regression that (a) hard-coded the body to a fixed answer,
11387 /// (b) inverted the projection, (c) dropped the resolver hop, or
11388 /// (d) crossed the wires with the sibling `input_arity`
11389 /// projection (which disagrees on six of eight variants) fails
11390 /// HERE at the substrate primitive before drifting through the
11391 /// future `single-output-arity` fixed tag or the peer point
11392 /// surface.
11393 #[test]
11394 fn output_arity_is_one_returns_output_arity_projection_per_kind() {
11395 for populated in ConvergencePointType::ALL {
11396 let mut classification = Classification::gate_compute();
11397 classification.point_type = populated;
11398 let mut spec = empty_ephemeral();
11399 spec.classification = Some(classification);
11400 assert_eq!(
11401 spec.output_arity_is_one(),
11402 populated.output_arity().is_one(),
11403 "authored point_type={populated:?}: output_arity_is_one() drift",
11404 );
11405 }
11406 }
11407
11408 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11409 /// with `classification: None` routes through the
11410 /// [`Self::resolved_classification`] resolver's substrate default
11411 /// [`Classification::gate_compute`], which carries `point_type:
11412 /// Gate` and `Gate.output_arity() = One`, so
11413 /// [`Self::output_arity_is_one`] returns `true`. Pins the
11414 /// resolver's default-arm short-circuit reaching this derived-
11415 /// nullary predicate — every unadorned `(defephemeral …)` lands
11416 /// in the single-output bucket under the substrate default.
11417 /// Mirror-inverted from the sibling `output_arity_is_many`
11418 /// baseline on the same resolver walk (the XOR partition forces
11419 /// exactly one bucket per baseline). Note the workspace-baseline
11420 /// answer FLIPS between the input-arity and output-arity axes on
11421 /// the exact same absent-classification baseline: the input-arity
11422 /// sibling `input_arity_is_one` answers `false`, but this
11423 /// output-arity peer answers `true` — direct evidence at the
11424 /// resolver-hop layer that the two axes carve the closed set
11425 /// into structurally different partitions.
11426 #[test]
11427 fn output_arity_is_one_probes_true_on_absent_classification() {
11428 let spec = empty_ephemeral();
11429 assert!(spec.classification.is_none());
11430 assert!(
11431 spec.output_arity_is_one(),
11432 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_one=true)",
11433 );
11434 }
11435
11436 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11437 /// identically through [`Self::output_arity_is_one`] AND through
11438 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_one()`
11439 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11440 /// classification, `Some(_)` classification on every
11441 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11442 /// so a future regression on either side of the resolver fails
11443 /// HERE at the parity boundary. Byte-for-byte peer of
11444 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
11445 /// on the sibling output-arity projection via the same
11446 /// resolver-hop shape.
11447 #[test]
11448 fn output_arity_is_one_matches_point_peer_through_lowered_classification() {
11449 // Absent classification.
11450 let eph = empty_ephemeral();
11451 let lowered: ProcessSpec = eph.clone().into();
11452 assert_eq!(
11453 eph.output_arity_is_one(),
11454 lowered.classification.output_arity_is_one(),
11455 "None-classification parity drift",
11456 );
11457 // Authored classification.
11458 for populated in ConvergencePointType::ALL {
11459 let mut classification = Classification::gate_compute();
11460 classification.point_type = populated;
11461 let mut eph = empty_ephemeral();
11462 eph.classification = Some(classification);
11463 let lowered: ProcessSpec = eph.clone().into();
11464 assert_eq!(
11465 eph.output_arity_is_one(),
11466 lowered.classification.output_arity_is_one(),
11467 "authored point_type={populated:?}: parity drift",
11468 );
11469 }
11470 }
11471
11472 // ── EphemeralSpec::output_arity_is_many pins ────────────────────
11473 //
11474 // Fail-before-pass-after granularity: `output_arity_is_many` did
11475 // not exist pre-lift on `impl EphemeralSpec` — the multi-output
11476 // framing peer of [`Self::output_arity_is_one`] had no ephemeral-
11477 // surface substrate owner. Post-lift the NINETEENTH derived-
11478 // nullary-boolean peer on the ephemeral surface (SECOND on the
11479 // output-arity axis, CLOSING the EIGHTH classification axis into
11480 // a binary XOR partition on this surface) routes through the SAME
11481 // [`Self::resolved_classification`] resolver + the sibling
11482 // substrate primitive
11483 // [`crate::classification::Classification::output_arity_is_many`],
11484 // so the two-surface parity contract holds by construction, AND
11485 // the two-way single/many split on this surface CLOSES the
11486 // output-arity axis into the FULL binary XOR partition contract
11487 // via `ephemeral_output_arity_probes_form_binary_xor_partition_over_all`,
11488 // completing the DAG-composition arity PAIR on the ephemeral
11489 // derived-typed-projection stratum.
11490
11491 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11492 /// [`Classification`] carries `point_type: kind` answers
11493 /// [`Self::output_arity_is_many`] matching the closed set's own
11494 /// [`crate::classification::ConvergencePointType::output_arity`]
11495 /// truth table projected through [`Arity::is_many`]. Sweep
11496 /// [`crate::classification::ConvergencePointType::ALL`] so a
11497 /// regression that (a) hard-coded the body to a fixed answer,
11498 /// (b) inverted the projection, (c) dropped the resolver hop, or
11499 /// (d) crossed the wires with the sibling `input_arity`
11500 /// projection fails HERE at the substrate primitive before
11501 /// drifting through the future `multi-output-arity` fixed tag or
11502 /// the peer point surface.
11503 #[test]
11504 fn output_arity_is_many_returns_output_arity_projection_per_kind() {
11505 for populated in ConvergencePointType::ALL {
11506 let mut classification = Classification::gate_compute();
11507 classification.point_type = populated;
11508 let mut spec = empty_ephemeral();
11509 spec.classification = Some(classification);
11510 assert_eq!(
11511 spec.output_arity_is_many(),
11512 populated.output_arity().is_many(),
11513 "authored point_type={populated:?}: output_arity_is_many() drift",
11514 );
11515 }
11516 }
11517
11518 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11519 /// with `classification: None` routes through the
11520 /// [`Self::resolved_classification`] resolver's substrate default
11521 /// [`Classification::gate_compute`], which carries `point_type:
11522 /// Gate` and `Gate.output_arity() = One`, so
11523 /// [`Self::output_arity_is_many`] returns `false`. Pins the
11524 /// resolver's default-arm short-circuit reaching this derived-
11525 /// nullary predicate — every unadorned `(defephemeral …)` lands
11526 /// in the single-output bucket under the substrate default.
11527 /// Mirror-inverted from the sibling `output_arity_is_one`
11528 /// baseline on the same resolver walk (the XOR partition forces
11529 /// exactly one bucket per baseline).
11530 #[test]
11531 fn output_arity_is_many_probes_false_on_absent_classification() {
11532 let spec = empty_ephemeral();
11533 assert!(spec.classification.is_none());
11534 assert!(
11535 !spec.output_arity_is_many(),
11536 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_many=false)",
11537 );
11538 }
11539
11540 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11541 /// identically through [`Self::output_arity_is_many`] AND through
11542 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_many()`
11543 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11544 /// classification, `Some(_)` classification on every
11545 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11546 /// so a future regression on either side of the resolver fails
11547 /// HERE at the parity boundary. Byte-for-byte peer of
11548 /// `output_arity_is_one_matches_point_peer_through_lowered_classification`
11549 /// on the antisymmetric closed-set arm via the same resolver-hop
11550 /// shape.
11551 #[test]
11552 fn output_arity_is_many_matches_point_peer_through_lowered_classification() {
11553 // Absent classification.
11554 let eph = empty_ephemeral();
11555 let lowered: ProcessSpec = eph.clone().into();
11556 assert_eq!(
11557 eph.output_arity_is_many(),
11558 lowered.classification.output_arity_is_many(),
11559 "None-classification parity drift",
11560 );
11561 // Authored classification.
11562 for populated in ConvergencePointType::ALL {
11563 let mut classification = Classification::gate_compute();
11564 classification.point_type = populated;
11565 let mut eph = empty_ephemeral();
11566 eph.classification = Some(classification);
11567 let lowered: ProcessSpec = eph.clone().into();
11568 assert_eq!(
11569 eph.output_arity_is_many(),
11570 lowered.classification.output_arity_is_many(),
11571 "authored point_type={populated:?}: parity drift",
11572 );
11573 }
11574 }
11575
11576 /// BINARY XOR PARTITION pin — for the absent-classification
11577 /// baseline AND every
11578 /// [`crate::classification::ConvergencePointType::ALL`] variant,
11579 /// EXACTLY ONE of [`Self::output_arity_is_one`] and
11580 /// [`Self::output_arity_is_many`] returns `true`. CLOSES the
11581 /// output-arity axis into the FULL binary XOR partition contract
11582 /// on the ephemeral surface — the resolver-hop peer of the
11583 /// parent-composed
11584 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`
11585 /// test. Binary counterpart of the ternary XOR partitions sealed
11586 /// on the sibling `point_type` and `substrate` axes by
11587 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11588 /// and
11589 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11590 /// structural twin of the calm/data/direction/input-arity binary
11591 /// partitions on this surface. This pin is the EIGHTH
11592 /// classification axis to reach the closed XOR partition landmark
11593 /// on the ephemeral resolver-hop surface — the SECOND closed axis
11594 /// on the derived-typed-projection stratum of this surface,
11595 /// completing the DAG-composition arity PAIR on the ephemeral
11596 /// stratum after the input-arity closure. Guarantees the absent-
11597 /// classification case lands in the definite single-output bucket
11598 /// (`gate_compute` → point_type=Gate → output_arity=One →
11599 /// is_one=true, is_many=false), so every unadorned
11600 /// `(defephemeral …)` audits under a definite non-empty
11601 /// output-arity bucket.
11602 #[test]
11603 fn ephemeral_output_arity_probes_form_binary_xor_partition_over_all() {
11604 // Absent classification.
11605 let eph = empty_ephemeral();
11606 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
11607 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11608 assert_eq!(
11609 hits, 1,
11610 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11611 );
11612 // Authored classification.
11613 for populated in ConvergencePointType::ALL {
11614 let mut classification = Classification::gate_compute();
11615 classification.point_type = populated;
11616 let mut eph = empty_ephemeral();
11617 eph.classification = Some(classification);
11618 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
11619 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11620 assert_eq!(
11621 hits, 1,
11622 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11623 );
11624 }
11625 }
11626
11627 /// BINARY XOR PARTITION pin — for the absent-classification
11628 /// baseline AND every
11629 /// [`crate::classification::HorizonKind::ALL`] variant, EXACTLY
11630 /// ONE of [`Self::horizon_terminates`] and
11631 /// [`Self::horizon_requires_metric_axes`] returns `true`. CLOSES
11632 /// the horizon axis into the FULL binary XOR partition contract
11633 /// on the ephemeral surface — the resolver-hop peer of the
11634 /// parent-composed
11635 /// `classification_horizon_probes_form_binary_xor_partition_over_all`
11636 /// test. Binary counterpart of the ternary XOR partitions sealed
11637 /// on the sibling `point_type` and `substrate` axes by
11638 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11639 /// and
11640 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11641 /// structural twin of the calm/data binary partitions
11642 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`
11643 /// and
11644 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11645 /// This pin is the FIFTH (and final) classification axis to reach
11646 /// the closed XOR partition landmark on the ephemeral resolver-
11647 /// hop surface, sealing every classification axis under the
11648 /// SAME `hits == 1` bucket-array contract. Guarantees the absent-
11649 /// classification case lands in the definite terminating bucket
11650 /// (`gate_compute` → HorizonKind::Bounded → terminates = true,
11651 /// requires_metric_axes = false), so every unadorned
11652 /// `(defephemeral …)` audits under a definite non-empty horizon
11653 /// bucket. Rewritten from the earlier binary-XOR-only form
11654 /// (walked as `a ^ b`) into the canonical bucket-array shape
11655 /// shared with the calm/data partitions.
11656 #[test]
11657 fn ephemeral_horizon_probes_form_binary_xor_partition_over_all() {
11658 // Absent classification.
11659 let eph = empty_ephemeral();
11660 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
11661 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11662 assert_eq!(
11663 hits, 1,
11664 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11665 );
11666 // Authored classification.
11667 for populated in HorizonKind::ALL {
11668 let classification = Classification::gate_compute_with_axis(populated);
11669 let mut eph = empty_ephemeral();
11670 eph.classification = Some(classification);
11671 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
11672 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11673 assert_eq!(
11674 hits, 1,
11675 "authored horizon.kind={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11676 );
11677 }
11678 }
11679
11680 // ── EphemeralSpec::has_routing_form pins ─────────────────────────
11681 //
11682 // Fail-before-pass-after granularity: `has_routing_form` did not
11683 // exist pre-lift on `impl EphemeralSpec` — the point-surface
11684 // `routing-form-<kind>` prefix family in tatara-check routed
11685 // through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`
11686 // inline, so the ephemeral surface had no matching primitive to
11687 // publish the SAME `routing-form-<kind>` prefix family through
11688 // the `strip_and_classify_prefixed_kind` substrate. Post-lift the
11689 // Option-gated derived-scalar-child probe body lives at ONE
11690 // inherent site on [`EphemeralSpec`] and every consumer (this
11691 // module's peer-symmetry tests, tatara-check's ephemeral
11692 // require-tag classifier, any future audit dispatcher walking
11693 // [`RoutingForm::ALL`] over the ephemeral surface) binds through
11694 // the SAME `has_routing_form(kind)` shape.
11695
11696 fn routing_spec(is_stable: bool) -> RoutingSpec {
11697 use crate::routing::{RoutingBackend, RoutingHostname};
11698 RoutingSpec {
11699 hostnames: vec![RoutingHostname::content_hashed("api")],
11700 backend: RoutingBackend::plain("svc", 80),
11701 stable_name_claim: is_stable,
11702 priority: 0,
11703 }
11704 }
11705
11706 /// POPULATED-slot pin — a populated `routing` slot answers `true`
11707 /// exactly for the [`RoutingForm`] variant its
11708 /// [`RoutingSpec::has_form`] derived-scalar arm agrees with, and
11709 /// `false` for every other variant. Sweep the two-boolean × ALL
11710 /// cross so a regression that (a) hard-coded the arm to a single
11711 /// variant, (b) dropped the Option-parent gate (silently reading
11712 /// through `.unwrap_or_default()` on an absent routing slot), or
11713 /// (c) crossed the wires from
11714 /// [`RoutingForm::from_is_stable`] to a fixed variant fails
11715 /// HERE before landing at the operator-facing checks.lisp
11716 /// surface.
11717 #[test]
11718 fn has_routing_form_returns_true_iff_populated_routing_derives_form_per_kind() {
11719 for is_stable in [true, false] {
11720 let populated = RoutingForm::from_is_stable(is_stable);
11721 let mut spec = empty_ephemeral();
11722 spec.routing = Some(routing_spec(is_stable));
11723 for query in RoutingForm::ALL {
11724 let expected = query == populated;
11725 assert_eq!(
11726 spec.has_routing_form(query),
11727 expected,
11728 "ephemeral routing.stable_name_claim={is_stable} (derives {populated:?}): query {query:?} drifted",
11729 );
11730 }
11731 }
11732 }
11733
11734 /// OPTION-PARENT SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
11735 /// `routing` slot is `None` returns `false` for every
11736 /// [`RoutingForm`] variant, INCLUDING the closed set's
11737 /// derived-default [`RoutingForm::Instance`]. Locks the
11738 /// Option-parent silencing contract so a regression that dropped
11739 /// the `spec.routing.as_ref()` gate (silently probing an absent
11740 /// routing slot as if it carried the defaulted `Instance` form)
11741 /// fails HERE. Peer to
11742 /// [`evaluate_point_require_tag_returns_false_on_absent_routing_for_every_routing_form_kind`]
11743 /// on the point surface — the two-surface symmetry means both
11744 /// classifiers publish the SAME Option-parent silencing at ONE
11745 /// substrate site per surface.
11746 #[test]
11747 fn has_routing_form_returns_false_on_absent_routing_for_every_kind() {
11748 let spec = empty_ephemeral();
11749 assert!(spec.routing.is_none());
11750 for kind in RoutingForm::ALL {
11751 assert!(
11752 !spec.has_routing_form(kind),
11753 "absent ephemeral routing must return false for {kind:?}",
11754 );
11755 }
11756 }
11757
11758 /// DEFAULT-ARM SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
11759 /// `routing` slot is a [`RoutingSpec`] with `stable_name_claim`
11760 /// at its `#[serde(default)]` (bool default = `false`) answers
11761 /// `true` on [`RoutingForm::Instance`] and `false` on every other
11762 /// variant WITHOUT the operator naming the routing-form axis on
11763 /// the routing spec. Peer to
11764 /// [`evaluate_point_require_tag_returns_true_on_default_routing_form_for_instance_only`]
11765 /// on the point surface — both surfaces read the derived-child
11766 /// arm through the ONE substrate composer
11767 /// [`RoutingForm::from_is_stable`], so a future normalization at
11768 /// the derivation lands at ONE site and every downstream
11769 /// (routing-form require-tag families on both surfaces,
11770 /// closed-set audit dispatchers) picks it up mechanically.
11771 #[test]
11772 fn has_routing_form_probes_instance_only_on_default_populated_routing() {
11773 let mut spec = empty_ephemeral();
11774 spec.routing = Some(routing_spec(bool::default()));
11775 for kind in RoutingForm::ALL {
11776 let expected = kind == RoutingForm::Instance;
11777 assert_eq!(
11778 spec.has_routing_form(kind),
11779 expected,
11780 "default-populated ephemeral routing (stable_name_claim=false → Instance) baseline: query {kind:?} must be {expected}",
11781 );
11782 }
11783 }
11784
11785 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
11786 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
11787 /// answer identically on every [`RoutingForm`] × `is_stable`
11788 /// combination. Locks the byte-for-byte parity between
11789 /// [`EphemeralSpec::has_routing_form`] (this new primitive) and
11790 /// the point surface's `spec.routing.as_ref().is_some_and(|r|
11791 /// r.has_form(k))` inline projection at the tatara-check dispatch
11792 /// site. A regression that (a) diverged the ephemeral probe from
11793 /// the lowered point probe (e.g., dropped the Option-parent gate
11794 /// on ONE side, crossed the derived-child arm on the OTHER), or
11795 /// (b) diverged the `From<EphemeralSpec>` lowering's
11796 /// `routing: e.routing` copy from byte-for-byte forwarding, fails
11797 /// HERE at the two-surface boundary.
11798 #[test]
11799 fn has_routing_form_matches_point_peer_through_lowered_routing() {
11800 for is_stable in [true, false] {
11801 let mut authored = empty_ephemeral();
11802 authored.routing = Some(routing_spec(is_stable));
11803 let lowered: ProcessSpec = authored.clone().into();
11804 for kind in RoutingForm::ALL {
11805 let ephemeral_answer = authored.has_routing_form(kind);
11806 let point_answer = lowered.routing.as_ref().is_some_and(|r| r.has_form(kind));
11807 assert_eq!(
11808 ephemeral_answer, point_answer,
11809 "two-surface routing-form parity drift: stable_name_claim={is_stable}, kind={kind:?}",
11810 );
11811 }
11812 }
11813 }
11814
11815 // ── EphemeralSpec::has_applicable_exports_at substrate pins ───────
11816 //
11817 // Fail-before-pass-after granularity: `has_applicable_exports_at`
11818 // did not exist pre-lift on `impl EphemeralSpec` — the peer
11819 // `EphemeralLifetime::has_applicable_exports` on the lowered
11820 // `ProcessSpec` surface routed through the compound
11821 // `.iter().any(|e| e.when.fires_on(phase))` chain inline, so the
11822 // sugar surface had no matching primitive to publish an
11823 // `exports-fire-on-<phase>` prefix family through the
11824 // `strip_and_classify_prefixed_kind` substrate. Post-lift the
11825 // compound-`(when, phase) → fires_on(phase)` probe body lives at
11826 // ONE slice-level substrate site (`ExportSpecSliceExt::has_applicable_at`),
11827 // this ephemeral surface routes through it directly, and the
11828 // point surface reaches the same primitive through
11829 // `spec.lifetime.resolved_ephemeral().is_some_and(|e|
11830 // e.exports.has_applicable_at(phase))`.
11831
11832 fn export_at(when: crate::export::ExportTrigger) -> ExportSpec {
11833 use crate::export::{ArtifactSource, ReceiptsSource, StdoutChannel, VectorChannel};
11834 ExportSpec {
11835 source: ArtifactSource {
11836 receipts: Some(ReceiptsSource::default()),
11837 ..ArtifactSource::default()
11838 },
11839 channel: VectorChannel {
11840 stdout: Some(StdoutChannel::default()),
11841 ..VectorChannel::default()
11842 },
11843 when,
11844 experiment_id_override: None,
11845 }
11846 }
11847
11848 /// EMPTY-EXPORTS pin — an ephemeral spec with an empty `exports`
11849 /// vec returns `false` for EVERY [`ProcessPhase`]. Sweep
11850 /// [`ProcessPhase::ALL`] so a new variant added without a matching
11851 /// arm in [`crate::export::ExportTrigger::fires_on`] surfaces at
11852 /// rustc's exhaustiveness gate on the `ALL` literal (arity forced
11853 /// by `[Self; 11]`) rather than as a silent false-positive at
11854 /// every downstream `exports-fire-on-<phase>` ephemeral require-tag
11855 /// callsite.
11856 #[test]
11857 fn has_applicable_exports_at_returns_false_on_empty_exports_for_every_phase() {
11858 let spec = empty_ephemeral();
11859 assert!(spec.exports.is_empty());
11860 for phase in ProcessPhase::ALL {
11861 assert!(
11862 !spec.has_applicable_exports_at(phase),
11863 "empty-exports ephemeral must return false for {phase:?}",
11864 );
11865 }
11866 }
11867
11868 /// PER-TRIGGER × PER-PHASE pin — an ephemeral spec with a single
11869 /// export answers `has_applicable_exports_at` identically to the
11870 /// [`crate::export::ExportTrigger::fires_on`] truth table on that
11871 /// (trigger, phase) pair, for every combination. Sweep the
11872 /// [`crate::export::ExportTrigger::ALL`] × [`ProcessPhase::ALL`]
11873 /// cross so a regression that (a) short-circuited to raw `when ==
11874 /// kind` equality, (b) missed `Always`'s dual-phase coverage, or
11875 /// (c) inverted a non-terminal phase to return `true` fails HERE
11876 /// at the substrate primitive rather than at each downstream
11877 /// `exports-fire-on-<phase>` classifier callsite.
11878 #[test]
11879 fn has_applicable_exports_at_matches_fires_on_truth_table_per_pair() {
11880 for trigger in crate::export::ExportTrigger::ALL {
11881 let mut spec = empty_ephemeral();
11882 spec.exports = vec![export_at(trigger)];
11883 for phase in ProcessPhase::ALL {
11884 let expected = trigger.fires_on(phase);
11885 assert_eq!(
11886 spec.has_applicable_exports_at(phase),
11887 expected,
11888 "ephemeral trigger={trigger:?} phase={phase:?} drifted from fires_on",
11889 );
11890 }
11891 }
11892 }
11893
11894 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
11895 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
11896 /// answer identically on every [`ProcessPhase`] × trigger
11897 /// combination. Locks the byte-for-byte parity between
11898 /// [`EphemeralSpec::has_applicable_exports_at`] (this new primitive)
11899 /// and the point surface's `spec.lifetime.resolved_ephemeral()
11900 /// .is_some_and(|e| e.exports.has_applicable_at(phase))` projection
11901 /// at the tatara-check dispatch site. A regression that (a)
11902 /// diverged the ephemeral probe from the lowered-lifetime probe,
11903 /// (b) diverged the `From<EphemeralSpec>` lowering's
11904 /// `exports: e.exports` copy from byte-for-byte forwarding, fails
11905 /// HERE at the two-surface boundary.
11906 #[test]
11907 fn has_applicable_exports_at_matches_point_peer_through_lowered_exports() {
11908 for trigger in crate::export::ExportTrigger::ALL {
11909 let mut authored = empty_ephemeral();
11910 authored.exports = vec![export_at(trigger)];
11911 let lowered: ProcessSpec = authored.clone().into();
11912 for phase in ProcessPhase::ALL {
11913 let ephemeral_answer = authored.has_applicable_exports_at(phase);
11914 let point_answer = lowered
11915 .lifetime
11916 .resolved_ephemeral()
11917 .is_some_and(|e| e.exports.has_applicable_at(phase));
11918 assert_eq!(
11919 ephemeral_answer, point_answer,
11920 "two-surface exports-fire-on parity drift: trigger={trigger:?}, phase={phase:?}",
11921 );
11922 }
11923 }
11924 }
11925
11926 /// SUBSTRATE-DELEGATION pin (EphemeralSpec saturation-predicate
11927 /// triad) — the three `is_*_kind_saturated` methods on
11928 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
11929 /// [`ConditionSliceExt::is_kind_saturated`] over the two
11930 /// `Vec<Condition>` slots (precondition + postcondition) and
11931 /// compose the union via `ConditionKind::ALL.iter().all(|k|
11932 /// has_condition_kind(*k))`. Two-surface parity pin against
11933 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on the
11934 /// point-domain [`ProcessSpec`] surface — the two struct-level
11935 /// saturation callers compose against the SAME slice-level
11936 /// substrate primitive so a regression at the per-slice `all`
11937 /// short-circuit fails at that primitive's tests rather than as
11938 /// silent drift at either sugar-surface arm.
11939 #[test]
11940 fn is_condition_kind_saturated_triad_delegates_to_slice_is_kind_saturated() {
11941 // Empty ephemeral spec — every arm returns false.
11942 let spec = empty_ephemeral();
11943 assert!(
11944 !spec.is_precondition_kind_saturated(),
11945 "empty ephemeral must return false on is_precondition_kind_saturated",
11946 );
11947 assert!(
11948 !spec.is_postcondition_kind_saturated(),
11949 "empty ephemeral must return false on is_postcondition_kind_saturated",
11950 );
11951 assert!(
11952 !spec.is_condition_kind_saturated(),
11953 "empty ephemeral must return false on is_condition_kind_saturated",
11954 );
11955 assert_eq!(
11956 spec.is_condition_kind_saturated(),
11957 spec.missing_condition_kinds().is_empty(),
11958 "empty is_condition_kind_saturated must equal missing_condition_kinds().is_empty()",
11959 );
11960
11961 // Single-populated per side — sweep ALL × ALL.
11962 for pre_kind in ConditionKind::ALL {
11963 for post_kind in ConditionKind::ALL {
11964 let mut spec = empty_ephemeral();
11965 spec.preconditions.push(cond(pre_kind));
11966 spec.postconditions.push(cond(post_kind));
11967 assert_eq!(
11968 spec.is_precondition_kind_saturated(),
11969 spec.preconditions.is_kind_saturated(),
11970 "EphemeralSpec::is_precondition_kind_saturated must delegate verbatim to \
11971 preconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
11972 );
11973 assert_eq!(
11974 spec.is_postcondition_kind_saturated(),
11975 spec.postconditions.is_kind_saturated(),
11976 "EphemeralSpec::is_postcondition_kind_saturated must delegate verbatim to \
11977 postconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
11978 );
11979 let expected_union = ConditionKind::ALL
11980 .iter()
11981 .all(|k| pre_kind == *k || post_kind == *k);
11982 assert_eq!(
11983 spec.is_condition_kind_saturated(),
11984 expected_union,
11985 "EphemeralSpec::is_condition_kind_saturated must equal all-ALL-covered-by-either-slice \
11986 for pre={pre_kind:?} post={post_kind:?}",
11987 );
11988
11989 // Two-surface parity: lowered ProcessSpec's Boundary
11990 // must agree bit-for-bit with the ephemeral sugar
11991 // triad on every arm.
11992 let lowered: ProcessSpec = spec.clone().into();
11993 assert_eq!(
11994 spec.is_precondition_kind_saturated(),
11995 lowered.boundary.is_precondition_kind_saturated(),
11996 "two-surface is_precondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
11997 );
11998 assert_eq!(
11999 spec.is_postcondition_kind_saturated(),
12000 lowered.boundary.is_postcondition_kind_saturated(),
12001 "two-surface is_postcondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12002 );
12003 assert_eq!(
12004 spec.is_condition_kind_saturated(),
12005 lowered.boundary.is_condition_kind_saturated(),
12006 "two-surface is_condition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12007 );
12008 }
12009 }
12010
12011 // Saturated ephemeral — both slices carry every ConditionKind,
12012 // every arm returns true.
12013 let mut spec = empty_ephemeral();
12014 for k in ConditionKind::ALL {
12015 spec.preconditions.push(cond(k));
12016 spec.postconditions.push(cond(k));
12017 }
12018 assert!(
12019 spec.is_precondition_kind_saturated(),
12020 "saturated ephemeral must return true on is_precondition_kind_saturated",
12021 );
12022 assert!(
12023 spec.is_postcondition_kind_saturated(),
12024 "saturated ephemeral must return true on is_postcondition_kind_saturated",
12025 );
12026 assert!(
12027 spec.is_condition_kind_saturated(),
12028 "saturated ephemeral must return true on is_condition_kind_saturated",
12029 );
12030 }
12031
12032 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
12033 /// triad) — the three `has_any_missing_*_condition_kind` methods
12034 /// on [`EphemeralSpec`] delegate to the slice-level substrate
12035 /// primitive
12036 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
12037 /// over the two `Vec<Condition>` slots (precondition +
12038 /// postcondition) and compose the union via
12039 /// `!self.is_condition_kind_saturated()`. Two-surface parity pin
12040 /// against
12041 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
12042 /// the point-domain [`ProcessSpec`] surface — the two struct-level
12043 /// at-least-one halfspace callers compose against the SAME slice-
12044 /// level substrate primitive so a regression at the per-slice
12045 /// `all` short-circuit under negation fails at that primitive's
12046 /// tests rather than as silent drift at either sugar-surface arm.
12047 #[test]
12048 fn has_any_missing_condition_kind_triad_delegates_to_slice_has_any_missing_kind() {
12049 // Empty ephemeral spec — every arm returns true (every kind is
12050 // missing from every slice + from the union).
12051 let spec = empty_ephemeral();
12052 assert!(
12053 spec.has_any_missing_precondition_kind(),
12054 "empty ephemeral must return true on has_any_missing_precondition_kind",
12055 );
12056 assert!(
12057 spec.has_any_missing_postcondition_kind(),
12058 "empty ephemeral must return true on has_any_missing_postcondition_kind",
12059 );
12060 assert!(
12061 spec.has_any_missing_condition_kind(),
12062 "empty ephemeral must return true on has_any_missing_condition_kind",
12063 );
12064 assert_eq!(
12065 spec.has_any_missing_condition_kind(),
12066 !spec.is_condition_kind_saturated(),
12067 "empty has_any_missing_condition_kind must equal !is_condition_kind_saturated()",
12068 );
12069
12070 // Single-populated per side — sweep ALL × ALL, then pin the
12071 // (pre, post, union) triad + two-surface parity against the
12072 // lowered ProcessSpec's Boundary.
12073 for pre_kind in ConditionKind::ALL {
12074 for post_kind in ConditionKind::ALL {
12075 let mut spec = empty_ephemeral();
12076 spec.preconditions.push(cond(pre_kind));
12077 spec.postconditions.push(cond(post_kind));
12078 assert_eq!(
12079 spec.has_any_missing_precondition_kind(),
12080 spec.preconditions.has_any_missing_kind(),
12081 "EphemeralSpec::has_any_missing_precondition_kind must delegate verbatim to \
12082 preconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12083 );
12084 assert_eq!(
12085 spec.has_any_missing_postcondition_kind(),
12086 spec.postconditions.has_any_missing_kind(),
12087 "EphemeralSpec::has_any_missing_postcondition_kind must delegate verbatim to \
12088 postconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12089 );
12090 let expected_union = !ConditionKind::ALL
12091 .iter()
12092 .all(|k| pre_kind == *k || post_kind == *k);
12093 assert_eq!(
12094 spec.has_any_missing_condition_kind(),
12095 expected_union,
12096 "EphemeralSpec::has_any_missing_condition_kind must equal \
12097 !all-ALL-covered-by-either-slice \
12098 for pre={pre_kind:?} post={post_kind:?}",
12099 );
12100
12101 // Two-surface parity: lowered ProcessSpec's Boundary
12102 // must agree bit-for-bit with the ephemeral sugar
12103 // triad on every arm.
12104 let lowered: ProcessSpec = spec.clone().into();
12105 assert_eq!(
12106 spec.has_any_missing_precondition_kind(),
12107 lowered.boundary.has_any_missing_precondition_kind(),
12108 "two-surface has_any_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12109 );
12110 assert_eq!(
12111 spec.has_any_missing_postcondition_kind(),
12112 lowered.boundary.has_any_missing_postcondition_kind(),
12113 "two-surface has_any_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12114 );
12115 assert_eq!(
12116 spec.has_any_missing_condition_kind(),
12117 lowered.boundary.has_any_missing_condition_kind(),
12118 "two-surface has_any_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12119 );
12120 }
12121 }
12122
12123 // Saturated ephemeral — both slices carry every ConditionKind,
12124 // every arm returns false.
12125 let mut spec = empty_ephemeral();
12126 for k in ConditionKind::ALL {
12127 spec.preconditions.push(cond(k));
12128 spec.postconditions.push(cond(k));
12129 }
12130 assert!(
12131 !spec.has_any_missing_precondition_kind(),
12132 "saturated ephemeral must return false on has_any_missing_precondition_kind",
12133 );
12134 assert!(
12135 !spec.has_any_missing_postcondition_kind(),
12136 "saturated ephemeral must return false on has_any_missing_postcondition_kind",
12137 );
12138 assert!(
12139 !spec.has_any_missing_condition_kind(),
12140 "saturated ephemeral must return false on has_any_missing_condition_kind",
12141 );
12142 }
12143
12144 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
12145 /// triad on the closed-set-inversion axis) — the three
12146 /// `has_any_distinct_*_condition_kind` methods on
12147 /// [`EphemeralSpec`] delegate to the slice-level substrate
12148 /// primitive
12149 /// [`crate::boundary::ConditionSliceExt::has_any_distinct_kind`]
12150 /// over the two `Vec<Condition>` slots (precondition +
12151 /// postcondition) and compose the union via a SHORT-CIRCUITING
12152 /// closed-set walk over [`ConditionKind::ALL`] under
12153 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12154 /// against
12155 /// [`crate::boundary::Boundary::has_any_distinct_condition_kind`]
12156 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12157 /// level at-least-one halfspace callers compose against the SAME
12158 /// slice-level substrate primitive so a regression at the per-
12159 /// slice `any` short-circuit fails at that primitive's tests
12160 /// rather than as silent drift at either sugar-surface arm.
12161 #[test]
12162 fn has_any_distinct_condition_kind_triad_delegates_to_slice_has_any_distinct_kind() {
12163 // Empty ephemeral spec — every arm returns false (no kind
12164 // present in either slice).
12165 let spec = empty_ephemeral();
12166 assert!(
12167 !spec.has_any_distinct_precondition_kind(),
12168 "empty ephemeral must return false on has_any_distinct_precondition_kind",
12169 );
12170 assert!(
12171 !spec.has_any_distinct_postcondition_kind(),
12172 "empty ephemeral must return false on has_any_distinct_postcondition_kind",
12173 );
12174 assert!(
12175 !spec.has_any_distinct_condition_kind(),
12176 "empty ephemeral must return false on has_any_distinct_condition_kind",
12177 );
12178
12179 // Single-populated per side — sweep ALL × ALL, then pin the
12180 // (pre, post, union) triad + two-surface parity against the
12181 // lowered ProcessSpec's Boundary.
12182 for pre_kind in ConditionKind::ALL {
12183 for post_kind in ConditionKind::ALL {
12184 let mut spec = empty_ephemeral();
12185 spec.preconditions.push(cond(pre_kind));
12186 spec.postconditions.push(cond(post_kind));
12187 assert_eq!(
12188 spec.has_any_distinct_precondition_kind(),
12189 spec.preconditions.has_any_distinct_kind(),
12190 "EphemeralSpec::has_any_distinct_precondition_kind must delegate verbatim to \
12191 preconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12192 );
12193 assert_eq!(
12194 spec.has_any_distinct_postcondition_kind(),
12195 spec.postconditions.has_any_distinct_kind(),
12196 "EphemeralSpec::has_any_distinct_postcondition_kind must delegate verbatim to \
12197 postconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12198 );
12199 assert!(
12200 spec.has_any_distinct_precondition_kind(),
12201 "single-populated preconditions must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
12202 );
12203 assert!(
12204 spec.has_any_distinct_postcondition_kind(),
12205 "single-populated postconditions must return true on has_any_distinct_postcondition_kind for post={post_kind:?}",
12206 );
12207 assert!(
12208 spec.has_any_distinct_condition_kind(),
12209 "single-populated-per-side must return true on has_any_distinct_condition_kind for pre={pre_kind:?} post={post_kind:?}",
12210 );
12211
12212 // Two-surface parity: lowered ProcessSpec's Boundary
12213 // must agree bit-for-bit with the ephemeral sugar
12214 // triad on every arm.
12215 let lowered: ProcessSpec = spec.clone().into();
12216 assert_eq!(
12217 spec.has_any_distinct_precondition_kind(),
12218 lowered.boundary.has_any_distinct_precondition_kind(),
12219 "two-surface has_any_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12220 );
12221 assert_eq!(
12222 spec.has_any_distinct_postcondition_kind(),
12223 lowered.boundary.has_any_distinct_postcondition_kind(),
12224 "two-surface has_any_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12225 );
12226 assert_eq!(
12227 spec.has_any_distinct_condition_kind(),
12228 lowered.boundary.has_any_distinct_condition_kind(),
12229 "two-surface has_any_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12230 );
12231 }
12232 }
12233
12234 // Single-populated precondition only — precondition arm true,
12235 // postcondition arm false, union true.
12236 for pre_kind in ConditionKind::ALL {
12237 let mut spec = empty_ephemeral();
12238 spec.preconditions.push(cond(pre_kind));
12239 assert!(
12240 spec.has_any_distinct_precondition_kind(),
12241 "pre-only ephemeral must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
12242 );
12243 assert!(
12244 !spec.has_any_distinct_postcondition_kind(),
12245 "pre-only ephemeral must return false on has_any_distinct_postcondition_kind for pre={pre_kind:?}",
12246 );
12247 assert!(
12248 spec.has_any_distinct_condition_kind(),
12249 "pre-only ephemeral must return true on has_any_distinct_condition_kind for pre={pre_kind:?}",
12250 );
12251 }
12252
12253 // Saturated ephemeral — both slices carry every ConditionKind,
12254 // every arm returns true.
12255 let mut spec = empty_ephemeral();
12256 for k in ConditionKind::ALL {
12257 spec.preconditions.push(cond(k));
12258 spec.postconditions.push(cond(k));
12259 }
12260 assert!(
12261 spec.has_any_distinct_precondition_kind(),
12262 "saturated ephemeral must return true on has_any_distinct_precondition_kind",
12263 );
12264 assert!(
12265 spec.has_any_distinct_postcondition_kind(),
12266 "saturated ephemeral must return true on has_any_distinct_postcondition_kind",
12267 );
12268 assert!(
12269 spec.has_any_distinct_condition_kind(),
12270 "saturated ephemeral must return true on has_any_distinct_condition_kind",
12271 );
12272 }
12273
12274 /// SUBSTRATE-DELEGATION pin (EphemeralSpec singleton-coverage
12275 /// triad on the closed-set-inversion axis) — the three
12276 /// `has_unique_distinct_*_condition_kind` methods on
12277 /// [`EphemeralSpec`] delegate to the slice-level substrate
12278 /// primitive
12279 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
12280 /// over the two `Vec<Condition>` slots (precondition +
12281 /// postcondition) and compose the union via a two-step-short-
12282 /// circuit walk over [`ConditionKind::ALL`] under
12283 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12284 /// against
12285 /// [`crate::boundary::Boundary::has_unique_distinct_condition_kind`]
12286 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12287 /// level singleton-coverage callers compose against the SAME
12288 /// slice-level substrate primitive so a regression at the per-
12289 /// slice two-step short-circuit walk fails at that primitive's
12290 /// tests rather than as silent drift at either sugar-surface arm.
12291 #[test]
12292 fn has_unique_distinct_condition_kind_triad_delegates_to_slice_has_unique_distinct_kind() {
12293 // Empty ephemeral spec — every arm returns false (0 distinct,
12294 // not exactly 1).
12295 let spec = empty_ephemeral();
12296 assert!(
12297 !spec.has_unique_distinct_precondition_kind(),
12298 "empty ephemeral must return false on has_unique_distinct_precondition_kind",
12299 );
12300 assert!(
12301 !spec.has_unique_distinct_postcondition_kind(),
12302 "empty ephemeral must return false on has_unique_distinct_postcondition_kind",
12303 );
12304 assert!(
12305 !spec.has_unique_distinct_condition_kind(),
12306 "empty ephemeral must return false on has_unique_distinct_condition_kind",
12307 );
12308 assert_eq!(
12309 spec.has_unique_distinct_condition_kind(),
12310 spec.distinct_condition_kind_count() == 1,
12311 "empty has_unique_distinct_condition_kind must equal (distinct_condition_kind_count() == 1)",
12312 );
12313
12314 // Single-populated per side — sweep ALL × ALL. Every per-
12315 // slice arm returns true; the union returns true iff the two
12316 // populated kinds coincide (union covers exactly one kind).
12317 for pre_kind in ConditionKind::ALL {
12318 for post_kind in ConditionKind::ALL {
12319 let mut spec = empty_ephemeral();
12320 spec.preconditions.push(cond(pre_kind));
12321 spec.postconditions.push(cond(post_kind));
12322 assert_eq!(
12323 spec.has_unique_distinct_precondition_kind(),
12324 spec.preconditions.has_unique_distinct_kind(),
12325 "EphemeralSpec::has_unique_distinct_precondition_kind must delegate verbatim to \
12326 preconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12327 );
12328 assert_eq!(
12329 spec.has_unique_distinct_postcondition_kind(),
12330 spec.postconditions.has_unique_distinct_kind(),
12331 "EphemeralSpec::has_unique_distinct_postcondition_kind must delegate verbatim to \
12332 postconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12333 );
12334 let covered_count = ConditionKind::ALL
12335 .into_iter()
12336 .filter(|k| *k == pre_kind || *k == post_kind)
12337 .count();
12338 let expected_union = covered_count == 1;
12339 assert_eq!(
12340 spec.has_unique_distinct_condition_kind(),
12341 expected_union,
12342 "EphemeralSpec::has_unique_distinct_condition_kind must equal \
12343 (covered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
12344 );
12345
12346 // Two-surface parity: lowered ProcessSpec's Boundary
12347 // must agree bit-for-bit with the ephemeral sugar
12348 // triad on every arm.
12349 let lowered: ProcessSpec = spec.clone().into();
12350 assert_eq!(
12351 spec.has_unique_distinct_precondition_kind(),
12352 lowered.boundary.has_unique_distinct_precondition_kind(),
12353 "two-surface has_unique_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12354 );
12355 assert_eq!(
12356 spec.has_unique_distinct_postcondition_kind(),
12357 lowered.boundary.has_unique_distinct_postcondition_kind(),
12358 "two-surface has_unique_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12359 );
12360 assert_eq!(
12361 spec.has_unique_distinct_condition_kind(),
12362 lowered.boundary.has_unique_distinct_condition_kind(),
12363 "two-surface has_unique_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12364 );
12365 }
12366 }
12367
12368 // Saturated ephemeral — every arm returns false on N ≥ 2 (N
12369 // distinct, not exactly 1).
12370 if ConditionKind::ALL.len() >= 2 {
12371 let mut spec = empty_ephemeral();
12372 for k in ConditionKind::ALL {
12373 spec.preconditions.push(cond(k));
12374 spec.postconditions.push(cond(k));
12375 }
12376 assert!(
12377 !spec.has_unique_distinct_precondition_kind(),
12378 "saturated ephemeral must return false on has_unique_distinct_precondition_kind",
12379 );
12380 assert!(
12381 !spec.has_unique_distinct_postcondition_kind(),
12382 "saturated ephemeral must return false on has_unique_distinct_postcondition_kind",
12383 );
12384 assert!(
12385 !spec.has_unique_distinct_condition_kind(),
12386 "saturated ephemeral must return false on has_unique_distinct_condition_kind",
12387 );
12388 }
12389 }
12390
12391 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-mid-endpoint
12392 /// triad) — the three `has_unique_missing_*_condition_kind`
12393 /// methods on [`EphemeralSpec`] delegate to the slice-level
12394 /// substrate primitive
12395 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
12396 /// over the two `Vec<Condition>` slots (precondition +
12397 /// postcondition) and compose the union via a two-step-short-
12398 /// circuit walk over [`ConditionKind::ALL`] under negated
12399 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12400 /// against
12401 /// [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
12402 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12403 /// level near-saturation-endpoint callers compose against the
12404 /// SAME slice-level substrate primitive so a regression at the
12405 /// per-slice two-step short-circuit walk under negation fails at
12406 /// that primitive's tests rather than as silent drift at either
12407 /// sugar-surface arm.
12408 #[test]
12409 fn has_unique_missing_condition_kind_triad_delegates_to_slice_has_unique_missing_kind() {
12410 // Empty ephemeral spec — every arm returns false (all N
12411 // missing, not exactly 1) on any N ≥ 2 closed set.
12412 assert!(
12413 ConditionKind::ALL.len() >= 2,
12414 "test assumes ConditionKind::ALL has ≥ 2 variants",
12415 );
12416 let spec = empty_ephemeral();
12417 assert!(
12418 !spec.has_unique_missing_precondition_kind(),
12419 "empty ephemeral must return false on has_unique_missing_precondition_kind",
12420 );
12421 assert!(
12422 !spec.has_unique_missing_postcondition_kind(),
12423 "empty ephemeral must return false on has_unique_missing_postcondition_kind",
12424 );
12425 assert!(
12426 !spec.has_unique_missing_condition_kind(),
12427 "empty ephemeral must return false on has_unique_missing_condition_kind",
12428 );
12429 assert_eq!(
12430 spec.has_unique_missing_condition_kind(),
12431 spec.missing_condition_kind_count() == 1,
12432 "empty has_unique_missing_condition_kind must equal (missing_condition_kind_count() == 1)",
12433 );
12434
12435 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
12436 // sets. Every per-slice arm returns false; the union returns
12437 // true iff exactly one ALL variant is uncovered.
12438 if ConditionKind::ALL.len() >= 3 {
12439 for pre_kind in ConditionKind::ALL {
12440 for post_kind in ConditionKind::ALL {
12441 let mut spec = empty_ephemeral();
12442 spec.preconditions.push(cond(pre_kind));
12443 spec.postconditions.push(cond(post_kind));
12444 assert_eq!(
12445 spec.has_unique_missing_precondition_kind(),
12446 spec.preconditions.has_unique_missing_kind(),
12447 "EphemeralSpec::has_unique_missing_precondition_kind must delegate verbatim to \
12448 preconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12449 );
12450 assert_eq!(
12451 spec.has_unique_missing_postcondition_kind(),
12452 spec.postconditions.has_unique_missing_kind(),
12453 "EphemeralSpec::has_unique_missing_postcondition_kind must delegate verbatim to \
12454 postconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12455 );
12456 let uncovered = ConditionKind::ALL
12457 .into_iter()
12458 .filter(|k| *k != pre_kind && *k != post_kind)
12459 .count();
12460 let expected_union = uncovered == 1;
12461 assert_eq!(
12462 spec.has_unique_missing_condition_kind(),
12463 expected_union,
12464 "EphemeralSpec::has_unique_missing_condition_kind must equal \
12465 (uncovered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
12466 );
12467
12468 // Two-surface parity: lowered ProcessSpec's
12469 // Boundary must agree bit-for-bit with the
12470 // ephemeral sugar triad on every arm.
12471 let lowered: ProcessSpec = spec.clone().into();
12472 assert_eq!(
12473 spec.has_unique_missing_precondition_kind(),
12474 lowered.boundary.has_unique_missing_precondition_kind(),
12475 "two-surface has_unique_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12476 );
12477 assert_eq!(
12478 spec.has_unique_missing_postcondition_kind(),
12479 lowered.boundary.has_unique_missing_postcondition_kind(),
12480 "two-surface has_unique_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12481 );
12482 assert_eq!(
12483 spec.has_unique_missing_condition_kind(),
12484 lowered.boundary.has_unique_missing_condition_kind(),
12485 "two-surface has_unique_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12486 );
12487 }
12488 }
12489 }
12490
12491 // Near-saturation-endpoint per side — each slice carries
12492 // every ConditionKind except one. Every per-slice arm returns
12493 // true; the union returns true iff BOTH slices omit the SAME
12494 // kind.
12495 for pre_omit in ConditionKind::ALL {
12496 for post_omit in ConditionKind::ALL {
12497 let mut spec = empty_ephemeral();
12498 for k in ConditionKind::ALL {
12499 if k != pre_omit {
12500 spec.preconditions.push(cond(k));
12501 }
12502 if k != post_omit {
12503 spec.postconditions.push(cond(k));
12504 }
12505 }
12506 assert!(
12507 spec.has_unique_missing_precondition_kind(),
12508 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_unique_missing_precondition_kind",
12509 );
12510 assert!(
12511 spec.has_unique_missing_postcondition_kind(),
12512 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_unique_missing_postcondition_kind",
12513 );
12514 let expected_union = pre_omit == post_omit;
12515 assert_eq!(
12516 spec.has_unique_missing_condition_kind(),
12517 expected_union,
12518 "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:?}",
12519 );
12520
12521 // Two-surface parity for near-saturation arm.
12522 let lowered: ProcessSpec = spec.clone().into();
12523 assert_eq!(
12524 spec.has_unique_missing_precondition_kind(),
12525 lowered.boundary.has_unique_missing_precondition_kind(),
12526 "two-surface has_unique_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12527 );
12528 assert_eq!(
12529 spec.has_unique_missing_postcondition_kind(),
12530 lowered.boundary.has_unique_missing_postcondition_kind(),
12531 "two-surface has_unique_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12532 );
12533 assert_eq!(
12534 spec.has_unique_missing_condition_kind(),
12535 lowered.boundary.has_unique_missing_condition_kind(),
12536 "two-surface has_unique_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12537 );
12538 }
12539 }
12540
12541 // Saturated ephemeral — every arm returns false (0 missing,
12542 // not exactly 1).
12543 let mut spec = empty_ephemeral();
12544 for k in ConditionKind::ALL {
12545 spec.preconditions.push(cond(k));
12546 spec.postconditions.push(cond(k));
12547 }
12548 assert!(
12549 !spec.has_unique_missing_precondition_kind(),
12550 "saturated ephemeral must return false on has_unique_missing_precondition_kind",
12551 );
12552 assert!(
12553 !spec.has_unique_missing_postcondition_kind(),
12554 "saturated ephemeral must return false on has_unique_missing_postcondition_kind",
12555 );
12556 assert!(
12557 !spec.has_unique_missing_condition_kind(),
12558 "saturated ephemeral must return false on has_unique_missing_condition_kind",
12559 );
12560 }
12561
12562 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
12563 /// triad) — the three `has_multiple_missing_*_condition_kind`
12564 /// methods on [`EphemeralSpec`] delegate to the slice-level
12565 /// substrate primitive
12566 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
12567 /// over the two `Vec<Condition>` slots (precondition +
12568 /// postcondition) and compose the union via a two-step-short-
12569 /// circuit walk over [`ConditionKind::ALL`] under negated
12570 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12571 /// against
12572 /// [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
12573 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12574 /// level cardinality-many-arm callers compose against the SAME
12575 /// slice-level substrate primitive so a regression at the per-
12576 /// slice two-step short-circuit walk under negation fails at that
12577 /// primitive's tests rather than as silent drift at either sugar-
12578 /// surface arm.
12579 #[test]
12580 fn has_multiple_missing_condition_kind_triad_delegates_to_slice_has_multiple_missing_kinds() {
12581 // Empty ephemeral spec — every arm returns true (all N
12582 // missing, ≥ 2) on any N ≥ 2 closed set.
12583 assert!(
12584 ConditionKind::ALL.len() >= 2,
12585 "test assumes ConditionKind::ALL has ≥ 2 variants",
12586 );
12587 let spec = empty_ephemeral();
12588 assert!(
12589 spec.has_multiple_missing_precondition_kind(),
12590 "empty ephemeral must return true on has_multiple_missing_precondition_kind",
12591 );
12592 assert!(
12593 spec.has_multiple_missing_postcondition_kind(),
12594 "empty ephemeral must return true on has_multiple_missing_postcondition_kind",
12595 );
12596 assert!(
12597 spec.has_multiple_missing_condition_kind(),
12598 "empty ephemeral must return true on has_multiple_missing_condition_kind",
12599 );
12600 assert_eq!(
12601 spec.has_multiple_missing_condition_kind(),
12602 spec.missing_condition_kind_count() >= 2,
12603 "empty has_multiple_missing_condition_kind must equal (missing_condition_kind_count() >= 2)",
12604 );
12605
12606 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
12607 // sets. Every per-slice arm returns true; the union returns
12608 // true iff ≥ 2 ALL variants are uncovered.
12609 if ConditionKind::ALL.len() >= 3 {
12610 for pre_kind in ConditionKind::ALL {
12611 for post_kind in ConditionKind::ALL {
12612 let mut spec = empty_ephemeral();
12613 spec.preconditions.push(cond(pre_kind));
12614 spec.postconditions.push(cond(post_kind));
12615 assert_eq!(
12616 spec.has_multiple_missing_precondition_kind(),
12617 spec.preconditions.has_multiple_missing_kinds(),
12618 "EphemeralSpec::has_multiple_missing_precondition_kind must delegate verbatim to \
12619 preconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
12620 );
12621 assert_eq!(
12622 spec.has_multiple_missing_postcondition_kind(),
12623 spec.postconditions.has_multiple_missing_kinds(),
12624 "EphemeralSpec::has_multiple_missing_postcondition_kind must delegate verbatim to \
12625 postconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
12626 );
12627 let uncovered = ConditionKind::ALL
12628 .into_iter()
12629 .filter(|k| *k != pre_kind && *k != post_kind)
12630 .count();
12631 let expected_union = uncovered >= 2;
12632 assert_eq!(
12633 spec.has_multiple_missing_condition_kind(),
12634 expected_union,
12635 "EphemeralSpec::has_multiple_missing_condition_kind must equal \
12636 (uncovered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
12637 );
12638
12639 // Two-surface parity: lowered ProcessSpec's
12640 // Boundary must agree bit-for-bit with the
12641 // ephemeral sugar triad on every arm.
12642 let lowered: ProcessSpec = spec.clone().into();
12643 assert_eq!(
12644 spec.has_multiple_missing_precondition_kind(),
12645 lowered.boundary.has_multiple_missing_precondition_kind(),
12646 "two-surface has_multiple_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12647 );
12648 assert_eq!(
12649 spec.has_multiple_missing_postcondition_kind(),
12650 lowered.boundary.has_multiple_missing_postcondition_kind(),
12651 "two-surface has_multiple_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12652 );
12653 assert_eq!(
12654 spec.has_multiple_missing_condition_kind(),
12655 lowered.boundary.has_multiple_missing_condition_kind(),
12656 "two-surface has_multiple_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12657 );
12658 }
12659 }
12660 }
12661
12662 // Near-saturation-endpoint per side — each slice carries
12663 // every ConditionKind except one. Every per-slice arm returns
12664 // false (exactly 1 missing per slice, not ≥ 2). The union
12665 // has at most 1 missing (pre and post's omissions either
12666 // coincide → 1 missing, or differ → 0 missing), so the union
12667 // is always false on this arm.
12668 for pre_omit in ConditionKind::ALL {
12669 for post_omit in ConditionKind::ALL {
12670 let mut spec = empty_ephemeral();
12671 for k in ConditionKind::ALL {
12672 if k != pre_omit {
12673 spec.preconditions.push(cond(k));
12674 }
12675 if k != post_omit {
12676 spec.postconditions.push(cond(k));
12677 }
12678 }
12679 assert!(
12680 !spec.has_multiple_missing_precondition_kind(),
12681 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return false on has_multiple_missing_precondition_kind",
12682 );
12683 assert!(
12684 !spec.has_multiple_missing_postcondition_kind(),
12685 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return false on has_multiple_missing_postcondition_kind",
12686 );
12687 assert!(
12688 !spec.has_multiple_missing_condition_kind(),
12689 "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:?}",
12690 );
12691
12692 // Two-surface parity for near-saturation arm.
12693 let lowered: ProcessSpec = spec.clone().into();
12694 assert_eq!(
12695 spec.has_multiple_missing_precondition_kind(),
12696 lowered.boundary.has_multiple_missing_precondition_kind(),
12697 "two-surface has_multiple_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12698 );
12699 assert_eq!(
12700 spec.has_multiple_missing_postcondition_kind(),
12701 lowered.boundary.has_multiple_missing_postcondition_kind(),
12702 "two-surface has_multiple_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12703 );
12704 assert_eq!(
12705 spec.has_multiple_missing_condition_kind(),
12706 lowered.boundary.has_multiple_missing_condition_kind(),
12707 "two-surface has_multiple_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12708 );
12709 }
12710 }
12711
12712 // Saturated ephemeral — every arm returns false (0 missing,
12713 // not ≥ 2).
12714 let mut spec = empty_ephemeral();
12715 for k in ConditionKind::ALL {
12716 spec.preconditions.push(cond(k));
12717 spec.postconditions.push(cond(k));
12718 }
12719 assert!(
12720 !spec.has_multiple_missing_precondition_kind(),
12721 "saturated ephemeral must return false on has_multiple_missing_precondition_kind",
12722 );
12723 assert!(
12724 !spec.has_multiple_missing_postcondition_kind(),
12725 "saturated ephemeral must return false on has_multiple_missing_postcondition_kind",
12726 );
12727 assert!(
12728 !spec.has_multiple_missing_condition_kind(),
12729 "saturated ephemeral must return false on has_multiple_missing_condition_kind",
12730 );
12731 }
12732
12733 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1"
12734 /// triad) — the three `has_at_most_one_missing_*_condition_kind`
12735 /// methods on [`EphemeralSpec`] delegate to the slice-level
12736 /// substrate primitive
12737 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
12738 /// over the two `Vec<Condition>` slots (precondition +
12739 /// postcondition) and compose the union via
12740 /// `!self.has_multiple_missing_condition_kind()` — a definitional
12741 /// negation of the many-arm union primitive. Two-surface parity
12742 /// pin against
12743 /// [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
12744 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12745 /// level cardinality "≤ 1" callers compose against the SAME
12746 /// slice-level substrate primitive so a regression at the per-
12747 /// slice "≤ 1" negation fails at that primitive's tests rather
12748 /// than as silent drift at either sugar-surface arm.
12749 #[test]
12750 fn has_at_most_one_missing_condition_kind_triad_delegates_to_slice_has_at_most_one_missing_kind(
12751 ) {
12752 // Empty ephemeral spec — every arm returns false (all N
12753 // missing, not ≤ 1) on any N ≥ 2 closed set.
12754 assert!(
12755 ConditionKind::ALL.len() >= 2,
12756 "test assumes ConditionKind::ALL has ≥ 2 variants",
12757 );
12758 let spec = empty_ephemeral();
12759 assert!(
12760 !spec.has_at_most_one_missing_precondition_kind(),
12761 "empty ephemeral must return false on has_at_most_one_missing_precondition_kind",
12762 );
12763 assert!(
12764 !spec.has_at_most_one_missing_postcondition_kind(),
12765 "empty ephemeral must return false on has_at_most_one_missing_postcondition_kind",
12766 );
12767 assert!(
12768 !spec.has_at_most_one_missing_condition_kind(),
12769 "empty ephemeral must return false on has_at_most_one_missing_condition_kind",
12770 );
12771 assert_eq!(
12772 spec.has_at_most_one_missing_condition_kind(),
12773 spec.missing_condition_kind_count() <= 1,
12774 "empty has_at_most_one_missing_condition_kind must equal (missing_condition_kind_count() <= 1)",
12775 );
12776
12777 // Single-populated per side — sweep ALL × ALL on N ≥ 3
12778 // closed sets. Every per-slice arm returns false; the union
12779 // returns true iff ≤ 1 ALL variant is uncovered.
12780 if ConditionKind::ALL.len() >= 3 {
12781 for pre_kind in ConditionKind::ALL {
12782 for post_kind in ConditionKind::ALL {
12783 let mut spec = empty_ephemeral();
12784 spec.preconditions.push(cond(pre_kind));
12785 spec.postconditions.push(cond(post_kind));
12786 assert_eq!(
12787 spec.has_at_most_one_missing_precondition_kind(),
12788 spec.preconditions.has_at_most_one_missing_kind(),
12789 "EphemeralSpec::has_at_most_one_missing_precondition_kind must delegate verbatim to \
12790 preconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12791 );
12792 assert_eq!(
12793 spec.has_at_most_one_missing_postcondition_kind(),
12794 spec.postconditions.has_at_most_one_missing_kind(),
12795 "EphemeralSpec::has_at_most_one_missing_postcondition_kind must delegate verbatim to \
12796 postconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12797 );
12798 let uncovered = ConditionKind::ALL
12799 .into_iter()
12800 .filter(|k| *k != pre_kind && *k != post_kind)
12801 .count();
12802 let expected_union = uncovered <= 1;
12803 assert_eq!(
12804 spec.has_at_most_one_missing_condition_kind(),
12805 expected_union,
12806 "EphemeralSpec::has_at_most_one_missing_condition_kind must equal \
12807 (uncovered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
12808 );
12809
12810 // Two-surface parity: lowered ProcessSpec's
12811 // Boundary must agree bit-for-bit with the
12812 // ephemeral sugar triad on every arm.
12813 let lowered: ProcessSpec = spec.clone().into();
12814 assert_eq!(
12815 spec.has_at_most_one_missing_precondition_kind(),
12816 lowered.boundary.has_at_most_one_missing_precondition_kind(),
12817 "two-surface has_at_most_one_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12818 );
12819 assert_eq!(
12820 spec.has_at_most_one_missing_postcondition_kind(),
12821 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
12822 "two-surface has_at_most_one_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12823 );
12824 assert_eq!(
12825 spec.has_at_most_one_missing_condition_kind(),
12826 lowered.boundary.has_at_most_one_missing_condition_kind(),
12827 "two-surface has_at_most_one_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12828 );
12829 }
12830 }
12831 }
12832
12833 // Near-saturation-endpoint per side — each slice carries
12834 // every ConditionKind except one. Every per-slice arm returns
12835 // true (exactly 1 missing per slice, ≤ 1). The union has ≤ 1
12836 // missing (pre and post's omissions either coincide → 1
12837 // missing, or differ → 0 missing), so the union is always
12838 // true on this arm.
12839 for pre_omit in ConditionKind::ALL {
12840 for post_omit in ConditionKind::ALL {
12841 let mut spec = empty_ephemeral();
12842 for k in ConditionKind::ALL {
12843 if k != pre_omit {
12844 spec.preconditions.push(cond(k));
12845 }
12846 if k != post_omit {
12847 spec.postconditions.push(cond(k));
12848 }
12849 }
12850 assert!(
12851 spec.has_at_most_one_missing_precondition_kind(),
12852 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_at_most_one_missing_precondition_kind",
12853 );
12854 assert!(
12855 spec.has_at_most_one_missing_postcondition_kind(),
12856 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_at_most_one_missing_postcondition_kind",
12857 );
12858 assert!(
12859 spec.has_at_most_one_missing_condition_kind(),
12860 "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:?}",
12861 );
12862
12863 // Two-surface parity for near-saturation arm.
12864 let lowered: ProcessSpec = spec.clone().into();
12865 assert_eq!(
12866 spec.has_at_most_one_missing_precondition_kind(),
12867 lowered.boundary.has_at_most_one_missing_precondition_kind(),
12868 "two-surface has_at_most_one_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12869 );
12870 assert_eq!(
12871 spec.has_at_most_one_missing_postcondition_kind(),
12872 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
12873 "two-surface has_at_most_one_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12874 );
12875 assert_eq!(
12876 spec.has_at_most_one_missing_condition_kind(),
12877 lowered.boundary.has_at_most_one_missing_condition_kind(),
12878 "two-surface has_at_most_one_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12879 );
12880 }
12881 }
12882
12883 // Saturated ephemeral — every arm returns true (0 missing,
12884 // ≤ 1).
12885 let mut spec = empty_ephemeral();
12886 for k in ConditionKind::ALL {
12887 spec.preconditions.push(cond(k));
12888 spec.postconditions.push(cond(k));
12889 }
12890 assert!(
12891 spec.has_at_most_one_missing_precondition_kind(),
12892 "saturated ephemeral must return true on has_at_most_one_missing_precondition_kind",
12893 );
12894 assert!(
12895 spec.has_at_most_one_missing_postcondition_kind(),
12896 "saturated ephemeral must return true on has_at_most_one_missing_postcondition_kind",
12897 );
12898 assert!(
12899 spec.has_at_most_one_missing_condition_kind(),
12900 "saturated ephemeral must return true on has_at_most_one_missing_condition_kind",
12901 );
12902 }
12903
12904 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind-complement
12905 /// triad) — the three `lacks_*_condition_kind` methods on
12906 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
12907 /// [`ConditionSliceExt::lacks_kind`] over the two `Vec<Condition>`
12908 /// slots (precondition + postcondition) and compose the union via
12909 /// `!self.has_condition_kind(kind)`. Two-surface parity pin against
12910 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
12911 /// point-domain [`ProcessSpec`] surface — the two struct-level
12912 /// per-kind-complement callers compose against the SAME slice-level
12913 /// substrate primitive so a regression at the per-slice negation
12914 /// fails at that primitive's tests rather than as silent drift at
12915 /// either sugar-surface arm. Also pins the composition laws
12916 /// `lacks_*_condition_kind(k) == !has_*_condition_kind(k)` at each
12917 /// arm AND `lacks_condition_kind(k) == lacks_precondition_kind(k) &&
12918 /// lacks_postcondition_kind(k)` (the union AND-composition dual of
12919 /// `has`'s OR-composition).
12920 #[test]
12921 fn lacks_condition_kind_triad_delegates_to_slice_lacks_kind() {
12922 // Empty ephemeral spec — every arm returns true on every kind.
12923 let spec = empty_ephemeral();
12924 for kind in ConditionKind::ALL {
12925 assert!(
12926 spec.lacks_precondition_kind(kind),
12927 "empty ephemeral must return true on lacks_precondition_kind for {kind:?}",
12928 );
12929 assert!(
12930 spec.lacks_postcondition_kind(kind),
12931 "empty ephemeral must return true on lacks_postcondition_kind for {kind:?}",
12932 );
12933 assert!(
12934 spec.lacks_condition_kind(kind),
12935 "empty ephemeral must return true on lacks_condition_kind for {kind:?}",
12936 );
12937 assert_eq!(
12938 spec.lacks_condition_kind(kind),
12939 !spec.has_condition_kind(kind),
12940 "empty lacks_condition_kind must equal !has_condition_kind for {kind:?}",
12941 );
12942 }
12943
12944 // Single-populated per side — sweep ALL × ALL, then probe every
12945 // ConditionKind on the (pre, post, union) triad + two-surface
12946 // parity against the lowered ProcessSpec's Boundary.
12947 for pre_kind in ConditionKind::ALL {
12948 for post_kind in ConditionKind::ALL {
12949 let mut spec = empty_ephemeral();
12950 spec.preconditions.push(cond(pre_kind));
12951 spec.postconditions.push(cond(post_kind));
12952 let lowered: ProcessSpec = spec.clone().into();
12953 for probe in ConditionKind::ALL {
12954 assert_eq!(
12955 spec.lacks_precondition_kind(probe),
12956 spec.preconditions.lacks_kind(probe),
12957 "EphemeralSpec::lacks_precondition_kind must delegate verbatim to preconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12958 );
12959 assert_eq!(
12960 spec.lacks_postcondition_kind(probe),
12961 spec.postconditions.lacks_kind(probe),
12962 "EphemeralSpec::lacks_postcondition_kind must delegate verbatim to postconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12963 );
12964 let expected_union = pre_kind != probe && post_kind != probe;
12965 assert_eq!(
12966 spec.lacks_condition_kind(probe),
12967 expected_union,
12968 "EphemeralSpec::lacks_condition_kind must equal all-ALL-absent-in-both-slices for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12969 );
12970 assert_eq!(
12971 spec.lacks_condition_kind(probe),
12972 !spec.has_condition_kind(probe),
12973 "EphemeralSpec::lacks_condition_kind must equal !has_condition_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12974 );
12975 assert_eq!(
12976 spec.lacks_condition_kind(probe),
12977 spec.lacks_precondition_kind(probe)
12978 && spec.lacks_postcondition_kind(probe),
12979 "EphemeralSpec::lacks_condition_kind must equal AND-of-half-slice-arms for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12980 );
12981
12982 // Two-surface parity: lowered ProcessSpec's Boundary
12983 // must agree bit-for-bit with the ephemeral sugar
12984 // triad on every arm.
12985 assert_eq!(
12986 spec.lacks_precondition_kind(probe),
12987 lowered.boundary.lacks_precondition_kind(probe),
12988 "two-surface lacks_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12989 );
12990 assert_eq!(
12991 spec.lacks_postcondition_kind(probe),
12992 lowered.boundary.lacks_postcondition_kind(probe),
12993 "two-surface lacks_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12994 );
12995 assert_eq!(
12996 spec.lacks_condition_kind(probe),
12997 lowered.boundary.lacks_condition_kind(probe),
12998 "two-surface lacks_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12999 );
13000 }
13001 }
13002 }
13003
13004 // Saturated ephemeral — both slices carry every ConditionKind,
13005 // every arm returns false on every kind.
13006 let mut spec = empty_ephemeral();
13007 for k in ConditionKind::ALL {
13008 spec.preconditions.push(cond(k));
13009 spec.postconditions.push(cond(k));
13010 }
13011 for kind in ConditionKind::ALL {
13012 assert!(
13013 !spec.lacks_precondition_kind(kind),
13014 "saturated ephemeral must return false on lacks_precondition_kind for {kind:?}",
13015 );
13016 assert!(
13017 !spec.lacks_postcondition_kind(kind),
13018 "saturated ephemeral must return false on lacks_postcondition_kind for {kind:?}",
13019 );
13020 assert!(
13021 !spec.lacks_condition_kind(kind),
13022 "saturated ephemeral must return false on lacks_condition_kind for {kind:?}",
13023 );
13024 }
13025 }
13026
13027 /// TRIAD delegation pin — the (precondition, postcondition,
13028 /// condition-union) kind-scoped strict-refinement triad on
13029 /// [`EphemeralSpec`] agrees byte-for-byte with the slice-level
13030 /// substrate primitive
13031 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] on every
13032 /// authored arrangement AND with the lowered
13033 /// [`ProcessSpec::boundary`]'s kind-scoped strict-refinement
13034 /// triad through the `From<EphemeralSpec>` bridge — the two-
13035 /// surface parity contract at the well-formed-diagonal arm.
13036 ///
13037 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
13038 /// single-populated-per-side arrangements (the well-formed
13039 /// diagonal), probing every [`ConditionKind`] at the union arm
13040 /// against the DERIVED oracle `pre_kind == probe && post_kind ==
13041 /// probe`. Also sweeps the single-side-only-populated arms (the
13042 /// union carries a singleton distinct set — pins the union arm
13043 /// reaches the union primitive, not the (pre AND post) AND-
13044 /// composition). A regression at the union arm's fused walk or
13045 /// at the `From<EphemeralSpec>` bridge surfaces HERE.
13046 #[test]
13047 fn has_only_condition_kind_triad_delegates_to_slice_has_only_kind() {
13048 // Empty ephemeral spec — every arm returns false on every
13049 // kind (no kind is populated, so no kind is "only").
13050 let spec = empty_ephemeral();
13051 for kind in ConditionKind::ALL {
13052 assert!(
13053 !spec.has_only_precondition_kind(kind),
13054 "empty ephemeral must return false on has_only_precondition_kind for {kind:?}",
13055 );
13056 assert!(
13057 !spec.has_only_postcondition_kind(kind),
13058 "empty ephemeral must return false on has_only_postcondition_kind for {kind:?}",
13059 );
13060 assert!(
13061 !spec.has_only_condition_kind(kind),
13062 "empty ephemeral must return false on has_only_condition_kind for {kind:?}",
13063 );
13064 }
13065
13066 // Single-populated per side — sweep ALL × ALL, then probe
13067 // every ConditionKind on the (pre, post, union) triad + two-
13068 // surface parity against the lowered ProcessSpec's Boundary.
13069 for pre_kind in ConditionKind::ALL {
13070 for post_kind in ConditionKind::ALL {
13071 let mut spec = empty_ephemeral();
13072 spec.preconditions.push(cond(pre_kind));
13073 spec.postconditions.push(cond(post_kind));
13074 let lowered: ProcessSpec = spec.clone().into();
13075 for probe in ConditionKind::ALL {
13076 assert_eq!(
13077 spec.has_only_precondition_kind(probe),
13078 spec.preconditions.has_only_kind(probe),
13079 "EphemeralSpec::has_only_precondition_kind must delegate verbatim to preconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13080 );
13081 assert_eq!(
13082 spec.has_only_postcondition_kind(probe),
13083 spec.postconditions.has_only_kind(probe),
13084 "EphemeralSpec::has_only_postcondition_kind must delegate verbatim to postconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13085 );
13086 let expected_union = pre_kind == probe && post_kind == probe;
13087 assert_eq!(
13088 spec.has_only_condition_kind(probe),
13089 expected_union,
13090 "EphemeralSpec::has_only_condition_kind must equal (pre_kind == probe && post_kind == probe) for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13091 );
13092
13093 // Two-surface parity: lowered ProcessSpec's
13094 // Boundary must agree bit-for-bit with the
13095 // ephemeral sugar triad on every arm.
13096 assert_eq!(
13097 spec.has_only_precondition_kind(probe),
13098 lowered.boundary.has_only_precondition_kind(probe),
13099 "two-surface has_only_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13100 );
13101 assert_eq!(
13102 spec.has_only_postcondition_kind(probe),
13103 lowered.boundary.has_only_postcondition_kind(probe),
13104 "two-surface has_only_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13105 );
13106 assert_eq!(
13107 spec.has_only_condition_kind(probe),
13108 lowered.boundary.has_only_condition_kind(probe),
13109 "two-surface has_only_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
13110 );
13111 }
13112 }
13113 }
13114
13115 // Single-side-only populated — the union carries a singleton
13116 // distinct set; the union arm returns `true` for the populated
13117 // kind and `false` for every other kind, DESPITE the empty
13118 // side's `has_only_kind` returning `false`. Pins that the
13119 // union arm reaches the union primitive
13120 // [`Self::has_condition_kind`], not the (pre AND post) AND-
13121 // composition of the per-slice arms. Also pins two-surface
13122 // parity on the single-side arrangement.
13123 for populated in ConditionKind::ALL {
13124 let mut spec = empty_ephemeral();
13125 spec.preconditions.push(cond(populated));
13126 let lowered: ProcessSpec = spec.clone().into();
13127 for probe in ConditionKind::ALL {
13128 let expected = probe == populated;
13129 assert_eq!(
13130 spec.has_only_condition_kind(probe),
13131 expected,
13132 "pre-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
13133 );
13134 assert_eq!(
13135 spec.has_only_condition_kind(probe),
13136 lowered.boundary.has_only_condition_kind(probe),
13137 "two-surface pre-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
13138 );
13139 }
13140
13141 let mut spec = empty_ephemeral();
13142 spec.postconditions.push(cond(populated));
13143 let lowered: ProcessSpec = spec.clone().into();
13144 for probe in ConditionKind::ALL {
13145 let expected = probe == populated;
13146 assert_eq!(
13147 spec.has_only_condition_kind(probe),
13148 expected,
13149 "post-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
13150 );
13151 assert_eq!(
13152 spec.has_only_condition_kind(probe),
13153 lowered.boundary.has_only_condition_kind(probe),
13154 "two-surface post-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
13155 );
13156 }
13157 }
13158
13159 // Saturated ephemeral — both slices carry every ConditionKind,
13160 // every arm returns false on every kind (N distinct kinds, no
13161 // kind is "only").
13162 let mut spec = empty_ephemeral();
13163 for k in ConditionKind::ALL {
13164 spec.preconditions.push(cond(k));
13165 spec.postconditions.push(cond(k));
13166 }
13167 for kind in ConditionKind::ALL {
13168 assert!(
13169 !spec.has_only_precondition_kind(kind),
13170 "saturated ephemeral must return false on has_only_precondition_kind for {kind:?}",
13171 );
13172 assert!(
13173 !spec.has_only_postcondition_kind(kind),
13174 "saturated ephemeral must return false on has_only_postcondition_kind for {kind:?}",
13175 );
13176 assert!(
13177 !spec.has_only_condition_kind(kind),
13178 "saturated ephemeral must return false on has_only_condition_kind for {kind:?}",
13179 );
13180 }
13181 }
13182
13183 /// TRIAD delegation pin — the (precondition, postcondition,
13184 /// condition-union) kind-scoped strict-refinement-on-missing triad
13185 /// on [`EphemeralSpec`] agrees byte-for-byte with the slice-level
13186 /// substrate primitive
13187 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] on every
13188 /// authored arrangement, AND agrees bit-for-bit with the lowered
13189 /// [`ProcessSpec::boundary`]'s triad via the [`From`] bridge.
13190 ///
13191 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
13192 /// single-populated-per-side arrangements + near-saturation-per-
13193 /// side arrangements + single-side-only near-saturation
13194 /// arrangements. The union arm is probed against the DERIVED
13195 /// oracle `spec.missing_condition_kinds() == vec![probe]`, and
13196 /// the per-slice arms delegate to the slice substrate primitive
13197 /// verbatim. Two-surface parity ensures a regression at the
13198 /// `From<EphemeralSpec>` bridge (a re-ordered condition Vec, a
13199 /// dropped ClosedLoopAuth default) surfaces HERE at the union arm.
13200 #[test]
13201 fn lacks_only_condition_kind_triad_delegates_to_slice_lacks_only_kind() {
13202 // Empty ephemeral spec — every kind is missing on N ≥ 2, so
13203 // no kind is "only" missing on any arm.
13204 let spec = empty_ephemeral();
13205 let lowered: ProcessSpec = spec.clone().into();
13206 for kind in ConditionKind::ALL {
13207 assert_eq!(
13208 spec.lacks_only_precondition_kind(kind),
13209 spec.preconditions.lacks_only_kind(kind),
13210 "empty ephemeral lacks_only_precondition_kind must delegate to preconditions.lacks_only_kind for {kind:?}",
13211 );
13212 assert_eq!(
13213 spec.lacks_only_postcondition_kind(kind),
13214 spec.postconditions.lacks_only_kind(kind),
13215 "empty ephemeral lacks_only_postcondition_kind must delegate to postconditions.lacks_only_kind for {kind:?}",
13216 );
13217 assert_eq!(
13218 spec.lacks_only_condition_kind(kind),
13219 lowered.boundary.lacks_only_condition_kind(kind),
13220 "two-surface empty lacks_only_condition_kind parity drift for {kind:?}",
13221 );
13222 }
13223
13224 // Near-saturation per side — build an ephemeral spec whose both
13225 // sides carry every kind except one; sweep every omitted kind
13226 // and probe every ConditionKind on the (pre, post, union) triad.
13227 for omitted in ConditionKind::ALL {
13228 let mut spec = empty_ephemeral();
13229 for k in ConditionKind::ALL {
13230 if k != omitted {
13231 spec.preconditions.push(cond(k));
13232 spec.postconditions.push(cond(k));
13233 }
13234 }
13235 let lowered: ProcessSpec = spec.clone().into();
13236 for probe in ConditionKind::ALL {
13237 let expected = probe == omitted;
13238 assert_eq!(
13239 spec.lacks_only_precondition_kind(probe),
13240 expected,
13241 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_precondition_kind({probe:?})",
13242 );
13243 assert_eq!(
13244 spec.lacks_only_postcondition_kind(probe),
13245 expected,
13246 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_postcondition_kind({probe:?})",
13247 );
13248 assert_eq!(
13249 spec.lacks_only_condition_kind(probe),
13250 expected,
13251 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
13252 );
13253 assert_eq!(
13254 spec.lacks_only_condition_kind(probe),
13255 spec.missing_condition_kinds() == vec![probe],
13256 "near-saturation ephemeral omitted={omitted:?} must agree with missing_condition_kinds() == vec![{probe:?}]",
13257 );
13258
13259 // Two-surface parity via lowered ProcessSpec.
13260 assert_eq!(
13261 spec.lacks_only_precondition_kind(probe),
13262 lowered.boundary.lacks_only_precondition_kind(probe),
13263 "two-surface lacks_only_precondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13264 );
13265 assert_eq!(
13266 spec.lacks_only_postcondition_kind(probe),
13267 lowered.boundary.lacks_only_postcondition_kind(probe),
13268 "two-surface lacks_only_postcondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13269 );
13270 assert_eq!(
13271 spec.lacks_only_condition_kind(probe),
13272 lowered.boundary.lacks_only_condition_kind(probe),
13273 "two-surface lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13274 );
13275 }
13276 }
13277
13278 // Single-side-only near-saturation — the populated side covers
13279 // every kind except one; the OTHER side is empty. The union
13280 // still has missing set `{omitted}` (the populated side's hole
13281 // wins), so the union arm returns `true` for `omitted` and
13282 // `false` for every other kind, DESPITE the empty side's
13283 // `lacks_only_kind` returning `false` on every kind for N ≥ 2.
13284 // Pins that the union arm reaches the union primitive, not the
13285 // (pre AND post) AND-composition.
13286 for omitted in ConditionKind::ALL {
13287 let mut spec = empty_ephemeral();
13288 for k in ConditionKind::ALL {
13289 if k != omitted {
13290 spec.preconditions.push(cond(k));
13291 }
13292 }
13293 let lowered: ProcessSpec = spec.clone().into();
13294 for probe in ConditionKind::ALL {
13295 let expected = probe == omitted;
13296 assert_eq!(
13297 spec.lacks_only_condition_kind(probe),
13298 expected,
13299 "pre-only near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
13300 );
13301 assert_eq!(
13302 spec.lacks_only_condition_kind(probe),
13303 lowered.boundary.lacks_only_condition_kind(probe),
13304 "two-surface pre-only near-saturation lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
13305 );
13306 }
13307 }
13308
13309 // Saturated ephemeral — every kind populated, no kind missing,
13310 // every arm returns false on every kind.
13311 let mut spec = empty_ephemeral();
13312 for k in ConditionKind::ALL {
13313 spec.preconditions.push(cond(k));
13314 spec.postconditions.push(cond(k));
13315 }
13316 for kind in ConditionKind::ALL {
13317 assert!(
13318 !spec.lacks_only_precondition_kind(kind),
13319 "saturated ephemeral must return false on lacks_only_precondition_kind for {kind:?}",
13320 );
13321 assert!(
13322 !spec.lacks_only_postcondition_kind(kind),
13323 "saturated ephemeral must return false on lacks_only_postcondition_kind for {kind:?}",
13324 );
13325 assert!(
13326 !spec.lacks_only_condition_kind(kind),
13327 "saturated ephemeral must return false on lacks_only_condition_kind for {kind:?}",
13328 );
13329 }
13330 }
13331}