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 /// Scalar cardinality of the [`ConditionKind`] set appearing at
643 /// least once in `preconditions ∪ postconditions` — the peer of
644 /// [`crate::boundary::Boundary::distinct_condition_kind_count`] on
645 /// the [`EphemeralSpec`] sugar surface.
646 ///
647 /// # Composed body — byte-identical to
648 /// [`crate::boundary::Boundary::distinct_condition_kind_count`]
649 ///
650 /// `ConditionKind::ALL.iter().filter(|k|
651 /// self.has_condition_kind(**k)).count()` — the scalar cardinality
652 /// projection of [`Self::distinct_condition_kinds`] onto its
653 /// `.len()`, without materializing the intermediate
654 /// `Vec<ConditionKind>`. Byte-identical to the peer method on the
655 /// point-domain [`crate::boundary::Boundary`] surface — both
656 /// compose against the SAME slice-level substrate primitive
657 /// [`crate::boundary::ConditionSliceExt::distinct_kind_count`] via
658 /// the two-slice union composed through [`Self::has_condition_kind`]
659 /// so a regression at the per-slice closed-set walk fails at that
660 /// primitive's tests rather than as silent drift at either
661 /// struct-level scalar-cardinality caller.
662 ///
663 /// # Sibling to [`Self::distinct_condition_kinds`]
664 ///
665 /// Scalar projection of the closed-set-inversion widened primitive
666 /// on the ephemeral-union surface — where `distinct_condition_kinds`
667 /// returns the SET, `distinct_condition_kind_count` collapses it to
668 /// its cardinality. The two-surface parity contract now covers SIX
669 /// refinements (bool / `&Condition` / `impl Iterator` / `usize` /
670 /// `Vec<ConditionKind>` closed-set-inversion / `usize` scalar
671 /// cardinality of the closed-set-inversion) on the condition axis,
672 /// byte-for-byte peer of the point-domain triad on
673 /// [`crate::boundary::Boundary`].
674 ///
675 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
676 /// proofs — the scalar cardinality composes the SAME closed-set
677 /// walk on both this ephemeral surface and the point-domain
678 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
679 /// (generation over composition — a future [`ConditionKind`] variant
680 /// added to `ALL` reaches both surfaces' distinct-kind-count triads
681 /// mechanically through the SAME closed-set walk).
682 #[must_use]
683 pub fn distinct_condition_kind_count(&self) -> usize {
684 ConditionKind::ALL
685 .iter()
686 .filter(|k| self.has_condition_kind(**k))
687 .count()
688 }
689
690 /// Scalar cardinality of the [`ConditionKind`] set appearing at
691 /// least once in [`Self::preconditions`] — the precondition-side
692 /// arm of the (precondition, postcondition, condition-union)
693 /// distinct-kind-count triad on [`EphemeralSpec`]. Thin typed
694 /// delegate to
695 /// [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
696 /// over [`Self::preconditions`].
697 ///
698 /// Peer of
699 /// [`crate::boundary::Boundary::distinct_precondition_kind_count`]
700 /// on the point-domain surface — both peers compose against the
701 /// SAME slice-level substrate primitive so a regression at the
702 /// per-slice closed-set walk fails at that primitive's tests rather
703 /// than as silent drift at either struct-level arm.
704 #[must_use]
705 pub fn distinct_precondition_kind_count(&self) -> usize {
706 self.preconditions.distinct_kind_count()
707 }
708
709 /// Scalar cardinality of the [`ConditionKind`] set appearing at
710 /// least once in [`Self::postconditions`] — the postcondition-side
711 /// arm of the (precondition, postcondition, condition-union)
712 /// distinct-kind-count triad on [`EphemeralSpec`]. Thin typed
713 /// delegate to
714 /// [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
715 /// over [`Self::postconditions`].
716 ///
717 /// Peer of
718 /// [`crate::boundary::Boundary::distinct_postcondition_kind_count`]
719 /// on the point-domain surface. See
720 /// [`Self::distinct_precondition_kind_count`] for the full rationale
721 /// — the two methods share ONE lift motivation, ONE fail-before-
722 /// pass-after composition-law pin, and ONE two-surface parity
723 /// contract with the point-domain
724 /// [`crate::boundary::Boundary`] distinct-kind-count peer methods.
725 #[must_use]
726 pub fn distinct_postcondition_kind_count(&self) -> usize {
727 self.postconditions.distinct_kind_count()
728 }
729
730 /// The set of [`ConditionKind`] variants that do NOT appear in
731 /// `preconditions ∪ postconditions`, projected in
732 /// [`ConditionKind::ALL`] order — the closed-set-inversion
733 /// COMPLEMENT of [`Self::distinct_condition_kinds`] on the
734 /// (precondition, postcondition, condition-union) missing-set triad.
735 /// Byte-identical peer of
736 /// [`crate::boundary::Boundary::missing_condition_kinds`] on the
737 /// ephemeral sugar surface.
738 ///
739 /// # Composed body — byte-identical to
740 /// [`crate::boundary::Boundary::missing_condition_kinds`]
741 ///
742 /// `ConditionKind::ALL.into_iter().filter(|k|
743 /// !self.has_condition_kind(*k)).collect()` — a thin projection
744 /// over the closed set composed against the two-slice union
745 /// primitive [`Self::has_condition_kind`] under a negated
746 /// predicate. Equivalent to the SET-INTERSECTION of
747 /// [`Self::missing_precondition_kinds`] and
748 /// [`Self::missing_postcondition_kinds`] projected in canonical
749 /// [`ConditionKind::ALL`] order (the union-composition law pinned
750 /// by [`crate::assert_surface_union_composition_laws`]).
751 ///
752 /// # Peer on the point surface — [`crate::boundary::Boundary::missing_condition_kinds`]
753 ///
754 /// Same signature `(&Self) -> Vec<ConditionKind>`, same closed-set-
755 /// complement body, on the point-domain [`crate::boundary::Boundary`]
756 /// nested-slot carrier. Both methods compose against the SAME
757 /// slice-level substrate primitive
758 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] via the
759 /// two-slice union composed through [`Self::has_condition_kind`] —
760 /// a regression at the per-slice walk fails at that primitive's
761 /// tests rather than as silent drift at either struct-level
762 /// complement caller.
763 ///
764 /// # Sibling to [`Self::distinct_condition_kinds`]
765 ///
766 /// SIXTH refinement on the ephemeral-surface presence-probe algebra,
767 /// on the SAME closed-set-inversion axis as `distinct_condition_kinds`
768 /// but under a NEGATED point-probe. The two-surface parity contract
769 /// now covers SEVEN refinements (bool / `&Condition` /
770 /// `impl Iterator` / `usize` / `Vec<ConditionKind>` closed-set-
771 /// inversion / `usize` scalar cardinality of the closed-set-
772 /// inversion / `Vec<ConditionKind>` closed-set-complement) on the
773 /// condition axis, byte-for-byte peer of the point-domain triad on
774 /// [`crate::boundary::Boundary`].
775 ///
776 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
777 /// preserves proofs — the closed-set complement composes the SAME
778 /// closed-set walk on both this ephemeral surface and the point-
779 /// domain [`crate::boundary::Boundary`] surface).
780 /// THEORY.md §VI.1 (generation over composition — a future
781 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
782 /// missing-set triads mechanically through the SAME closed-set walk).
783 #[must_use]
784 pub fn missing_condition_kinds(&self) -> Vec<ConditionKind> {
785 ConditionKind::ALL
786 .into_iter()
787 .filter(|k| !self.has_condition_kind(*k))
788 .collect()
789 }
790
791 /// The set of [`ConditionKind`] variants that do NOT appear in
792 /// [`Self::preconditions`], projected in [`ConditionKind::ALL`]
793 /// order — the precondition-side arm of the (precondition,
794 /// postcondition, condition-union) missing-set triad on
795 /// [`EphemeralSpec`]. Thin typed delegate to
796 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over
797 /// [`Self::preconditions`].
798 ///
799 /// Peer of [`crate::boundary::Boundary::missing_precondition_kinds`]
800 /// on the point-domain surface — both peers compose against the
801 /// SAME slice-level substrate primitive so a regression at the
802 /// per-slice closed-set walk fails at that primitive's tests
803 /// rather than as silent drift at either struct-level arm.
804 #[must_use]
805 pub fn missing_precondition_kinds(&self) -> Vec<ConditionKind> {
806 self.preconditions.missing_kinds()
807 }
808
809 /// The set of [`ConditionKind`] variants that do NOT appear in
810 /// [`Self::postconditions`], projected in [`ConditionKind::ALL`]
811 /// order — the postcondition-side arm of the (precondition,
812 /// postcondition, condition-union) missing-set triad on
813 /// [`EphemeralSpec`]. Thin typed delegate to
814 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over
815 /// [`Self::postconditions`].
816 ///
817 /// Peer of [`crate::boundary::Boundary::missing_postcondition_kinds`]
818 /// on the point-domain surface. See
819 /// [`Self::missing_precondition_kinds`] for the full rationale —
820 /// the two methods share ONE lift motivation, ONE fail-before-
821 /// pass-after composition-law pin, and ONE two-surface parity
822 /// contract with the point-domain
823 /// [`crate::boundary::Boundary`] missing-set peer methods.
824 #[must_use]
825 pub fn missing_postcondition_kinds(&self) -> Vec<ConditionKind> {
826 self.postconditions.missing_kinds()
827 }
828
829 /// Scalar cardinality of the [`ConditionKind`] set NOT appearing in
830 /// `preconditions ∪ postconditions` — the peer of
831 /// [`crate::boundary::Boundary::missing_condition_kind_count`] on
832 /// the [`EphemeralSpec`] sugar surface.
833 ///
834 /// # Composed body — byte-identical to
835 /// [`crate::boundary::Boundary::missing_condition_kind_count`]
836 ///
837 /// `ConditionKind::ALL.iter().filter(|k|
838 /// !self.has_condition_kind(**k)).count()` — the scalar cardinality
839 /// projection of [`Self::missing_condition_kinds`] onto its
840 /// `.len()`, without materializing the intermediate
841 /// `Vec<ConditionKind>`. Byte-identical to the peer method on the
842 /// point-domain [`crate::boundary::Boundary`] surface — both
843 /// compose against the SAME slice-level substrate primitive
844 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] via
845 /// the two-slice union composed through [`Self::has_condition_kind`]
846 /// so a regression at the per-slice negated closed-set walk fails
847 /// at that primitive's tests rather than as silent drift at either
848 /// struct-level scalar-cardinality caller.
849 ///
850 /// # Sibling to [`Self::missing_condition_kinds`]
851 ///
852 /// Scalar projection of the closed-set-complement widened primitive
853 /// on the ephemeral-union surface — where `missing_condition_kinds`
854 /// returns the SET, `missing_condition_kind_count` collapses it to
855 /// its cardinality. The two-surface parity contract now covers
856 /// EIGHT refinements (bool / `&Condition` / `impl Iterator` /
857 /// `usize` / `Vec<ConditionKind>` closed-set-inversion / `usize`
858 /// scalar cardinality of the closed-set-inversion /
859 /// `Vec<ConditionKind>` closed-set-complement / `usize` scalar
860 /// cardinality of the closed-set-complement) on the condition axis,
861 /// byte-for-byte peer of the point-domain triad on
862 /// [`crate::boundary::Boundary`].
863 ///
864 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
865 /// proofs — the scalar cardinality composes the SAME closed-set
866 /// walk under negation on both this ephemeral surface and the
867 /// point-domain [`crate::boundary::Boundary`] surface).
868 /// THEORY.md §VI.1 (generation over composition — a future
869 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
870 /// missing-kind-count triads mechanically through the SAME
871 /// closed-set walk).
872 #[must_use]
873 pub fn missing_condition_kind_count(&self) -> usize {
874 ConditionKind::ALL
875 .iter()
876 .filter(|k| !self.has_condition_kind(**k))
877 .count()
878 }
879
880 /// Scalar cardinality of the [`ConditionKind`] set NOT appearing in
881 /// [`Self::preconditions`] — the precondition-side arm of the
882 /// (precondition, postcondition, condition-union) missing-kind-count
883 /// triad on [`EphemeralSpec`]. Thin typed delegate to
884 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
885 /// [`Self::preconditions`].
886 ///
887 /// Peer of
888 /// [`crate::boundary::Boundary::missing_precondition_kind_count`]
889 /// on the point-domain surface — both peers compose against the
890 /// SAME slice-level substrate primitive so a regression at the
891 /// per-slice negated closed-set walk fails at that primitive's tests
892 /// rather than as silent drift at either struct-level arm.
893 #[must_use]
894 pub fn missing_precondition_kind_count(&self) -> usize {
895 self.preconditions.missing_kind_count()
896 }
897
898 /// Scalar cardinality of the [`ConditionKind`] set NOT appearing in
899 /// [`Self::postconditions`] — the postcondition-side arm of the
900 /// (precondition, postcondition, condition-union) missing-kind-count
901 /// triad on [`EphemeralSpec`]. Thin typed delegate to
902 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
903 /// [`Self::postconditions`].
904 ///
905 /// Peer of
906 /// [`crate::boundary::Boundary::missing_postcondition_kind_count`]
907 /// on the point-domain surface. See
908 /// [`Self::missing_precondition_kind_count`] for the full rationale
909 /// — the two methods share ONE lift motivation, ONE fail-before-
910 /// pass-after composition-law pin, and ONE two-surface parity
911 /// contract with the point-domain
912 /// [`crate::boundary::Boundary`] missing-kind-count peer methods.
913 #[must_use]
914 pub fn missing_postcondition_kind_count(&self) -> usize {
915 self.postconditions.missing_kind_count()
916 }
917
918 /// Earliest [`ConditionKind::ALL`] entry present in
919 /// `preconditions ∪ postconditions`, or `None` when neither side
920 /// populates any variant — the peer of
921 /// [`crate::boundary::Boundary::first_distinct_condition_kind`]
922 /// on the [`EphemeralSpec`] sugar surface.
923 ///
924 /// # Composed body — byte-identical to
925 /// [`crate::boundary::Boundary::first_distinct_condition_kind`]
926 ///
927 /// `ConditionKind::ALL.iter().copied().find(|k|
928 /// self.has_condition_kind(*k))` — the earliest-element scalar
929 /// projection of [`Self::distinct_condition_kinds`] onto its first
930 /// entry, without materializing the intermediate
931 /// `Vec<ConditionKind>`. Byte-identical to the peer method on the
932 /// point-domain [`crate::boundary::Boundary`] surface — both
933 /// compose against the SAME slice-level substrate primitive
934 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] via
935 /// the two-slice union composed through
936 /// [`Self::has_condition_kind`] so a regression at the per-slice
937 /// short-circuit walk fails at that primitive's tests rather than
938 /// as silent drift at either struct-level earliest-element caller.
939 ///
940 /// # Sibling to [`Self::distinct_condition_kinds`]
941 ///
942 /// Third scalar projection of the closed-set-inversion widened
943 /// primitive on the ephemeral-union surface. The two-surface
944 /// parity contract now covers NINE refinements on the condition
945 /// axis (bool / `&Condition` / `impl Iterator` / `usize` /
946 /// `Vec<ConditionKind>` closed-set-inversion / `usize` scalar
947 /// cardinality of the closed-set-inversion / `Vec<ConditionKind>`
948 /// closed-set-complement / `usize` scalar cardinality of the
949 /// closed-set-complement / `Option<ConditionKind>` earliest-element
950 /// scalar of the closed-set-inversion), byte-for-byte peer of the
951 /// point-domain triad on [`crate::boundary::Boundary`].
952 ///
953 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
954 /// preserves proofs — the earliest-element projection composes the
955 /// SAME closed-set walk on both this ephemeral surface and the
956 /// point-domain [`crate::boundary::Boundary`] surface under short-
957 /// circuit semantics). THEORY.md §VI.1 (generation over composition
958 /// — a future [`ConditionKind`] variant added to `ALL` reaches both
959 /// surfaces' first-distinct-kind triads mechanically through the
960 /// SAME closed-set walk).
961 #[must_use]
962 pub fn first_distinct_condition_kind(&self) -> Option<ConditionKind> {
963 ConditionKind::ALL
964 .iter()
965 .copied()
966 .find(|k| self.has_condition_kind(*k))
967 }
968
969 /// Earliest [`ConditionKind::ALL`] entry present in
970 /// [`Self::preconditions`], or `None` when preconditions carry no
971 /// matching kind — the precondition-side arm of the (precondition,
972 /// postcondition, condition-union) first-distinct-kind triad on
973 /// [`EphemeralSpec`]. Thin typed delegate to
974 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`]
975 /// over [`Self::preconditions`].
976 ///
977 /// Peer of
978 /// [`crate::boundary::Boundary::first_distinct_precondition_kind`]
979 /// on the point-domain surface — both peers compose against the
980 /// SAME slice-level substrate primitive so a regression at the
981 /// per-slice short-circuit walk fails at that primitive's tests
982 /// rather than as silent drift at either struct-level arm.
983 #[must_use]
984 pub fn first_distinct_precondition_kind(&self) -> Option<ConditionKind> {
985 self.preconditions.first_distinct_kind()
986 }
987
988 /// Earliest [`ConditionKind::ALL`] entry present in
989 /// [`Self::postconditions`], or `None` when postconditions carry
990 /// no matching kind — the postcondition-side arm of the
991 /// (precondition, postcondition, condition-union) first-distinct-
992 /// kind triad on [`EphemeralSpec`]. Thin typed delegate to
993 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`]
994 /// over [`Self::postconditions`].
995 ///
996 /// Peer of
997 /// [`crate::boundary::Boundary::first_distinct_postcondition_kind`]
998 /// on the point-domain surface. See
999 /// [`Self::first_distinct_precondition_kind`] for the full
1000 /// rationale — the two methods share ONE lift motivation, ONE
1001 /// fail-before-pass-after composition-law pin, and ONE two-surface
1002 /// parity contract with the point-domain
1003 /// [`crate::boundary::Boundary`] first-distinct-kind peer methods.
1004 #[must_use]
1005 pub fn first_distinct_postcondition_kind(&self) -> Option<ConditionKind> {
1006 self.postconditions.first_distinct_kind()
1007 }
1008
1009 /// Earliest [`ConditionKind::ALL`] entry ABSENT from
1010 /// `preconditions ∪ postconditions`, or `None` when the union
1011 /// carries every variant — the peer of
1012 /// [`crate::boundary::Boundary::first_missing_condition_kind`]
1013 /// on the [`EphemeralSpec`] sugar surface.
1014 ///
1015 /// # Composed body — byte-identical to
1016 /// [`crate::boundary::Boundary::first_missing_condition_kind`]
1017 ///
1018 /// `ConditionKind::ALL.iter().copied().find(|k|
1019 /// !self.has_condition_kind(*k))` — the earliest-element scalar
1020 /// projection of [`Self::missing_condition_kinds`] onto its first
1021 /// entry under a NEGATED predicate. Byte-identical to the peer
1022 /// method on the point-domain [`crate::boundary::Boundary`]
1023 /// surface — both compose against the SAME slice-level substrate
1024 /// primitive [`crate::boundary::ConditionSliceExt::first_missing_kind`]
1025 /// via the two-slice union composed through
1026 /// [`Self::has_condition_kind`] so a regression at the per-slice
1027 /// negated short-circuit walk fails at that primitive's tests
1028 /// rather than as silent drift at either struct-level earliest-
1029 /// element caller.
1030 ///
1031 /// # Sibling to [`Self::missing_condition_kinds`]
1032 ///
1033 /// Third scalar projection of the closed-set-complement widened
1034 /// primitive on the ephemeral-union surface. The two-surface
1035 /// parity contract now covers TEN refinements on the condition
1036 /// axis (the nine listed at [`Self::first_distinct_condition_kind`]
1037 /// plus `Option<ConditionKind>` earliest-element scalar of the
1038 /// closed-set-complement), byte-for-byte peer of the point-domain
1039 /// triad on [`crate::boundary::Boundary`].
1040 ///
1041 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1042 /// preserves proofs — the complement-earliest-element projection
1043 /// composes the SAME closed-set walk on both this ephemeral
1044 /// surface and the point-domain [`crate::boundary::Boundary`]
1045 /// surface under short-circuit semantics with a negated predicate).
1046 /// THEORY.md §VI.1 (generation over composition — a future
1047 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
1048 /// first-missing-kind triads mechanically through the SAME closed-
1049 /// set walk).
1050 #[must_use]
1051 pub fn first_missing_condition_kind(&self) -> Option<ConditionKind> {
1052 ConditionKind::ALL
1053 .iter()
1054 .copied()
1055 .find(|k| !self.has_condition_kind(*k))
1056 }
1057
1058 /// Earliest [`ConditionKind::ALL`] entry ABSENT from
1059 /// [`Self::preconditions`], or `None` when preconditions carry
1060 /// every variant — the precondition-side arm of the (precondition,
1061 /// postcondition, condition-union) first-missing-kind triad on
1062 /// [`EphemeralSpec`]. Thin typed delegate to
1063 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`]
1064 /// over [`Self::preconditions`].
1065 ///
1066 /// Peer of
1067 /// [`crate::boundary::Boundary::first_missing_precondition_kind`]
1068 /// on the point-domain surface — both peers compose against the
1069 /// SAME slice-level substrate primitive so a regression at the
1070 /// per-slice negated short-circuit walk fails at that primitive's
1071 /// tests rather than as silent drift at either struct-level arm.
1072 #[must_use]
1073 pub fn first_missing_precondition_kind(&self) -> Option<ConditionKind> {
1074 self.preconditions.first_missing_kind()
1075 }
1076
1077 /// Earliest [`ConditionKind::ALL`] entry ABSENT from
1078 /// [`Self::postconditions`], or `None` when postconditions carry
1079 /// every variant — the postcondition-side arm of the (precondition,
1080 /// postcondition, condition-union) first-missing-kind triad on
1081 /// [`EphemeralSpec`]. Thin typed delegate to
1082 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`]
1083 /// over [`Self::postconditions`].
1084 ///
1085 /// Peer of
1086 /// [`crate::boundary::Boundary::first_missing_postcondition_kind`]
1087 /// on the point-domain surface. See
1088 /// [`Self::first_missing_precondition_kind`] for the full
1089 /// rationale — the two methods share ONE lift motivation, ONE
1090 /// fail-before-pass-after composition-law pin, and ONE two-surface
1091 /// parity contract with the point-domain
1092 /// [`crate::boundary::Boundary`] first-missing-kind peer methods.
1093 #[must_use]
1094 pub fn first_missing_postcondition_kind(&self) -> Option<ConditionKind> {
1095 self.postconditions.first_missing_kind()
1096 }
1097
1098 /// Latest [`ConditionKind::ALL`] entry present in
1099 /// `preconditions ∪ postconditions`, or `None` when neither side
1100 /// populates any variant — the peer of
1101 /// [`crate::boundary::Boundary::last_distinct_condition_kind`]
1102 /// on the [`EphemeralSpec`] sugar surface.
1103 ///
1104 /// # Composed body — byte-identical to
1105 /// [`crate::boundary::Boundary::last_distinct_condition_kind`]
1106 ///
1107 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
1108 /// self.has_condition_kind(*k))` — the latest-element scalar
1109 /// projection of [`Self::distinct_condition_kinds`] onto its last
1110 /// entry via a REVERSED closed-set walk, without materializing
1111 /// the intermediate `Vec<ConditionKind>`. Byte-identical to the
1112 /// peer method on the point-domain [`crate::boundary::Boundary`]
1113 /// surface — both compose against the SAME slice-level substrate
1114 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
1115 /// via the two-slice union composed through
1116 /// [`Self::has_condition_kind`] so a regression at the per-slice
1117 /// REVERSED short-circuit walk fails at that primitive's tests
1118 /// rather than as silent drift at either struct-level latest-
1119 /// element caller.
1120 ///
1121 /// # Sibling to [`Self::first_distinct_condition_kind`] /
1122 /// [`Self::distinct_condition_kinds`]
1123 ///
1124 /// Time-reversed scalar peer of the earliest-element projection
1125 /// under the SAME two-slice union predicate. The two-surface
1126 /// parity contract now covers ELEVEN refinements on the condition
1127 /// axis (the nine listed at `first_distinct_condition_kind` plus
1128 /// `Option<ConditionKind>` earliest-element scalar of the closed-
1129 /// set-complement (`first_missing_*_kind`), plus this
1130 /// `Option<ConditionKind>` latest-element scalar of the closed-
1131 /// set-inversion (`last_distinct_*_kind`)). Byte-for-byte peer of
1132 /// the point-domain triad on [`crate::boundary::Boundary`].
1133 ///
1134 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1135 /// preserves proofs — the latest-element projection composes the
1136 /// SAME reversed closed-set walk on both this ephemeral surface
1137 /// and the point-domain [`crate::boundary::Boundary`] surface
1138 /// under short-circuit semantics). THEORY.md §VI.1 (generation
1139 /// over composition — a future [`ConditionKind`] variant added to
1140 /// `ALL` reaches both surfaces' last-distinct-kind triads
1141 /// mechanically through the SAME reversed closed-set walk).
1142 #[must_use]
1143 pub fn last_distinct_condition_kind(&self) -> Option<ConditionKind> {
1144 ConditionKind::ALL
1145 .iter()
1146 .rev()
1147 .copied()
1148 .find(|k| self.has_condition_kind(*k))
1149 }
1150
1151 /// Latest [`ConditionKind::ALL`] entry present in
1152 /// [`Self::preconditions`], or `None` when preconditions carry no
1153 /// matching kind — the precondition-side arm of the (precondition,
1154 /// postcondition, condition-union) last-distinct-kind triad on
1155 /// [`EphemeralSpec`]. Thin typed delegate to
1156 /// [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
1157 /// over [`Self::preconditions`].
1158 ///
1159 /// Peer of
1160 /// [`crate::boundary::Boundary::last_distinct_precondition_kind`]
1161 /// on the point-domain surface — both peers compose against the
1162 /// SAME slice-level substrate primitive so a regression at the
1163 /// per-slice REVERSED short-circuit walk fails at that primitive's
1164 /// tests rather than as silent drift at either struct-level arm.
1165 #[must_use]
1166 pub fn last_distinct_precondition_kind(&self) -> Option<ConditionKind> {
1167 self.preconditions.last_distinct_kind()
1168 }
1169
1170 /// Latest [`ConditionKind::ALL`] entry present in
1171 /// [`Self::postconditions`], or `None` when postconditions carry
1172 /// no matching kind — the postcondition-side arm of the
1173 /// (precondition, postcondition, condition-union) last-distinct-
1174 /// kind triad on [`EphemeralSpec`]. Thin typed delegate to
1175 /// [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
1176 /// over [`Self::postconditions`].
1177 ///
1178 /// Peer of
1179 /// [`crate::boundary::Boundary::last_distinct_postcondition_kind`]
1180 /// on the point-domain surface. See
1181 /// [`Self::last_distinct_precondition_kind`] for the full
1182 /// rationale — the two methods share ONE lift motivation, ONE
1183 /// fail-before-pass-after composition-law pin, and ONE two-surface
1184 /// parity contract with the point-domain
1185 /// [`crate::boundary::Boundary`] last-distinct-kind peer methods.
1186 #[must_use]
1187 pub fn last_distinct_postcondition_kind(&self) -> Option<ConditionKind> {
1188 self.postconditions.last_distinct_kind()
1189 }
1190
1191 /// Latest [`ConditionKind::ALL`] entry ABSENT from
1192 /// `preconditions ∪ postconditions`, or `None` when the union
1193 /// carries every variant — the peer of
1194 /// [`crate::boundary::Boundary::last_missing_condition_kind`]
1195 /// on the [`EphemeralSpec`] sugar surface.
1196 ///
1197 /// # Composed body — byte-identical to
1198 /// [`crate::boundary::Boundary::last_missing_condition_kind`]
1199 ///
1200 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
1201 /// !self.has_condition_kind(*k))` — the latest-element scalar
1202 /// projection of [`Self::missing_condition_kinds`] onto its last
1203 /// entry via a REVERSED closed-set walk under a NEGATED
1204 /// predicate. Byte-identical to the peer method on the point-
1205 /// domain [`crate::boundary::Boundary`] surface — both compose
1206 /// against the SAME slice-level substrate primitive
1207 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] via
1208 /// the two-slice union composed through
1209 /// [`Self::has_condition_kind`] so a regression at the per-slice
1210 /// negated REVERSED short-circuit walk fails at that primitive's
1211 /// tests rather than as silent drift at either struct-level
1212 /// latest-element caller.
1213 ///
1214 /// # Sibling to [`Self::first_missing_condition_kind`] /
1215 /// [`Self::missing_condition_kinds`]
1216 ///
1217 /// Time-reversed scalar peer of the earliest-element projection
1218 /// under the SAME negated two-slice union predicate. The two-
1219 /// surface parity contract now covers TWELVE refinements on the
1220 /// condition axis (the ten listed at `first_missing_condition_kind`
1221 /// plus `Option<ConditionKind>` latest-element scalar of the
1222 /// closed-set-inversion (`last_distinct_*_kind`), plus this
1223 /// `Option<ConditionKind>` latest-element scalar of the closed-
1224 /// set-complement). Byte-for-byte peer of the point-domain triad
1225 /// on [`crate::boundary::Boundary`].
1226 ///
1227 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1228 /// preserves proofs — the complement-latest-element projection
1229 /// composes the SAME reversed closed-set walk on both this
1230 /// ephemeral surface and the point-domain
1231 /// [`crate::boundary::Boundary`] surface under short-circuit
1232 /// semantics with a negated predicate). THEORY.md §VI.1
1233 /// (generation over composition — a future [`ConditionKind`]
1234 /// variant added to `ALL` reaches both surfaces' last-missing-kind
1235 /// triads mechanically through the SAME reversed closed-set walk).
1236 #[must_use]
1237 pub fn last_missing_condition_kind(&self) -> Option<ConditionKind> {
1238 ConditionKind::ALL
1239 .iter()
1240 .rev()
1241 .copied()
1242 .find(|k| !self.has_condition_kind(*k))
1243 }
1244
1245 /// Latest [`ConditionKind::ALL`] entry ABSENT from
1246 /// [`Self::preconditions`], or `None` when preconditions carry
1247 /// every variant — the precondition-side arm of the (precondition,
1248 /// postcondition, condition-union) last-missing-kind triad on
1249 /// [`EphemeralSpec`]. Thin typed delegate to
1250 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`]
1251 /// over [`Self::preconditions`].
1252 ///
1253 /// Peer of
1254 /// [`crate::boundary::Boundary::last_missing_precondition_kind`]
1255 /// on the point-domain surface — both peers compose against the
1256 /// SAME slice-level substrate primitive so a regression at the
1257 /// per-slice negated REVERSED short-circuit walk fails at that
1258 /// primitive's tests rather than as silent drift at either
1259 /// struct-level arm.
1260 #[must_use]
1261 pub fn last_missing_precondition_kind(&self) -> Option<ConditionKind> {
1262 self.preconditions.last_missing_kind()
1263 }
1264
1265 /// Latest [`ConditionKind::ALL`] entry ABSENT from
1266 /// [`Self::postconditions`], or `None` when postconditions carry
1267 /// every variant — the postcondition-side arm of the
1268 /// (precondition, postcondition, condition-union) last-missing-
1269 /// kind triad on [`EphemeralSpec`]. Thin typed delegate to
1270 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`]
1271 /// over [`Self::postconditions`].
1272 ///
1273 /// Peer of
1274 /// [`crate::boundary::Boundary::last_missing_postcondition_kind`]
1275 /// on the point-domain surface. See
1276 /// [`Self::last_missing_precondition_kind`] for the full
1277 /// rationale — the two methods share ONE lift motivation, ONE
1278 /// fail-before-pass-after composition-law pin, and ONE two-surface
1279 /// parity contract with the point-domain
1280 /// [`crate::boundary::Boundary`] last-missing-kind peer methods.
1281 #[must_use]
1282 pub fn last_missing_postcondition_kind(&self) -> Option<ConditionKind> {
1283 self.postconditions.last_missing_kind()
1284 }
1285
1286 /// `true` iff `preconditions ∪ postconditions` carries every
1287 /// [`ConditionKind::ALL`] variant at least once — the peer of
1288 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on
1289 /// the [`EphemeralSpec`] sugar surface.
1290 ///
1291 /// # Composed body — byte-identical to
1292 /// [`crate::boundary::Boundary::is_condition_kind_saturated`]
1293 ///
1294 /// `ConditionKind::ALL.iter().all(|k| self.has_condition_kind(*k))`
1295 /// — the saturation-endpoint projection of
1296 /// [`Self::missing_condition_kinds`] onto its emptiness test via
1297 /// a SHORT-CIRCUITING closed-set walk under the two-slice union
1298 /// primitive [`Self::has_condition_kind`]. Byte-identical to the
1299 /// peer method on the point-domain [`crate::boundary::Boundary`]
1300 /// surface — both compose against the SAME slice-level substrate
1301 /// primitive [`crate::boundary::ConditionSliceExt::is_kind_saturated`]
1302 /// via the two-slice union so a regression at the per-slice `all`
1303 /// short-circuit fails at that primitive's tests rather than as
1304 /// silent drift at either struct-level saturation caller.
1305 ///
1306 /// # Sibling to [`Self::missing_condition_kinds`] /
1307 /// [`Self::missing_condition_kind_count`]
1308 ///
1309 /// Boolean saturation-endpoint peer of the widened and scalar
1310 /// closed-set-complement primitives on the ephemeral-union
1311 /// surface — where those primitives return the SET and its
1312 /// cardinality, `is_condition_kind_saturated` collapses the
1313 /// scalar to its zero-arm Boolean projection.
1314 ///
1315 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1316 /// preserves proofs — the saturation-endpoint projection composes
1317 /// the SAME closed-set walk on both this ephemeral surface and the
1318 /// point-domain [`crate::boundary::Boundary`] surface under
1319 /// short-circuit semantics). THEORY.md §VI.1 (generation over
1320 /// composition — a future [`ConditionKind`] variant added to `ALL`
1321 /// reaches both surfaces' saturation-predicate triads mechanically
1322 /// through the SAME closed-set walk).
1323 #[must_use]
1324 pub fn is_condition_kind_saturated(&self) -> bool {
1325 ConditionKind::ALL
1326 .iter()
1327 .all(|k| self.has_condition_kind(*k))
1328 }
1329
1330 /// `true` iff [`Self::preconditions`] carries every
1331 /// [`ConditionKind::ALL`] variant at least once — the precondition-
1332 /// side arm of the (precondition, postcondition, condition-union)
1333 /// saturation-predicate triad on [`EphemeralSpec`]. Thin typed
1334 /// delegate to
1335 /// [`crate::boundary::ConditionSliceExt::is_kind_saturated`] over
1336 /// [`Self::preconditions`].
1337 ///
1338 /// Peer of
1339 /// [`crate::boundary::Boundary::is_precondition_kind_saturated`]
1340 /// on the point-domain surface — both peers compose against the
1341 /// SAME slice-level substrate primitive so a regression at the
1342 /// per-slice `all` short-circuit fails at that primitive's tests
1343 /// rather than as silent drift at either struct-level arm.
1344 #[must_use]
1345 pub fn is_precondition_kind_saturated(&self) -> bool {
1346 self.preconditions.is_kind_saturated()
1347 }
1348
1349 /// `true` iff [`Self::postconditions`] carries every
1350 /// [`ConditionKind::ALL`] variant at least once — the postcondition-
1351 /// side arm of the (precondition, postcondition, condition-union)
1352 /// saturation-predicate triad on [`EphemeralSpec`]. Thin typed
1353 /// delegate to
1354 /// [`crate::boundary::ConditionSliceExt::is_kind_saturated`] over
1355 /// [`Self::postconditions`].
1356 ///
1357 /// Peer of
1358 /// [`crate::boundary::Boundary::is_postcondition_kind_saturated`]
1359 /// on the point-domain surface. See
1360 /// [`Self::is_precondition_kind_saturated`] for the full rationale
1361 /// — the two methods share ONE lift motivation, ONE fail-before-
1362 /// pass-after composition-law pin, and ONE two-surface parity
1363 /// contract with the point-domain
1364 /// [`crate::boundary::Boundary`] saturation-predicate peer methods.
1365 #[must_use]
1366 pub fn is_postcondition_kind_saturated(&self) -> bool {
1367 self.postconditions.is_kind_saturated()
1368 }
1369
1370 /// `true` iff `preconditions ∪ postconditions` is MISSING at least
1371 /// one [`ConditionKind::ALL`] variant — the peer of
1372 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
1373 /// the [`EphemeralSpec`] sugar surface.
1374 ///
1375 /// # Composed body — byte-identical to
1376 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`]
1377 ///
1378 /// `!self.is_condition_kind_saturated()` — the at-least-one
1379 /// halfspace projection of [`Self::missing_condition_kinds`] onto
1380 /// its non-emptiness test via a SHORT-CIRCUITING closed-set walk
1381 /// under the two-slice union primitive [`Self::has_condition_kind`]
1382 /// negated. Byte-identical to the peer method on the point-domain
1383 /// [`crate::boundary::Boundary`] surface — both compose against the
1384 /// SAME slice-level substrate primitive
1385 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`] via
1386 /// the two-slice union so a regression at the per-slice `all`
1387 /// short-circuit under negation fails at that primitive's tests
1388 /// rather than as silent drift at either struct-level at-least-
1389 /// one halfspace caller.
1390 ///
1391 /// # Sibling to [`Self::missing_condition_kinds`] /
1392 /// [`Self::missing_condition_kind_count`]
1393 ///
1394 /// Boolean at-least-one halfspace peer of the widened and scalar
1395 /// closed-set-complement primitives on the ephemeral-union
1396 /// surface — where those primitives return the SET and its
1397 /// cardinality, `has_any_missing_condition_kind` collapses either
1398 /// to its `>= 1` halfspace Boolean.
1399 ///
1400 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1401 /// preserves proofs — the at-least-one halfspace projection
1402 /// composes the SAME closed-set walk under negation on both this
1403 /// ephemeral surface and the point-domain
1404 /// [`crate::boundary::Boundary`] surface under short-circuit
1405 /// semantics). THEORY.md §VI.1 (generation over composition — a
1406 /// future [`ConditionKind`] variant added to `ALL` reaches both
1407 /// surfaces' at-least-one halfspace triads mechanically through
1408 /// the SAME closed-set walk).
1409 #[must_use]
1410 pub fn has_any_missing_condition_kind(&self) -> bool {
1411 !self.is_condition_kind_saturated()
1412 }
1413
1414 /// `true` iff [`Self::preconditions`] is MISSING at least one
1415 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1416 /// the (precondition, postcondition, condition-union) at-least-
1417 /// one halfspace triad on [`EphemeralSpec`]. Thin typed delegate
1418 /// to [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
1419 /// over [`Self::preconditions`].
1420 ///
1421 /// Peer of
1422 /// [`crate::boundary::Boundary::has_any_missing_precondition_kind`]
1423 /// on the point-domain surface — both peers compose against the
1424 /// SAME slice-level substrate primitive so a regression at the
1425 /// per-slice `all` short-circuit under negation fails at that
1426 /// primitive's tests rather than as silent drift at either
1427 /// struct-level arm.
1428 #[must_use]
1429 pub fn has_any_missing_precondition_kind(&self) -> bool {
1430 self.preconditions.has_any_missing_kind()
1431 }
1432
1433 /// `true` iff [`Self::postconditions`] is MISSING at least one
1434 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1435 /// the (precondition, postcondition, condition-union) at-least-
1436 /// one halfspace triad on [`EphemeralSpec`]. Thin typed delegate
1437 /// to [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
1438 /// over [`Self::postconditions`].
1439 ///
1440 /// Peer of
1441 /// [`crate::boundary::Boundary::has_any_missing_postcondition_kind`]
1442 /// on the point-domain surface. See
1443 /// [`Self::has_any_missing_precondition_kind`] for the full
1444 /// rationale — the two methods share ONE lift motivation, ONE
1445 /// fail-before-pass-after composition-law pin, and ONE two-surface
1446 /// parity contract with the point-domain
1447 /// [`crate::boundary::Boundary`] at-least-one halfspace peer
1448 /// methods.
1449 #[must_use]
1450 pub fn has_any_missing_postcondition_kind(&self) -> bool {
1451 self.postconditions.has_any_missing_kind()
1452 }
1453
1454 /// `true` iff `preconditions ∪ postconditions` is MISSING EXACTLY
1455 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
1456 /// (precondition, postcondition, condition-union) cardinality-
1457 /// mid-endpoint triad on [`EphemeralSpec`] closing the near-
1458 /// saturation-endpoint on the union of the two condition slots.
1459 /// The Boolean cardinality-mid-endpoint fast-path peer of
1460 /// [`Self::is_condition_kind_saturated`]: where the saturation-
1461 /// endpoint predicate answers "is the union covered by every ALL
1462 /// variant?", `has_unique_missing_condition_kind` answers "is the
1463 /// union one kind away from covered?".
1464 ///
1465 /// Composed body: constructs a two-step-short-circuit walk over
1466 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
1467 /// union primitive negated — the first missing union arm surfaces,
1468 /// then the walk short-circuits at the second. Byte-for-byte peer
1469 /// of
1470 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
1471 /// one slice-layer down, lifted to compose against
1472 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1473 /// against a single slice's `has_kind`.
1474 ///
1475 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
1476 ///
1477 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1478 /// two-step short-circuit body composed against the point-domain
1479 /// surface's own union primitive. Both methods compose against
1480 /// the SAME slice-level substrate primitive
1481 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
1482 /// via the two-slice union — a regression at the per-slice
1483 /// near-saturation-endpoint walk fails at that primitive's tests
1484 /// rather than as silent drift at either struct-level near-
1485 /// saturation caller.
1486 ///
1487 /// # Sibling to [`Self::missing_condition_kinds`] /
1488 /// [`Self::missing_condition_kind_count`]
1489 ///
1490 /// Cardinality-mid-endpoint Boolean projection of the widened +
1491 /// scalar closed-set-complement primitives on the ephemeral-union
1492 /// surface — where those primitives return the FULL missing SET
1493 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
1494 /// in `0..=ConditionKind::ALL.len()`),
1495 /// `has_unique_missing_condition_kind` collapses either the
1496 /// widened primitive to its unit-length Boolean or the scalar to
1497 /// its `== 1` cardinality-mid-endpoint Boolean. Strictly cheaper
1498 /// than either widened primitive on every arm with `≥ 2` missing
1499 /// kinds because the negation short-circuits at the second
1500 /// missing kind rather than allocating the closed-set-complement
1501 /// scan or walking every slot to build the scalar cardinality.
1502 ///
1503 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1504 /// preserves proofs — the cardinality-mid-endpoint projection on
1505 /// the missing axis composes the SAME two-step short-circuit walk
1506 /// under a two-slice union negation on both this ephemeral
1507 /// surface and the point-domain
1508 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
1509 /// (generation over composition — a new [`ConditionKind`]
1510 /// variant reaches both surfaces' cardinality-mid-endpoint triads
1511 /// mechanically through the delegated union primitive).
1512 #[must_use]
1513 pub fn has_unique_missing_condition_kind(&self) -> bool {
1514 let mut it = ConditionKind::ALL
1515 .iter()
1516 .copied()
1517 .filter(|k| !self.has_condition_kind(*k));
1518 it.next().is_some() && it.next().is_none()
1519 }
1520
1521 /// `true` iff [`Self::preconditions`] is MISSING EXACTLY ONE
1522 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1523 /// the (precondition, postcondition, condition-union)
1524 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
1525 /// typed delegate to
1526 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
1527 /// over [`Self::preconditions`].
1528 ///
1529 /// Peer of
1530 /// [`crate::boundary::Boundary::has_unique_missing_precondition_kind`]
1531 /// on the point-domain surface — both peers compose against the
1532 /// SAME slice-level substrate primitive so a regression at the
1533 /// per-slice two-step short-circuit walk under negation fails at
1534 /// that primitive's tests rather than as silent drift at either
1535 /// struct-level arm.
1536 #[must_use]
1537 pub fn has_unique_missing_precondition_kind(&self) -> bool {
1538 self.preconditions.has_unique_missing_kind()
1539 }
1540
1541 /// `true` iff [`Self::postconditions`] is MISSING EXACTLY ONE
1542 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1543 /// the (precondition, postcondition, condition-union)
1544 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
1545 /// typed delegate to
1546 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
1547 /// over [`Self::postconditions`].
1548 ///
1549 /// Peer of
1550 /// [`crate::boundary::Boundary::has_unique_missing_postcondition_kind`]
1551 /// on the point-domain surface. See
1552 /// [`Self::has_unique_missing_precondition_kind`] for the full
1553 /// rationale — the two methods share ONE lift motivation, ONE
1554 /// fail-before-pass-after composition-law pin, and ONE two-surface
1555 /// parity contract with the point-domain
1556 /// [`crate::boundary::Boundary`] cardinality-mid-endpoint peer
1557 /// methods.
1558 #[must_use]
1559 pub fn has_unique_missing_postcondition_kind(&self) -> bool {
1560 self.postconditions.has_unique_missing_kind()
1561 }
1562
1563 /// `true` iff `preconditions ∪ postconditions` is MISSING AT
1564 /// LEAST TWO [`ConditionKind::ALL`] variants — the union arm of
1565 /// the (precondition, postcondition, condition-union) cardinality-
1566 /// many-arm triad on [`EphemeralSpec`] closing the "≥ 2 holes
1567 /// remaining" arm on the union of the two condition slots. The
1568 /// Boolean cardinality many-arm fast-path peer of
1569 /// [`Self::has_unique_missing_condition_kind`] (=1 arm) and
1570 /// [`Self::is_condition_kind_saturated`] (=0 arm): closes the
1571 /// {0, 1, ≥2} trichotomy on the missing axis at the ephemeral
1572 /// union struct layer.
1573 ///
1574 /// Composed body: constructs a two-step-short-circuit walk over
1575 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
1576 /// union primitive negated — pulls up to two hits off the
1577 /// filtered iterator; the primitive returns `true` iff BOTH the
1578 /// first and the second are [`Some`]. Byte-for-byte peer of
1579 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1580 /// one slice-layer down, lifted to compose against
1581 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1582 /// against a single slice's `has_kind`.
1583 ///
1584 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
1585 ///
1586 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1587 /// two-step short-circuit body composed against the point-domain
1588 /// surface's own union primitive. Both methods compose against
1589 /// the SAME slice-level substrate primitive
1590 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1591 /// via the two-slice union — a regression at the per-slice many-
1592 /// arm walk fails at that primitive's tests rather than as silent
1593 /// drift at either struct-level many-missing caller.
1594 ///
1595 /// # Sibling to [`Self::missing_condition_kinds`] /
1596 /// [`Self::missing_condition_kind_count`]
1597 ///
1598 /// Cardinality-many-arm Boolean projection of the widened +
1599 /// scalar closed-set-complement primitives on the ephemeral-union
1600 /// surface — where those primitives return the FULL missing SET
1601 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
1602 /// in `0..=ConditionKind::ALL.len()`),
1603 /// `has_multiple_missing_condition_kind` collapses either the
1604 /// widened primitive to its ≥ 2-length Boolean or the scalar to
1605 /// its `>= 2` cardinality-many-arm Boolean. Strictly cheaper than
1606 /// either widened primitive on every arm with `≥ 2` missing kinds
1607 /// because the negation short-circuits at the second missing kind
1608 /// rather than allocating the closed-set-complement scan or
1609 /// walking every slot to build the scalar cardinality.
1610 ///
1611 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1612 /// preserves proofs — the cardinality-many-arm projection on the
1613 /// missing axis composes the SAME two-step short-circuit walk
1614 /// under a two-slice union negation on both this ephemeral
1615 /// surface and the point-domain
1616 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
1617 /// (generation over composition — a new [`ConditionKind`]
1618 /// variant reaches both surfaces' cardinality-many-arm triads
1619 /// mechanically through the delegated union primitive).
1620 #[must_use]
1621 pub fn has_multiple_missing_condition_kind(&self) -> bool {
1622 let mut it = ConditionKind::ALL
1623 .iter()
1624 .copied()
1625 .filter(|k| !self.has_condition_kind(*k));
1626 it.next().is_some() && it.next().is_some()
1627 }
1628
1629 /// `true` iff [`Self::preconditions`] is MISSING AT LEAST TWO
1630 /// [`ConditionKind::ALL`] variants — the precondition-side arm of
1631 /// the (precondition, postcondition, condition-union) cardinality-
1632 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
1633 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1634 /// over [`Self::preconditions`].
1635 ///
1636 /// Peer of
1637 /// [`crate::boundary::Boundary::has_multiple_missing_precondition_kind`]
1638 /// on the point-domain surface — both peers compose against the
1639 /// SAME slice-level substrate primitive so a regression at the
1640 /// per-slice two-step short-circuit walk under negation fails at
1641 /// that primitive's tests rather than as silent drift at either
1642 /// struct-level arm.
1643 #[must_use]
1644 pub fn has_multiple_missing_precondition_kind(&self) -> bool {
1645 self.preconditions.has_multiple_missing_kinds()
1646 }
1647
1648 /// `true` iff [`Self::postconditions`] is MISSING AT LEAST TWO
1649 /// [`ConditionKind::ALL`] variants — the postcondition-side arm of
1650 /// the (precondition, postcondition, condition-union) cardinality-
1651 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
1652 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
1653 /// over [`Self::postconditions`].
1654 ///
1655 /// Peer of
1656 /// [`crate::boundary::Boundary::has_multiple_missing_postcondition_kind`]
1657 /// on the point-domain surface. See
1658 /// [`Self::has_multiple_missing_precondition_kind`] for the full
1659 /// rationale — the two methods share ONE lift motivation, ONE
1660 /// fail-before-pass-after composition-law pin, and ONE two-surface
1661 /// parity contract with the point-domain
1662 /// [`crate::boundary::Boundary`] cardinality-many-arm peer
1663 /// methods.
1664 #[must_use]
1665 pub fn has_multiple_missing_postcondition_kind(&self) -> bool {
1666 self.postconditions.has_multiple_missing_kinds()
1667 }
1668
1669 /// `true` iff `preconditions ∪ postconditions` is MISSING AT MOST
1670 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
1671 /// (precondition, postcondition, condition-union) cardinality
1672 /// "≤ 1" triad on [`EphemeralSpec`] closing the "at most one hole
1673 /// remaining" arm on the union of the two condition slots. The
1674 /// Boolean cardinality "≤ 1" negation peer of
1675 /// [`Self::has_multiple_missing_condition_kind`] (≥ 2 many-arm)
1676 /// under the definitional negation
1677 /// `!has_multiple_missing_condition_kind`, and the trichotomy-
1678 /// union peer of [`Self::is_condition_kind_saturated`] (=0
1679 /// zero-arm) OR [`Self::has_unique_missing_condition_kind`] (=1
1680 /// mid-endpoint) — names the arrangement space where the
1681 /// ephemeral spec is SATURATED-OR-NEAR-SATURATED on the union
1682 /// (zero or exactly one kind missing across the union of the two
1683 /// slices).
1684 ///
1685 /// Composed body: `!self.has_multiple_missing_condition_kind()`
1686 /// — a definitional negation of the many-arm union primitive.
1687 /// Short-circuits transitively through
1688 /// [`Self::has_multiple_missing_condition_kind`]'s two-step short-
1689 /// circuit walk over [`ConditionKind::ALL`] under negated
1690 /// [`Self::has_condition_kind`]. Byte-for-byte peer of
1691 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
1692 /// one slice-layer down, lifted to compose against
1693 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1694 /// against a single slice's `has_kind`.
1695 ///
1696 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
1697 ///
1698 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1699 /// definitional-negation body composed against the point-domain
1700 /// surface's own many-arm union primitive. Both methods compose
1701 /// against the SAME slice-level substrate primitive
1702 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
1703 /// via the two-slice union — a regression at the per-slice "≤ 1"
1704 /// negation fails at that primitive's tests rather than as silent
1705 /// drift at either struct-level near-saturation-or-saturated
1706 /// caller.
1707 ///
1708 /// # Sibling to [`Self::missing_condition_kinds`] /
1709 /// [`Self::missing_condition_kind_count`]
1710 ///
1711 /// Cardinality "≤ 1" Boolean projection of the widened + scalar
1712 /// closed-set-complement primitives on the ephemeral-union
1713 /// surface — where those primitives return the FULL missing SET
1714 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
1715 /// in `0..=ConditionKind::ALL.len()`),
1716 /// `has_at_most_one_missing_condition_kind` collapses either the
1717 /// widened primitive to its `≤ 1`-length Boolean or the scalar
1718 /// to its `<= 1` cardinality-negation Boolean. Strictly cheaper
1719 /// than either widened primitive on every arm because the
1720 /// underlying many-arm walk short-circuits at the second missing
1721 /// kind — a subsequent bit-flip surfaces at ONE substrate call
1722 /// with no allocation.
1723 ///
1724 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1725 /// preserves proofs — the cardinality "≤ 1" projection on the
1726 /// missing axis composes the SAME definitional negation of the
1727 /// many-arm two-step short-circuit walk on both this ephemeral
1728 /// surface and the point-domain [`crate::boundary::Boundary`]
1729 /// surface). THEORY.md §VI.1 (generation over composition — a
1730 /// new [`ConditionKind`] variant reaches both surfaces'
1731 /// cardinality "≤ 1" triads mechanically through the delegated
1732 /// union primitive).
1733 #[must_use]
1734 pub fn has_at_most_one_missing_condition_kind(&self) -> bool {
1735 !self.has_multiple_missing_condition_kind()
1736 }
1737
1738 /// `true` iff [`Self::preconditions`] is MISSING AT MOST ONE
1739 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1740 /// the (precondition, postcondition, condition-union) cardinality
1741 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
1742 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
1743 /// over [`Self::preconditions`].
1744 ///
1745 /// Peer of
1746 /// [`crate::boundary::Boundary::has_at_most_one_missing_precondition_kind`]
1747 /// on the point-domain surface — both peers compose against the
1748 /// SAME slice-level substrate primitive so a regression at the
1749 /// per-slice "≤ 1" negation fails at that primitive's tests
1750 /// rather than as silent drift at either struct-level arm.
1751 #[must_use]
1752 pub fn has_at_most_one_missing_precondition_kind(&self) -> bool {
1753 self.preconditions.has_at_most_one_missing_kind()
1754 }
1755
1756 /// `true` iff [`Self::postconditions`] is MISSING AT MOST ONE
1757 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1758 /// the (precondition, postcondition, condition-union) cardinality
1759 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
1760 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
1761 /// over [`Self::postconditions`].
1762 ///
1763 /// Peer of
1764 /// [`crate::boundary::Boundary::has_at_most_one_missing_postcondition_kind`]
1765 /// on the point-domain surface. See
1766 /// [`Self::has_at_most_one_missing_precondition_kind`] for the
1767 /// full rationale — the two methods share ONE lift motivation,
1768 /// ONE fail-before-pass-after composition-law pin, and ONE two-
1769 /// surface parity contract with the point-domain
1770 /// [`crate::boundary::Boundary`] cardinality "≤ 1" peer methods.
1771 #[must_use]
1772 pub fn has_at_most_one_missing_postcondition_kind(&self) -> bool {
1773 self.postconditions.has_at_most_one_missing_kind()
1774 }
1775
1776 /// `true` iff `preconditions ∪ postconditions` carries NO
1777 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
1778 /// — the peer of
1779 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
1780 /// [`EphemeralSpec`] sugar surface.
1781 ///
1782 /// # Composed body — byte-identical to
1783 /// [`crate::boundary::Boundary::lacks_condition_kind`]
1784 ///
1785 /// `!self.has_condition_kind(kind)` — the definitional negation of
1786 /// the two-slice union primitive [`Self::has_condition_kind`].
1787 /// Byte-identical to the peer method on the point-domain
1788 /// [`crate::boundary::Boundary`] surface — both compose against
1789 /// the SAME slice-level substrate primitive
1790 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] via the
1791 /// two-slice union so a regression at the per-slice negation
1792 /// fails at that primitive's tests rather than as silent drift at
1793 /// either struct-level complement caller.
1794 ///
1795 /// # Sibling to [`Self::missing_condition_kinds`] /
1796 /// [`Self::missing_condition_kind_count`]
1797 ///
1798 /// Per-kind Boolean projection of the widened + scalar closed-set-
1799 /// complement primitives on the ephemeral-union surface — where
1800 /// those primitives return the FULL missing SET (a `Vec` of every
1801 /// absent kind) and its cardinality (a `usize`),
1802 /// `lacks_condition_kind` collapses the missing SET to its
1803 /// per-kind membership Boolean for ONE addressed kind. Strictly
1804 /// cheaper than reaching for the widened primitive on every
1805 /// per-kind question because the negation short-circuits through
1806 /// [`Self::has_condition_kind`] rather than allocating the
1807 /// closed-set-complement scan.
1808 ///
1809 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1810 /// preserves proofs — the per-kind closed-set-complement
1811 /// projection composes the SAME two-slice union negation on both
1812 /// this ephemeral surface and the point-domain
1813 /// [`crate::boundary::Boundary`] surface under definitional
1814 /// negation). THEORY.md §VI.1 (generation over composition — a
1815 /// future [`ConditionKind`] variant reaches both surfaces'
1816 /// per-kind-complement triads mechanically through the delegated
1817 /// union primitive).
1818 #[must_use]
1819 pub fn lacks_condition_kind(&self, kind: ConditionKind) -> bool {
1820 !self.has_condition_kind(kind)
1821 }
1822
1823 /// `true` iff [`Self::preconditions`] carries NO
1824 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
1825 /// — the precondition-side arm of the (precondition, postcondition,
1826 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
1827 /// Thin typed delegate to
1828 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
1829 /// [`Self::preconditions`].
1830 ///
1831 /// Peer of
1832 /// [`crate::boundary::Boundary::lacks_precondition_kind`] on the
1833 /// point-domain surface — both peers compose against the SAME
1834 /// slice-level substrate primitive so a regression at the
1835 /// per-slice negation fails at that primitive's tests rather than
1836 /// as silent drift at either struct-level arm.
1837 #[must_use]
1838 pub fn lacks_precondition_kind(&self, kind: ConditionKind) -> bool {
1839 self.preconditions.lacks_kind(kind)
1840 }
1841
1842 /// `true` iff [`Self::postconditions`] carries NO
1843 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
1844 /// — the postcondition-side arm of the (precondition, postcondition,
1845 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
1846 /// Thin typed delegate to
1847 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
1848 /// [`Self::postconditions`].
1849 ///
1850 /// Peer of
1851 /// [`crate::boundary::Boundary::lacks_postcondition_kind`] on the
1852 /// point-domain surface. See [`Self::lacks_precondition_kind`] for
1853 /// the full rationale — the two methods share ONE lift motivation,
1854 /// ONE fail-before-pass-after composition-law pin, and ONE
1855 /// two-surface parity contract with the point-domain
1856 /// [`crate::boundary::Boundary`] per-kind-complement peer methods.
1857 #[must_use]
1858 pub fn lacks_postcondition_kind(&self, kind: ConditionKind) -> bool {
1859 self.postconditions.lacks_kind(kind)
1860 }
1861
1862 /// True iff this ephemeral spec's stored [`TeardownPolicy`] equals
1863 /// `kind` — the substrate primitive that owns the
1864 /// (`&EphemeralSpec`, [`TeardownPolicy`]) → `bool` presence-probe
1865 /// shape on the sugar-surface type.
1866 ///
1867 /// # Peer to [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
1868 ///
1869 /// [`EphemeralLifetime::has_teardown_policy`] carries the same
1870 /// `(&self, TeardownPolicy) -> bool` signature on the point-surface
1871 /// carrier ([`ProcessSpec`]'s nested [`crate::lifetime::Lifetime`]
1872 /// slot reached through
1873 /// [`crate::lifetime::Lifetime::resolved_ephemeral`]); this peer
1874 /// composes byte-identical `==` semantics on
1875 /// [`EphemeralSpec`]'s direct `teardown: TeardownPolicy` scalar
1876 /// slot, so both surfaces' `teardown-policy-<kind>` require-tag
1877 /// families ([`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
1878 /// on the point surface, this peer on the ephemeral surface) route
1879 /// through the SAME scalar `==` shape. A future normalization at
1880 /// the probe shape (a widened return carrying a `TerminatePolicy`
1881 /// disambiguator, a debug-build assertion on operator-set vs
1882 /// defaulted overrides, a fleet-wide warn on `Never` combined with
1883 /// short TTLs) lands at ONE site per surface and every downstream
1884 /// `teardown-policy-<kind>` require-tag family + closed-set audit
1885 /// dispatcher picks it up mechanically.
1886 ///
1887 /// # Semantics — VARIANT match, not POPULATED slot
1888 ///
1889 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
1890 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
1891 /// absent state to detect. `has_teardown_policy(kind)` returns
1892 /// `true` iff `self.teardown == kind`. On a hand-authored
1893 /// [`EphemeralSpec`] that omits `:teardown` from the
1894 /// `(defephemeral …)` form (or a Rust builder that reaches
1895 /// [`TeardownPolicy::default`]) the probe returns `true` for
1896 /// [`TeardownPolicy::Always`] and `false` for every other variant
1897 /// — distinct from the Option-slot axis where a default carrier
1898 /// returns `false` for EVERY kind. An operator who left
1899 /// `:teardown` at the substrate default IS configured for
1900 /// `Always`, and a `:requires (teardown-policy-Always)` check
1901 /// should pass; only an operator who deliberately overrode the
1902 /// policy to `OnAttested` / `OnFailed` / `Never` fails the tag on
1903 /// this axis.
1904 ///
1905 /// # Corner — (required-scalar-child)
1906 ///
1907 /// Fresh corner on the ephemeral surface's presence-probe algebra:
1908 /// [`EphemeralSpec`] has no Option-parent hop between the sugar
1909 /// struct and the `teardown` scalar (the point surface reaches
1910 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
1911 /// through the Option-parent `resolved_ephemeral()` gate), so the
1912 /// probe body is a bare scalar `==` on a required field. Distinct
1913 /// from [`Self::has_condition_kind`] on this same surface, which
1914 /// walks a `Vec<Condition>` slice-child.
1915 ///
1916 /// # Compounding
1917 ///
1918 /// The ephemeral require-tag classifier composes this primitive
1919 /// with the closed-set `FromStr` autoderived on [`TeardownPolicy`]
1920 /// through the `strip_and_classify_prefixed_kind` substrate to
1921 /// publish a `teardown-policy-<kind>` prefix family byte-for-byte
1922 /// symmetrical with the point surface's family via
1923 /// [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]. A
1924 /// future fifth [`TeardownPolicy`] variant added to `ALL` (a
1925 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
1926 /// reaches BOTH surfaces' `teardown-policy-<kind>` prefix families
1927 /// through the SAME closed-set walk with no per-caller edit — the
1928 /// two-surface symmetry means adding a variant on the closed set
1929 /// publishes it in lockstep across every downstream consumer.
1930 ///
1931 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1932 /// preserves proofs — the scalar-carrier presence-probe body lives
1933 /// at ONE substrate site per surface so every downstream
1934 /// (`teardown-policy-<kind>` require-tag families on both surfaces
1935 /// in tatara-check, closed-set audit dispatchers, future variant
1936 /// additions on [`TeardownPolicy`]) binds through the SAME
1937 /// `has(kind)` shape rather than restating the `<eph>.teardown ==
1938 /// kind` closure body at each call site). THEORY.md §VI.1
1939 /// (generation over composition — a future variant lands at ONE
1940 /// `ALL` entry + one `as_str` arm on the closed set and the probe
1941 /// picks it up mechanically without further per-consumer edits).
1942 #[must_use]
1943 pub fn has_teardown_policy(&self, kind: TeardownPolicy) -> bool {
1944 self.teardown == kind
1945 }
1946
1947 /// Derived-bool-predicate presence probe on the stored
1948 /// [`Self::teardown`] slot — `true` iff this ephemeral sugar's
1949 /// [`TeardownPolicy`] would auto-SIGTERM the Process on the
1950 /// queried [`ProcessPhase`] transition (as read through
1951 /// [`TeardownPolicy::should_teardown_on`]).
1952 ///
1953 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
1954 ///
1955 /// Same shape, same axis, one refinement lower: the point-surface
1956 /// peer on [`crate::lifetime::EphemeralLifetime`] composes the SAME
1957 /// [`TeardownPolicy::should_teardown_on`] predicate against the
1958 /// SAME stored `teardown_policy` slot; this method composes the
1959 /// same predicate against the sugar surface's flattened
1960 /// [`Self::teardown`] slot. Both bodies delegate to the ONE
1961 /// substrate owner [`TeardownPolicy::should_teardown_on`], so a
1962 /// regression at the (policy, phase) → bool truth table surfaces
1963 /// at THAT primitive's tests rather than as silent drift at
1964 /// either struct-level caller.
1965 ///
1966 /// # Corner — (required-scalar-parent × derived-bool-predicate-child)
1967 ///
1968 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
1969 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
1970 /// Option-parent hop between the sugar struct and the `teardown`
1971 /// scalar (the point surface reaches
1972 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
1973 /// through the Option-parent `resolved_ephemeral()` gate). The
1974 /// probe body is a bare predicate application on a required
1975 /// field. Distinct from [`Self::has_teardown_policy`] on this
1976 /// same surface, which reads the raw stored variant for equality
1977 /// (`self.teardown == kind`) rather than the derived firing-arm
1978 /// predicate against a [`ProcessPhase`] argument.
1979 ///
1980 /// # Compounding
1981 ///
1982 /// The ephemeral require-tag classifier composes this primitive
1983 /// with the closed-set [`crate::phase::ProcessPhase`]'s
1984 /// autoderived `FromStr` through the
1985 /// `strip_and_classify_prefixed_kind` substrate to publish a
1986 /// `teardown-fires-on-<phase>` prefix family byte-for-byte
1987 /// symmetrical with the point surface's family via
1988 /// [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`].
1989 /// A future fifth [`TeardownPolicy`] variant added to `ALL` (a
1990 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
1991 /// reaches BOTH surfaces' `teardown-fires-on-<phase>` prefix
1992 /// families through the SAME
1993 /// [`TeardownPolicy::should_teardown_on`] match with no per-
1994 /// caller edit — the two-surface symmetry means adding a variant
1995 /// on the closed set publishes it in lockstep across every
1996 /// downstream consumer.
1997 ///
1998 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1999 /// preserves proofs — the derived-bool-predicate presence-probe
2000 /// body lives at ONE substrate site per surface, both composing
2001 /// the SAME [`TeardownPolicy::should_teardown_on`] projection, so
2002 /// every downstream (`teardown-fires-on-<phase>` require-tag
2003 /// families on both surfaces in tatara-check, closed-set audit
2004 /// dispatchers, future variant additions on either
2005 /// [`TeardownPolicy`] or [`crate::phase::ProcessPhase`]) binds
2006 /// through the SAME `has_teardown_firing_on(phase)` shape rather
2007 /// than restating the `<eph>.teardown.should_teardown_on(phase)`
2008 /// closure body at each call site). THEORY.md §VI.1 (generation
2009 /// over composition — a future variant lands at ONE `ALL` entry +
2010 /// one `as_str` arm + one `should_teardown_on` arm on the closed
2011 /// set and the probe picks it up mechanically without further
2012 /// per-consumer edits).
2013 #[must_use]
2014 pub const fn has_teardown_firing_on(&self, phase: ProcessPhase) -> bool {
2015 self.teardown.should_teardown_on(phase)
2016 }
2017
2018 /// Resolve the operator-authored [`Self::classification`] slot to
2019 /// the concrete [`Classification`] the point surface sees, filling
2020 /// `None` through the same [`default_ephemeral_class`] baseline the
2021 /// `From<EphemeralSpec> for ProcessSpec` lowering uses when the
2022 /// operator omits `:classification` from the `(defephemeral …)`
2023 /// form. Returns [`Cow::Borrowed`] on the populated arm (zero
2024 /// allocation), else [`Cow::Owned`] with the workspace-baseline
2025 /// `(Gate, Compute, Bounded, Monotone, Internal)` value the sibling
2026 /// primitive [`Classification::gate_compute`] owns.
2027 ///
2028 /// # ONE substrate primitive for `Option<Classification>` resolution
2029 ///
2030 /// This is the ONE `EphemeralSpec`-inherent primitive that owns the
2031 /// `Option<Classification>` → resolved-[`Classification`] walk.
2032 /// Every downstream classification-axis presence probe on the
2033 /// [`EphemeralSpec`] surface ([`Self::has_point_type`],
2034 /// [`Self::has_substrate`], [`Self::has_calm`],
2035 /// [`Self::has_data_classification`], [`Self::has_horizon_kind`],
2036 /// [`Self::has_optimization_direction`], [`Self::has_input_arity`],
2037 /// [`Self::has_output_arity`]) routes through THIS
2038 /// primitive so the "`None` fills through
2039 /// [`default_ephemeral_class`]" resolution lives at ONE site rather
2040 /// than being restated in each per-axis probe body. A future
2041 /// regression on the fill-through (a shift from the `(Gate,
2042 /// Compute, …)` baseline to a different `default_ephemeral_class`
2043 /// body, a shift from the `Option`-carrier shape to a
2044 /// serde-defaulted required-field carrier, an eventual audit hook
2045 /// naming the resolved-vs-authored provenance) lands at ONE site
2046 /// and every downstream axis-probe on the ephemeral surface picks
2047 /// it up mechanically.
2048 ///
2049 /// # Sibling to the `From<EphemeralSpec>` lowering
2050 ///
2051 /// The lowering `From<EphemeralSpec> for ProcessSpec` fills
2052 /// [`ProcessSpec::classification`] through the SAME
2053 /// `.unwrap_or_else(default_ephemeral_class)` walk that this
2054 /// primitive owns on the borrow-friendly `Cow` return. Both sites
2055 /// resolve the same operator-authored slot through the same default
2056 /// so a future two-surface parity contract on the classification
2057 /// axes (`point-type-<kind>` on both surfaces, `substrate-<kind>`
2058 /// on both surfaces, …) reads identically through the sibling
2059 /// point-surface probe [`Classification::has_<axis>`] on the
2060 /// lowered `ProcessSpec` and through THIS primitive on the same
2061 /// authored [`EphemeralSpec`].
2062 ///
2063 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2064 /// preserves proofs; the `Option<Classification>` resolution body
2065 /// lives at ONE substrate primitive on the ephemeral surface so
2066 /// every downstream classification-axis probe binds through the
2067 /// SAME `resolved_classification()` shape rather than restating
2068 /// the `self.classification.as_ref().unwrap_or(&default_…)`
2069 /// closure body at each callsite. THEORY.md §VI.1 — generation
2070 /// over composition; a future classification-axis peer
2071 /// (`has_substrate`, `has_calm`, …) lands as ONE inherent method
2072 /// that delegates through the resolver's `has_<axis>(kind)` call
2073 /// on the sibling [`Classification`] closed-set primitive with no
2074 /// per-axis restatement of the fill-through logic.
2075 #[must_use]
2076 pub fn resolved_classification(&self) -> Cow<'_, Classification> {
2077 match &self.classification {
2078 Some(c) => Cow::Borrowed(c),
2079 None => Cow::Owned(default_ephemeral_class()),
2080 }
2081 }
2082
2083 /// Overlay a single [`ClassificationAxis`] variant onto this
2084 /// ephemeral spec's authored [`Self::classification`] slot, filling
2085 /// `None` through [`Classification::gate_compute`] before the
2086 /// overlay so the resulting slot carries `Some(_)` regardless of
2087 /// the pre-call state. Fluent chaining primitive: the peer of
2088 /// [`ProcessSpec::gate_compute_with_axis`] (fresh-spec × axis
2089 /// overlay) and [`Classification::with_axis`] (arbitrary-base ×
2090 /// axis overlay) on the ephemeral sugar surface.
2091 ///
2092 /// # Substrate ergonomics
2093 ///
2094 /// Pre-lift the four-line shape `let mut classification =
2095 /// Classification::gate_compute(); classification.<axis> =
2096 /// populated; let spec = EphemeralSpec { classification:
2097 /// Some(classification), ..ephemeral_fixture() };` (and its newer
2098 /// three-line peer `let classification =
2099 /// Classification::gate_compute_with_axis(populated); let spec =
2100 /// EphemeralSpec { classification: Some(classification),
2101 /// ..ephemeral_fixture() };`) recurred at THIRTY-SIX hand-authored
2102 /// callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger
2103 /// inside `tatara-reconciler::bin::tatara-check`'s
2104 /// `evaluate_ephemeral_require_tag_*` classifier-facing test
2105 /// module. Post-lift each callsite reads
2106 /// `let spec = ephemeral_fixture().with_classification_axis(populated);`
2107 /// — one line, one immutable binding, and every per-axis loop
2108 /// dispatches its per-iteration axis mutation through the SAME
2109 /// [`ClassificationAxis::overlay`] trait rather than by directly
2110 /// poking a `classification.<axis>` field or restating the
2111 /// `Some(_)` wrap.
2112 ///
2113 /// # Fluent chaining semantics
2114 ///
2115 /// * `EphemeralSpec { classification: None, .. }
2116 /// .with_classification_axis(axis)` produces
2117 /// `EphemeralSpec { classification:
2118 /// Some(Classification::gate_compute_with_axis(axis)), .. }` —
2119 /// the `None`-arm short-circuit fills through
2120 /// [`Classification::gate_compute`] identically to the sibling
2121 /// [`Self::resolved_classification`] resolver on the read side.
2122 /// * `EphemeralSpec { classification: Some(prior), .. }
2123 /// .with_classification_axis(axis)` produces
2124 /// `EphemeralSpec { classification: Some(prior.with_axis(axis)),
2125 /// .. }` — the axis overlay composes onto the existing carrier
2126 /// via [`ClassificationAxis::overlay`], preserving every other
2127 /// axis slot on `prior`. Chained calls
2128 /// `.with_classification_axis(a).with_classification_axis(b)`
2129 /// compose arbitrary N-axis conjunctions on the ephemeral
2130 /// sugar surface with the same order-independence guarantee
2131 /// [`Classification::with_axis`] carries on distinct-slot axes.
2132 ///
2133 /// # Sibling to [`ProcessSpec::gate_compute_with_axis`]
2134 ///
2135 /// Same (spec-carrier × axis) shape, one refinement lower on
2136 /// the composition-depth axis: `ProcessSpec::gate_compute_with_axis`
2137 /// owns the (fresh-`gate_compute_defaults`-spec × axis-overlay)
2138 /// construction on the point-surface carrier;
2139 /// [`Self::with_classification_axis`] owns the
2140 /// (arbitrary-`EphemeralSpec` × axis-overlay-onto-authored-classification)
2141 /// construction on the ephemeral sugar-surface carrier. Both
2142 /// primitives compose through the SAME
2143 /// [`ClassificationAxis::overlay`] trait so a regression on any
2144 /// axis's overlay surfaces at both composer owners' pin sets
2145 /// simultaneously.
2146 ///
2147 /// # Compounding
2148 ///
2149 /// A future SIXTH classification axis lands as ONE peer
2150 /// `impl ClassificationAxis` — every ephemeral-surface fixture
2151 /// that binds through this primitive picks up the sixth axis
2152 /// mechanically without a `classification.<new-axis> = value;`
2153 /// restatement per site. A future audit dispatcher walking the
2154 /// (ephemeral-surface × axis-loop) shape (per-axis matrix
2155 /// generator, closed-set-sweep sagas, per-axis-XOR-partition-
2156 /// witness synthesis on the ephemeral side) binds through the
2157 /// SAME composer regardless of which axis it targets. Directly
2158 /// benefits the P1 caixa-tatara renderer target
2159 /// (`(defaplicacao …)` → `Process` mechanical lowering test
2160 /// fixtures that construct authored classifications through the
2161 /// ephemeral sugar surface) and future ephemeral-surface XOR-
2162 /// partition landmark tests peer to the point-surface pins in
2163 /// `tatara-check.rs`.
2164 ///
2165 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2166 /// preserves proofs; the [`ClassificationAxis::overlay`] trait
2167 /// owns the axis-dispatch proof at ONE site and this primitive
2168 /// extends the ONE-site guarantee to the (ephemeral-spec ×
2169 /// authored-classification × axis-overlay) construction shape.
2170 /// THEORY.md §VI.1 — generation over composition; the 3-to-4-line
2171 /// hand-authored classification-then-wrap shape recurred at ≥ 36
2172 /// hand-authored callsites past the ★★ PRIME-DIRECTIVE ≥ 2
2173 /// duplication threshold and is lifted onto ONE substrate owner
2174 /// here.
2175 #[must_use]
2176 pub fn with_classification_axis<A: ClassificationAxis>(mut self, axis: A) -> Self {
2177 let mut c = self
2178 .classification
2179 .take()
2180 .unwrap_or_else(Classification::gate_compute);
2181 axis.overlay(&mut c);
2182 self.classification = Some(c);
2183 self
2184 }
2185
2186 /// True iff the resolved [`Classification`] carries the given
2187 /// [`ConvergencePointType`] on its `point_type` slot — byte-for-
2188 /// byte peer of [`Classification::has_point_type`] wrapped through
2189 /// the [`Self::resolved_classification`] resolver so an
2190 /// operator-omitted `:classification` slot reads as the
2191 /// [`default_ephemeral_class`] baseline the sibling
2192 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2193 ///
2194 /// # Two-surface parity contract
2195 ///
2196 /// A given [`EphemeralSpec`] classifies identically through this
2197 /// primitive AND through
2198 /// `<eph.clone().into::<ProcessSpec>>().classification.has_point_type(kind)`
2199 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2200 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2201 /// the lowering side both dereference the same
2202 /// `default_ephemeral_class()` value on `None` and the same
2203 /// authored value on `Some(_)`. This means the ephemeral-surface
2204 /// `point-type-<kind>` `:requires` family in
2205 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2206 /// truth on the SAME authored spec as the point-surface family
2207 /// on the mechanically-lowered `ProcessSpec`.
2208 ///
2209 /// # Sibling to the seven other classification axes
2210 ///
2211 /// FIRST classification-axis peer on the [`EphemeralSpec`]
2212 /// surface. Six future sibling axes on the SAME `Cow`-resolver
2213 /// carrier ([`Self::has_substrate`] opened the SECOND,
2214 /// [`Self::has_calm`] the THIRD,
2215 /// [`Self::has_data_classification`] the FOURTH,
2216 /// [`Self::has_horizon_kind`] the FIFTH,
2217 /// [`Self::has_optimization_direction`] the SIXTH; then
2218 /// `has_input_arity`, `has_output_arity`) land as one-line
2219 /// wrappers around the SAME resolver + the sibling
2220 /// [`Classification`] closed-set primitive, so a future variant
2221 /// added to [`ConvergencePointType`] (or any of the seven other
2222 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2223 /// families through the SAME closed-set walk with no per-caller
2224 /// edit.
2225 ///
2226 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2227 /// preserves proofs; the classification-axis presence-probe body
2228 /// composes ONE resolver primitive
2229 /// ([`Self::resolved_classification`]) with ONE closed-set
2230 /// primitive ([`Classification::has_point_type`]) so every
2231 /// downstream (`point-type-<kind>` require-tag families on both
2232 /// surfaces in tatara-check, closed-set audit dispatchers, future
2233 /// variant additions on [`ConvergencePointType`]) binds through
2234 /// the SAME `has(kind)` shape rather than restating either the
2235 /// resolver walk or the closed-set equality at the callsite.
2236 #[must_use]
2237 pub fn has_point_type(&self, kind: ConvergencePointType) -> bool {
2238 self.resolved_classification().has_point_type(kind)
2239 }
2240
2241 /// True iff the resolved [`Classification`] carries the given
2242 /// [`SubstrateType`] on its `substrate` slot — byte-for-byte peer
2243 /// of [`Classification::has_substrate`] wrapped through the
2244 /// [`Self::resolved_classification`] resolver so an operator-
2245 /// omitted `:classification` slot reads as the
2246 /// [`default_ephemeral_class`] baseline the sibling
2247 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2248 ///
2249 /// # Two-surface parity contract
2250 ///
2251 /// A given [`EphemeralSpec`] classifies identically through this
2252 /// primitive AND through
2253 /// `<eph.clone().into::<ProcessSpec>>().classification.has_substrate(kind)`
2254 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2255 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2256 /// the lowering side both dereference the same
2257 /// `default_ephemeral_class()` value on `None` and the same
2258 /// authored value on `Some(_)`. This means the ephemeral-surface
2259 /// `substrate-<kind>` `:requires` family in
2260 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2261 /// truth on the SAME authored spec as the point-surface family
2262 /// on the mechanically-lowered `ProcessSpec`.
2263 ///
2264 /// # SECOND classification-axis peer on the ephemeral surface
2265 ///
2266 /// Peer of [`Self::has_point_type`] — both route through the SAME
2267 /// [`Self::resolved_classification`] resolver, so the operator-
2268 /// omitted `:classification` slot's fill-through logic lives at
2269 /// ONE substrate primitive rather than being restated in each
2270 /// per-axis probe body. Five future sibling axes on the SAME
2271 /// `Cow`-resolver carrier ([`Self::has_calm`] opened the THIRD,
2272 /// [`Self::has_data_classification`] the FOURTH,
2273 /// [`Self::has_horizon_kind`] the FIFTH,
2274 /// [`Self::has_optimization_direction`] the SIXTH; then
2275 /// `has_input_arity`, `has_output_arity`) land as one-line
2276 /// wrappers around the SAME resolver + the sibling
2277 /// [`Classification`] closed-set primitive, so a future variant
2278 /// added to [`SubstrateType`] (or any of the six other closed
2279 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
2280 /// through the SAME closed-set walk with no per-caller edit.
2281 ///
2282 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2283 /// preserves proofs; the classification-axis presence-probe body
2284 /// composes ONE resolver primitive
2285 /// ([`Self::resolved_classification`]) with ONE closed-set
2286 /// primitive ([`Classification::has_substrate`]) so every
2287 /// downstream (`substrate-<kind>` require-tag families on both
2288 /// surfaces in tatara-check, closed-set audit dispatchers, future
2289 /// variant additions on [`SubstrateType`]) binds through the
2290 /// SAME `has(kind)` shape rather than restating either the
2291 /// resolver walk or the closed-set equality at the callsite.
2292 #[must_use]
2293 pub fn has_substrate(&self, kind: SubstrateType) -> bool {
2294 self.resolved_classification().has_substrate(kind)
2295 }
2296
2297 /// True iff the resolved [`Classification`] carries the given
2298 /// [`CalmClassification`] on its `calm` slot — byte-for-byte peer
2299 /// of [`Classification::has_calm`] wrapped through the
2300 /// [`Self::resolved_classification`] resolver so an operator-
2301 /// omitted `:classification` slot reads as the
2302 /// [`default_ephemeral_class`] baseline the sibling
2303 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2304 ///
2305 /// # Two-surface parity contract
2306 ///
2307 /// A given [`EphemeralSpec`] classifies identically through this
2308 /// primitive AND through
2309 /// `<eph.clone().into::<ProcessSpec>>().classification.has_calm(kind)`
2310 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2311 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2312 /// the lowering side both dereference the same
2313 /// `default_ephemeral_class()` value on `None` and the same
2314 /// authored value on `Some(_)`. This means the ephemeral-surface
2315 /// `calm-<kind>` `:requires` family in
2316 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2317 /// truth on the SAME authored spec as the point-surface family
2318 /// on the mechanically-lowered `ProcessSpec`.
2319 ///
2320 /// # THIRD classification-axis peer on the ephemeral surface
2321 ///
2322 /// Peer of [`Self::has_point_type`] and [`Self::has_substrate`] —
2323 /// all three route through the SAME
2324 /// [`Self::resolved_classification`] resolver, so the operator-
2325 /// omitted `:classification` slot's fill-through logic lives at
2326 /// ONE substrate primitive rather than being restated in each
2327 /// per-axis probe body. FIRST occupant on the (Option-parent ×
2328 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
2329 /// of the ephemeral-surface presence-probe algebra — distinct
2330 /// from the (Option-parent × NON-DEFAULT-scalar-child) corner
2331 /// the first two classification-axis peers opened, since
2332 /// [`CalmClassification`] carries `#[default] = Monotone` on the
2333 /// closed set. The default-arm short-circuit on the absent-
2334 /// classification arm reads `true` on the [`CalmClassification`]
2335 /// child's `#[default]` variant precisely because BOTH the parent
2336 /// Option's fill-through baseline (`default_ephemeral_class`) AND
2337 /// the child's own `#[default]` land on the SAME variant
2338 /// ([`CalmClassification::Monotone`]) — a two-defaults
2339 /// composition property distinct from the NON-DEFAULT-scalar
2340 /// peers, whose absent-classification arm defaults through a
2341 /// specific chosen baseline (`ConvergencePointType::Gate`,
2342 /// `SubstrateType::Compute`) rather than through the child's own
2343 /// `#[default]`. Four future sibling axes on the SAME
2344 /// `Cow`-resolver carrier ([`Self::has_data_classification`]
2345 /// opened the FOURTH, [`Self::has_horizon_kind`] the FIFTH,
2346 /// [`Self::has_optimization_direction`] the SIXTH; then
2347 /// `has_input_arity`, `has_output_arity`) land as one-line
2348 /// wrappers around the SAME resolver + the sibling
2349 /// [`Classification`] closed-set primitive, so a future variant
2350 /// added to [`CalmClassification`] (or any of the five other
2351 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2352 /// families through the SAME closed-set walk with no per-caller
2353 /// edit.
2354 ///
2355 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2356 /// preserves proofs; the classification-axis presence-probe body
2357 /// composes ONE resolver primitive
2358 /// ([`Self::resolved_classification`]) with ONE closed-set
2359 /// primitive ([`Classification::has_calm`]) so every downstream
2360 /// (`calm-<kind>` require-tag families on both surfaces in
2361 /// tatara-check, closed-set audit dispatchers, future variant
2362 /// additions on [`CalmClassification`]) binds through the SAME
2363 /// `has(kind)` shape rather than restating either the resolver
2364 /// walk or the closed-set equality at the callsite.
2365 #[must_use]
2366 pub fn has_calm(&self, kind: CalmClassification) -> bool {
2367 self.resolved_classification().has_calm(kind)
2368 }
2369
2370 /// True iff the resolved [`Classification`] carries the given
2371 /// [`DataClassification`] on its `data_classification` slot —
2372 /// byte-for-byte peer of [`Classification::has_data_classification`]
2373 /// wrapped through the [`Self::resolved_classification`] resolver
2374 /// so an operator-omitted `:classification` slot reads as the
2375 /// [`default_ephemeral_class`] baseline the sibling
2376 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2377 ///
2378 /// # Two-surface parity contract
2379 ///
2380 /// A given [`EphemeralSpec`] classifies identically through this
2381 /// primitive AND through
2382 /// `<eph.clone().into::<ProcessSpec>>().classification.has_data_classification(kind)`
2383 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2384 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2385 /// the lowering side both dereference the same
2386 /// `default_ephemeral_class()` value on `None` and the same
2387 /// authored value on `Some(_)`. This means the ephemeral-surface
2388 /// `data-classification-<kind>` `:requires` family in
2389 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2390 /// truth on the SAME authored spec as the point-surface family
2391 /// on the mechanically-lowered `ProcessSpec`.
2392 ///
2393 /// # FOURTH classification-axis peer on the ephemeral surface
2394 ///
2395 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`], and
2396 /// [`Self::has_calm`] — all four route through the SAME
2397 /// [`Self::resolved_classification`] resolver, so the operator-
2398 /// omitted `:classification` slot's fill-through logic lives at
2399 /// ONE substrate primitive rather than being restated in each
2400 /// per-axis probe body. SECOND occupant on the (Option-parent ×
2401 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
2402 /// of the ephemeral-surface presence-probe algebra alongside
2403 /// [`Self::has_calm`] — both probe REQUIRED [`Classification`]
2404 /// sub-slots whose child closed set carries its own `#[default]`
2405 /// ([`DataClassification::Internal`] here,
2406 /// [`CalmClassification::Monotone`] on the peer), so the
2407 /// default-arm short-circuit on the absent-classification arm
2408 /// reads `true` on the [`DataClassification`] child's
2409 /// `#[default]` variant precisely because BOTH the parent
2410 /// Option's fill-through baseline (`default_ephemeral_class`)
2411 /// AND the child's own `#[default]` land on the SAME variant
2412 /// ([`DataClassification::Internal`]). The two-defaults
2413 /// composition property now walks TWO independent defaulted-
2414 /// scalar-child slots on the SAME ephemeral resolver — a
2415 /// regression that promoted a different [`DataClassification`]
2416 /// variant to `#[default]` (or wired the arm to a fixed variant
2417 /// answer) fails HERE at ONE narrow substrate site before
2418 /// drifting through every unadorned ephemeral spec's baseline
2419 /// data-classification answer. Distinct from the FIRST + SECOND
2420 /// peers on the (Option-parent × NON-DEFAULT-scalar-child)
2421 /// corner, whose absent-classification arm defaults through a
2422 /// specific chosen baseline (`ConvergencePointType::Gate`,
2423 /// `SubstrateType::Compute`) rather than through the child's own
2424 /// `#[default]`. Four future sibling axes on the SAME
2425 /// `Cow`-resolver carrier ([`Self::has_horizon_kind`] opened the
2426 /// FIFTH, [`Self::has_optimization_direction`] the SIXTH; then
2427 /// `has_input_arity`, `has_output_arity`) land as one-line
2428 /// wrappers around the SAME resolver + the sibling
2429 /// [`Classification`] closed-set primitive, so a future variant
2430 /// added to [`DataClassification`] (or any of the four other
2431 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2432 /// families through the SAME closed-set walk with no per-caller
2433 /// edit.
2434 ///
2435 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2436 /// preserves proofs; the classification-axis presence-probe body
2437 /// composes ONE resolver primitive
2438 /// ([`Self::resolved_classification`]) with ONE closed-set
2439 /// primitive ([`Classification::has_data_classification`]) so
2440 /// every downstream (`data-classification-<kind>` require-tag
2441 /// families on both surfaces in tatara-check, closed-set audit
2442 /// dispatchers, future variant additions on
2443 /// [`DataClassification`]) binds through the SAME `has(kind)`
2444 /// shape rather than restating either the resolver walk or the
2445 /// closed-set equality at the callsite.
2446 #[must_use]
2447 pub fn has_data_classification(&self, kind: DataClassification) -> bool {
2448 self.resolved_classification().has_data_classification(kind)
2449 }
2450
2451 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
2452 /// carries the given [`HorizonKind`] discriminator on its
2453 /// `horizon.kind` slot — byte-for-byte peer of
2454 /// [`Classification::has_horizon_kind`] wrapped through the
2455 /// [`Self::resolved_classification`] resolver so an operator-
2456 /// omitted `:classification` slot reads as the
2457 /// [`default_ephemeral_class`] baseline the sibling
2458 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2459 ///
2460 /// # Two-surface parity contract
2461 ///
2462 /// A given [`EphemeralSpec`] classifies identically through this
2463 /// primitive AND through
2464 /// `<eph.clone().into::<ProcessSpec>>().classification.has_horizon_kind(kind)`
2465 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2466 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2467 /// the lowering side both dereference the same
2468 /// `default_ephemeral_class()` value on `None` and the same
2469 /// authored value on `Some(_)`. This means the ephemeral-surface
2470 /// `horizon-<kind>` `:requires` family in
2471 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2472 /// truth on the SAME authored spec as the point-surface family
2473 /// on the mechanically-lowered `ProcessSpec`.
2474 ///
2475 /// # FIFTH classification-axis peer on the ephemeral surface
2476 ///
2477 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2478 /// [`Self::has_calm`], and [`Self::has_data_classification`] — all
2479 /// five route through the SAME [`Self::resolved_classification`]
2480 /// resolver, so the operator-omitted `:classification` slot's
2481 /// fill-through logic lives at ONE substrate primitive rather
2482 /// than being restated in each per-axis probe body. OPENS a fresh
2483 /// (Option-parent × NESTED-STRUCT-scalar-child ×
2484 /// operator-resolvable-baseline) corner on the ephemeral-surface
2485 /// presence-probe algebra — the four prior peers on this surface
2486 /// all read the closed-set discriminator DIRECTLY off a scalar
2487 /// [`Classification`] slot (`point_type`, `substrate`, `calm`,
2488 /// `data_classification`); this probe instead threads through a
2489 /// NESTED-STRUCT intermediary ([`Horizon`], the defaulted nested
2490 /// struct owning the `horizon` axis) to reach a scalar
2491 /// [`HorizonKind`] discriminator on `horizon.kind`. The
2492 /// default-arm short-circuit on the absent-classification arm
2493 /// reads `true` on the [`HorizonKind`] child's `#[default]`
2494 /// variant precisely because BOTH the parent Option's fill-
2495 /// through baseline ([`default_ephemeral_class`], which fills
2496 /// `horizon: Horizon::default()`) AND the child's own `#[default]`
2497 /// land on the SAME variant ([`HorizonKind::Bounded`]). A
2498 /// regression that dropped `#[default]` on [`HorizonKind`], or
2499 /// promoted `Asymptotic` to `#[default]`, or wired the arm to a
2500 /// fixed variant answer, or crossed the wires through the wrong
2501 /// nested struct fails HERE at ONE narrow substrate site before
2502 /// drifting through every unadorned ephemeral spec's baseline
2503 /// horizon answer. Distinct from the FIRST + SECOND peers on the
2504 /// (Option-parent × NON-DEFAULT-scalar-child) corner
2505 /// (`has_point_type`, `has_substrate`) whose absent-classification
2506 /// arm defaults through a specific chosen baseline
2507 /// (`ConvergencePointType::Gate`, `SubstrateType::Compute`), AND
2508 /// distinct from the THIRD + FOURTH peers on the (Option-parent ×
2509 /// DEFAULTED-scalar-child) corner (`has_calm`,
2510 /// `has_data_classification`) which reach a defaulted scalar
2511 /// DIRECTLY off the parent without a nested-struct hop. Three
2512 /// future sibling axes on the SAME `Cow`-resolver carrier
2513 /// ([`Self::has_optimization_direction`] opened the SIXTH; then
2514 /// `has_input_arity`, `has_output_arity`) land as one-line
2515 /// wrappers around the SAME resolver + the sibling
2516 /// [`Classification`] closed-set primitive, so a future variant
2517 /// added to [`HorizonKind`] (or any of the three other closed
2518 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
2519 /// through the SAME closed-set walk with no per-caller edit.
2520 ///
2521 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2522 /// preserves proofs; the classification-axis presence-probe body
2523 /// composes ONE resolver primitive
2524 /// ([`Self::resolved_classification`]) with ONE closed-set
2525 /// primitive ([`Classification::has_horizon_kind`]) so every
2526 /// downstream (`horizon-<kind>` require-tag families on both
2527 /// surfaces in tatara-check, closed-set audit dispatchers, future
2528 /// variant additions on [`HorizonKind`]) binds through the SAME
2529 /// `has(kind)` shape rather than restating either the resolver
2530 /// walk or the closed-set equality at the callsite.
2531 #[must_use]
2532 pub fn has_horizon_kind(&self, kind: HorizonKind) -> bool {
2533 self.resolved_classification().has_horizon_kind(kind)
2534 }
2535
2536 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
2537 /// carries the given [`OptimizationDirection`] discriminator on its
2538 /// `horizon.direction` slot (with the substrate
2539 /// `Option::unwrap_or_default` treating `None` as the closed set's
2540 /// `#[default] Minimize`) — byte-for-byte peer of
2541 /// [`Classification::has_optimization_direction`] wrapped through
2542 /// the [`Self::resolved_classification`] resolver so an operator-
2543 /// omitted `:classification` slot reads as the
2544 /// [`default_ephemeral_class`] baseline the sibling
2545 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2546 ///
2547 /// # Two-surface parity contract
2548 ///
2549 /// A given [`EphemeralSpec`] classifies identically through this
2550 /// primitive AND through
2551 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
2552 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2553 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2554 /// the lowering side both dereference the same
2555 /// `default_ephemeral_class()` value on `None` and the same
2556 /// authored value on `Some(_)`, and the sibling
2557 /// [`Classification::has_optimization_direction`] applies the same
2558 /// `Option::unwrap_or_default` collapse on the inner
2559 /// `horizon.direction` slot on both sides. This means the
2560 /// ephemeral-surface `optimization-direction-<kind>` `:requires`
2561 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2562 /// SAME truth on the SAME authored spec as the point-surface
2563 /// family on the mechanically-lowered `ProcessSpec`.
2564 ///
2565 /// # SIXTH classification-axis peer on the ephemeral surface
2566 ///
2567 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2568 /// [`Self::has_calm`], [`Self::has_data_classification`], and
2569 /// [`Self::has_horizon_kind`] — all six route through the SAME
2570 /// [`Self::resolved_classification`] resolver, so the operator-
2571 /// omitted `:classification` slot's fill-through logic lives at
2572 /// ONE substrate primitive rather than being restated in each per-
2573 /// axis probe body. SECOND occupant on the (Option-parent ×
2574 /// NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
2575 /// corner alongside [`Self::has_horizon_kind`] — both probes thread
2576 /// through the SAME nested [`Horizon`] intermediary to reach a
2577 /// scalar discriminator on the six-axis classification lattice, but
2578 /// this method additionally traverses an `Option`-slot with
2579 /// `unwrap_or_default` so a Process filled through
2580 /// [`crate::classification::Horizon::default`] (leaves `direction:
2581 /// None`) still reads `true` on the closed set's default arm
2582 /// ([`OptimizationDirection::Minimize`]). The corner therefore
2583 /// admits BOTH direct nested-scalar shapes ([`Self::has_horizon_kind`]
2584 /// walks `horizon.kind: HorizonKind` directly) AND Option-nested-
2585 /// scalar shapes (this method walks `horizon.direction:
2586 /// Option<OptimizationDirection>` through `unwrap_or_default`),
2587 /// pinning the corner as a proven-repeatable primitive shape on the
2588 /// ephemeral surface rather than a single-example curiosity. The
2589 /// two-defaults composition property (parent Option's fill-through
2590 /// baseline via `default_ephemeral_class` AND child's closed-set
2591 /// `#[default]` land on the SAME variant) reaches through TWO
2592 /// hops here: the parent Option's `.unwrap_or_else(default_…)`
2593 /// AND the inner Option's `.unwrap_or_default()` both dereference
2594 /// to the same [`OptimizationDirection::Minimize`] baseline the
2595 /// closed set publishes. A regression that flipped
2596 /// [`OptimizationDirection`]'s `#[default]` off `Minimize` (which
2597 /// would silently invert every unadorned `Asymptotic` Process's
2598 /// rate-window evaluator polarity), or that dropped the resolver
2599 /// hop, or that wired the arm to a fixed variant answer, fails
2600 /// HERE at ONE narrow substrate site before drifting through every
2601 /// unadorned ephemeral spec's baseline direction answer. Two future
2602 /// sibling axes on the SAME `Cow`-resolver carrier
2603 /// (`has_input_arity`, `has_output_arity`) land as one-line
2604 /// wrappers around the SAME resolver + the sibling
2605 /// [`Classification`] closed-set primitive, so a future variant
2606 /// added to [`OptimizationDirection`] (or any of the two other
2607 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2608 /// families through the SAME closed-set walk with no per-caller
2609 /// edit.
2610 ///
2611 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2612 /// preserves proofs; the classification-axis presence-probe body
2613 /// composes ONE resolver primitive
2614 /// ([`Self::resolved_classification`]) with ONE closed-set
2615 /// primitive ([`Classification::has_optimization_direction`]) so
2616 /// every downstream (`optimization-direction-<kind>` require-tag
2617 /// families on both surfaces in tatara-check, closed-set audit
2618 /// dispatchers, future variant additions on
2619 /// [`OptimizationDirection`]) binds through the SAME `has(kind)`
2620 /// shape rather than restating either the resolver walk or the
2621 /// closed-set equality plus the nested-struct-Option-hop at the
2622 /// callsite.
2623 #[must_use]
2624 pub fn has_optimization_direction(&self, kind: OptimizationDirection) -> bool {
2625 self.resolved_classification()
2626 .has_optimization_direction(kind)
2627 }
2628
2629 /// True iff the resolved [`Classification`]'s nested
2630 /// [`ConvergencePointType`] projects (via the many-to-one
2631 /// [`ConvergencePointType::input_arity`] typed projection) to the
2632 /// given [`Arity`] discriminator — byte-for-byte peer of
2633 /// [`Classification::has_input_arity`] wrapped through the
2634 /// [`Self::resolved_classification`] resolver so an operator-omitted
2635 /// `:classification` slot reads as the [`default_ephemeral_class`]
2636 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
2637 /// lowering fills.
2638 ///
2639 /// # Two-surface parity contract
2640 ///
2641 /// A given [`EphemeralSpec`] classifies identically through this
2642 /// primitive AND through
2643 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
2644 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2645 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
2646 /// lowering side both dereference the same
2647 /// `default_ephemeral_class()` value on `None` and the same
2648 /// authored value on `Some(_)`, and the sibling
2649 /// [`Classification::has_input_arity`] applies the same
2650 /// `point_type.input_arity()` typed projection on both sides. This
2651 /// means the ephemeral-surface `input-arity-<kind>` `:requires`
2652 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2653 /// SAME truth on the SAME authored spec as the point-surface family
2654 /// on the mechanically-lowered `ProcessSpec`.
2655 ///
2656 /// # SEVENTH classification-axis peer on the ephemeral surface — first via a derived-typed-projection
2657 ///
2658 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2659 /// [`Self::has_calm`], [`Self::has_data_classification`],
2660 /// [`Self::has_horizon_kind`], and
2661 /// [`Self::has_optimization_direction`] — all seven route through
2662 /// the SAME [`Self::resolved_classification`] resolver, so the
2663 /// operator-omitted `:classification` slot's fill-through logic
2664 /// lives at ONE substrate primitive rather than being restated in
2665 /// each per-axis probe body. FIRST occupant on the (Option-parent ×
2666 /// NESTED-STRUCT-scalar-child × derived-typed-projection) corner on
2667 /// the ephemeral surface — byte-for-byte symmetric with the
2668 /// derived-typed-projection precedent set by
2669 /// [`Classification::has_input_arity`] on the point surface: THAT
2670 /// peer routes through [`ConvergencePointType::input_arity`] on a
2671 /// required [`Classification`] carrier; THIS peer routes through the
2672 /// SAME projection on the `Cow`-resolver carrier so the resolver
2673 /// walk composes with the projection at ONE substrate site rather
2674 /// than being restated per surface. Distinct from the SIXTH peer
2675 /// [`Self::has_optimization_direction`] (which walks
2676 /// `horizon.direction` through an `Option::unwrap_or_default`
2677 /// collapse to reach a defaulted scalar child) and the FIFTH peer
2678 /// [`Self::has_horizon_kind`] (which walks `horizon.kind` DIRECTLY
2679 /// as a scalar without any typed-projection hop) on ONE dimension:
2680 /// this probe threads through the many-to-one closed-set typed
2681 /// projection [`ConvergencePointType::input_arity`] (`Transform |
2682 /// Fork | Broadcast | Observe → One`, `Join | Gate | Select |
2683 /// Reduce → Many`) so the child's closed set ([`Arity`]) is REACHED
2684 /// THROUGH a projection layer, not read raw off a scalar. The
2685 /// corner therefore admits three ephemeral-surface traversal
2686 /// shapes through the SAME `resolved_classification().<field>`
2687 /// walk: direct-nested-scalar
2688 /// ([`Self::has_horizon_kind`] reads `horizon.kind: HorizonKind`
2689 /// directly), Option-nested-scalar
2690 /// ([`Self::has_optimization_direction`] reads `horizon.direction:
2691 /// Option<OptimizationDirection>` through `unwrap_or_default`), and
2692 /// derived-typed-projection (this method reads
2693 /// `point_type.input_arity(): Arity` through a many-to-one
2694 /// projection). The co-tenant derived-typed-projection axis on the
2695 /// SAME `Cow`-resolver carrier ([`Self::has_output_arity`]) lands as
2696 /// a one-line wrapper around the SAME resolver + the sibling
2697 /// [`Classification`] closed-set primitive, so a future variant
2698 /// added to [`Arity`] or to [`ConvergencePointType`] reaches BOTH
2699 /// surfaces' `<axis>-<kind>` prefix families through the SAME
2700 /// closed-set walk with no per-caller edit.
2701 ///
2702 /// # Semantics — VARIANT match on the projected image
2703 ///
2704 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
2705 /// `#[default]`), so exactly ONE of the two arms answers `true` per
2706 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
2707 /// shortcut. The absent-`:classification` baseline
2708 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
2709 /// [`ConvergencePointType::input_arity`] projects `Gate → Many`, so
2710 /// the ephemeral sugar surface's `input-arity-Many` require-tag
2711 /// reads `true` on every operator-authored spec that omits the
2712 /// `:classification` slot — pinning the workspace's convergent-by-
2713 /// default point posture on the input side. The many-to-one
2714 /// projection shape means the answer is invariant under intra-
2715 /// bucket point-type swaps (`Transform ↔ Fork ↔ Broadcast ↔
2716 /// Observe` all keep `input-arity-One = true`) and flips at bucket
2717 /// boundaries (`Transform ↔ Join` flips `input-arity-One` from
2718 /// `true` to `false`). A regression that dropped the resolver hop,
2719 /// probed [`ConvergencePointType`] directly (dropping the
2720 /// `.input_arity()` call), inverted the projection (`One ↔ Many`),
2721 /// or crossed the wires with the sibling
2722 /// [`ConvergencePointType::output_arity`] projection fails HERE at
2723 /// ONE narrow substrate site before drifting through every
2724 /// unadorned ephemeral spec's baseline input-arity answer.
2725 ///
2726 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2727 /// preserves proofs; the classification-axis presence-probe body
2728 /// composes ONE resolver primitive
2729 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
2730 /// ([`Classification::has_input_arity`]) so every downstream
2731 /// (`input-arity-<kind>` require-tag families on both surfaces in
2732 /// tatara-check, closed-set audit dispatchers, future variant
2733 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
2734 /// through the SAME `has(kind)` shape rather than restating either
2735 /// the resolver walk or the closed-set equality plus the typed-
2736 /// projection hop at the callsite.
2737 #[must_use]
2738 pub fn has_input_arity(&self, kind: Arity) -> bool {
2739 self.resolved_classification().has_input_arity(kind)
2740 }
2741
2742 /// True iff the resolved [`Classification`]'s nested
2743 /// [`ConvergencePointType`] projects (via the many-to-one
2744 /// [`ConvergencePointType::output_arity`] typed projection) to the
2745 /// given [`Arity`] discriminator — byte-for-byte peer of
2746 /// [`Classification::has_output_arity`] wrapped through the
2747 /// [`Self::resolved_classification`] resolver so an operator-omitted
2748 /// `:classification` slot reads as the [`default_ephemeral_class`]
2749 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
2750 /// lowering fills.
2751 ///
2752 /// # Two-surface parity contract
2753 ///
2754 /// A given [`EphemeralSpec`] classifies identically through this
2755 /// primitive AND through
2756 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
2757 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2758 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
2759 /// lowering side both dereference the same
2760 /// `default_ephemeral_class()` value on `None` and the same
2761 /// authored value on `Some(_)`, and the sibling
2762 /// [`Classification::has_output_arity`] applies the same
2763 /// `point_type.output_arity()` typed projection on both sides. This
2764 /// means the ephemeral-surface `output-arity-<kind>` `:requires`
2765 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2766 /// SAME truth on the SAME authored spec as the point-surface family
2767 /// on the mechanically-lowered `ProcessSpec`.
2768 ///
2769 /// # EIGHTH classification-axis peer — closes the ephemeral-side DAG-composition arity pair
2770 ///
2771 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2772 /// [`Self::has_calm`], [`Self::has_data_classification`],
2773 /// [`Self::has_horizon_kind`], [`Self::has_optimization_direction`],
2774 /// and [`Self::has_input_arity`] — all eight route through the SAME
2775 /// [`Self::resolved_classification`] resolver, so the operator-
2776 /// omitted `:classification` slot's fill-through logic lives at ONE
2777 /// substrate primitive rather than being restated in each per-axis
2778 /// probe body. SECOND occupant on the (Option-parent × NESTED-
2779 /// STRUCT-scalar-child × derived-typed-projection) corner on the
2780 /// ephemeral surface — co-tenant with [`Self::has_input_arity`] on
2781 /// the SAME `point_type` scalar carrier through the SAME [`Arity`]
2782 /// closed set but through the sibling many-to-one typed projection
2783 /// [`ConvergencePointType::output_arity`] (`Transform | Join | Gate
2784 /// | Select | Reduce | Observe → One`, `Fork | Broadcast → Many`).
2785 /// Closes the DAG-composition arity pair on the ephemeral side —
2786 /// the two projections DISAGREE on the diffusive arms `Fork |
2787 /// Broadcast` (input `One` vs. output `Many`) and on the convergent
2788 /// arms `Join | Gate | Select | Reduce` (input `Many` vs. output
2789 /// `One`), and AGREE on the endomorphic arms `Transform | Observe`
2790 /// (both `One`). Byte-for-byte symmetric with the DAG-composition
2791 /// arity pair on the point surface ([`Classification::has_input_arity`] +
2792 /// [`Classification::has_output_arity`]) — THAT pair walks a required
2793 /// [`Classification`] carrier; THIS pair walks the SAME projection
2794 /// pair on the `Cow`-resolver carrier so the resolver walk composes
2795 /// with the projection at ONE substrate site rather than being
2796 /// restated per surface.
2797 ///
2798 /// # Semantics — VARIANT match on the projected image
2799 ///
2800 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
2801 /// `#[default]`), so exactly ONE of the two arms answers `true` per
2802 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
2803 /// shortcut. The absent-`:classification` baseline
2804 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
2805 /// [`ConvergencePointType::output_arity`] projects `Gate → One`, so
2806 /// the ephemeral sugar surface's `output-arity-One` require-tag
2807 /// reads `true` on every operator-authored spec that omits the
2808 /// `:classification` slot — pinning the workspace's convergent-by-
2809 /// default point posture on the output side. The many-to-one
2810 /// projection shape means the answer is invariant under intra-
2811 /// bucket point-type swaps (`Fork ↔ Broadcast` both keep
2812 /// `output-arity-Many = true`; `Transform ↔ Join ↔ Gate ↔ Select ↔
2813 /// Reduce ↔ Observe` all keep `output-arity-One = true`) and flips
2814 /// at bucket boundaries (`Fork ↔ Transform` flips `output-arity-
2815 /// Many` from `true` to `false`). A regression that dropped the
2816 /// resolver hop, probed [`ConvergencePointType`] directly (dropping
2817 /// the `.output_arity()` call), inverted the projection (`One ↔
2818 /// Many`), or crossed the wires with the sibling
2819 /// [`ConvergencePointType::input_arity`] projection fails HERE at
2820 /// ONE narrow substrate site before drifting through every
2821 /// unadorned ephemeral spec's baseline output-arity answer.
2822 ///
2823 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2824 /// preserves proofs; the classification-axis presence-probe body
2825 /// composes ONE resolver primitive
2826 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
2827 /// ([`Classification::has_output_arity`]) so every downstream
2828 /// (`output-arity-<kind>` require-tag families on both surfaces in
2829 /// tatara-check, closed-set audit dispatchers, future variant
2830 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
2831 /// through the SAME `has(kind)` shape rather than restating either
2832 /// the resolver walk or the closed-set equality plus the typed-
2833 /// projection hop at the callsite.
2834 #[must_use]
2835 pub fn has_output_arity(&self, kind: Arity) -> bool {
2836 self.resolved_classification().has_output_arity(kind)
2837 }
2838
2839 /// Derived-boolean predicate — does this ephemeral spec's
2840 /// resolved [`Classification`]'s [`Horizon`] project to `true`
2841 /// under [`crate::classification::HorizonKind::terminates`]?
2842 /// Byte-for-byte peer of
2843 /// [`Classification::horizon_terminates`] wrapped through the
2844 /// [`Self::resolved_classification`] resolver so an operator-
2845 /// omitted `:classification` slot on `(defephemeral …)` still
2846 /// answers via the substrate default. The ONE ephemeral-surface
2847 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2848 /// derived-nullary-boolean walk on the classification-horizon
2849 /// axis.
2850 ///
2851 /// # Two-surface parity — resolver hop + Classification primitive
2852 ///
2853 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2854 /// [`Self::has_calm`], [`Self::has_data_classification`],
2855 /// [`Self::has_horizon_kind`],
2856 /// [`Self::has_optimization_direction`],
2857 /// [`Self::has_input_arity`], and [`Self::has_output_arity`] on
2858 /// the (resolver-hop × [`Classification`] presence primitive)
2859 /// axis: all nine methods route through the SAME
2860 /// [`Self::resolved_classification`] resolver, and each composes
2861 /// against ONE [`Classification`] primitive. This method
2862 /// distinguishes itself by targeting the [`Classification`]
2863 /// primitive [`Classification::horizon_terminates`] which is the
2864 /// FIRST derived-nullary-boolean (no closed-set argument)
2865 /// primitive on the [`Classification`] surface — every prior
2866 /// peer probe on [`Classification`] admits a closed-set `kind`
2867 /// argument and answers a variant-equality question, while this
2868 /// probe collapses [`HorizonKind::ALL`] onto a single boolean
2869 /// via the closed set's own [`HorizonKind::terminates`]
2870 /// predicate.
2871 ///
2872 /// # Semantics — resolver hop + derived-nullary-boolean
2873 ///
2874 /// `horizon_terminates()` returns `true` iff
2875 /// `self.resolved_classification().horizon_terminates()`. The
2876 /// resolver returns the authored [`Classification`] when
2877 /// present and the substrate default
2878 /// [`Classification::gate_compute`] on absence. Because
2879 /// [`Classification::gate_compute`] uses [`Horizon::default`]
2880 /// (whose `kind` field defaults to [`HorizonKind::Bounded`] via
2881 /// `#[default]`), a bare ephemeral spec with no `:classification`
2882 /// slot answers `true` — the default-arm short-circuit
2883 /// propagates through THREE layers of `Default`
2884 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
2885 /// [`HorizonKind::default`]) to this predicate's answer, matching
2886 /// the default-arm shortcut every prior defaulted-child probe
2887 /// on this surface publishes. A regression that dropped the
2888 /// resolver hop, probed [`Classification::has_horizon_kind`]
2889 /// directly (dropping the `.terminates()` projection), or
2890 /// crossed the wires with the antisymmetric partner
2891 /// [`HorizonKind::requires_metric_axes`] fails HERE at ONE
2892 /// narrow substrate site before drifting through every
2893 /// unadorned ephemeral spec's baseline horizon-terminates
2894 /// answer.
2895 ///
2896 /// # Compounding
2897 ///
2898 /// The ephemeral require-tag classifier composes this primitive
2899 /// as a fixed tag `terminating-horizon` on
2900 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2901 /// surface's `terminating-horizon` fixed tag on
2902 /// `POINT_FIXED_TAG_ARMS` via [`Classification::horizon_terminates`]
2903 /// directly. The two-surface parity contract holds by
2904 /// construction: both surfaces route through the SAME
2905 /// [`Classification::horizon_terminates`] primitive after the
2906 /// ephemeral surface pays ONE resolver hop — a future
2907 /// [`HorizonKind`] variant or a future normalization at the
2908 /// substrate primitive lands at ONE site and both surfaces'
2909 /// `terminating-horizon` fixed tags inherit the shift
2910 /// mechanically. A future co-tenant peer on this surface (a
2911 /// hypothetical `horizon_requires_metric_axes` composing the
2912 /// antisymmetric partner [`HorizonKind::requires_metric_axes`]
2913 /// through the SAME resolver hop) lands as ONE peer inherent
2914 /// method with the same nullary-derived body.
2915 ///
2916 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2917 /// preserves proofs; the classification-axis derived-nullary-
2918 /// boolean probe body composes ONE resolver primitive
2919 /// ([`Self::resolved_classification`]) with ONE
2920 /// [`Classification`] primitive
2921 /// ([`Classification::horizon_terminates`]) so every downstream
2922 /// (`terminating-horizon` fixed tags on both surfaces in
2923 /// tatara-check, future scheduler / termination-shape
2924 /// validators, future variant additions on [`HorizonKind`])
2925 /// binds through the SAME `horizon_terminates()` shape rather
2926 /// than restating either the resolver walk or the closed-set
2927 /// projection composition at the callsite. THEORY.md §VI.1 —
2928 /// generation over composition; a future [`HorizonKind`]
2929 /// variant lands at ONE `ALL` entry + ONE `terminates` arm on
2930 /// the closed set and both surfaces pick it up mechanically.
2931 #[must_use]
2932 pub fn horizon_terminates(&self) -> bool {
2933 self.resolved_classification().horizon_terminates()
2934 }
2935
2936 /// Derived-boolean predicate — does this ephemeral spec's
2937 /// resolved [`Classification`]'s [`Horizon`] project to `true`
2938 /// under [`crate::classification::HorizonKind::requires_metric_axes`]?
2939 /// Byte-for-byte peer of
2940 /// [`Classification::horizon_requires_metric_axes`] wrapped
2941 /// through the [`Self::resolved_classification`] resolver so an
2942 /// operator-omitted `:classification` slot on `(defephemeral …)`
2943 /// still answers via the substrate default. The ONE ephemeral-
2944 /// surface substrate primitive that owns the
2945 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on
2946 /// the metric-axes-required question over the classification-
2947 /// horizon axis.
2948 ///
2949 /// # Antisymmetric peer of [`Self::horizon_terminates`]
2950 ///
2951 /// Byte-for-byte antisymmetric peer of [`Self::horizon_terminates`]
2952 /// via the SAME [`Self::resolved_classification`] resolver hop
2953 /// and the SAME closed set [`crate::classification::HorizonKind`]:
2954 /// [`Self::horizon_terminates`] composes
2955 /// [`Classification::horizon_terminates`] (walking
2956 /// [`crate::classification::HorizonKind::terminates`]); this
2957 /// method composes the ANTISYMMETRIC partner
2958 /// [`Classification::horizon_requires_metric_axes`] (walking
2959 /// [`crate::classification::HorizonKind::requires_metric_axes`]).
2960 /// The closed set pins the XOR contract
2961 /// `terminates() ^ requires_metric_axes()` on every variant, so
2962 /// exactly ONE of these two ephemeral-surface derived-nullary
2963 /// probes answers `true` per resolved [`Classification`] and the
2964 /// two probes together partition the resolver's output space into
2965 /// two disjoint buckets on every ephemeral spec — authored or
2966 /// defaulted.
2967 ///
2968 /// # Semantics — resolver hop + derived-nullary-boolean
2969 ///
2970 /// `horizon_requires_metric_axes()` returns `true` iff
2971 /// `self.resolved_classification().horizon_requires_metric_axes()`.
2972 /// The resolver returns the authored [`Classification`] when
2973 /// present and the substrate default
2974 /// [`Classification::gate_compute`] on absence. Because
2975 /// [`Classification::gate_compute`] uses [`Horizon::default`]
2976 /// (whose `kind` field defaults to
2977 /// [`crate::classification::HorizonKind::Bounded`] via
2978 /// `#[default]`), a bare ephemeral spec with no `:classification`
2979 /// slot answers `false` — the default-arm short-circuit
2980 /// propagates through THREE layers of `Default`
2981 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
2982 /// [`crate::classification::HorizonKind::default`]) to this
2983 /// predicate's answer, the mirror image of
2984 /// [`Self::horizon_terminates`]'s default-arm `true` answer. A
2985 /// regression that dropped the resolver hop, probed
2986 /// [`Classification::has_horizon_kind`] directly (dropping the
2987 /// `.requires_metric_axes()` projection), or crossed the wires
2988 /// with the antisymmetric partner
2989 /// [`crate::classification::HorizonKind::terminates`] fails HERE
2990 /// at ONE narrow substrate site before drifting through every
2991 /// unadorned ephemeral spec's baseline metric-provisioning
2992 /// answer.
2993 ///
2994 /// # Compounding
2995 ///
2996 /// The ephemeral require-tag classifier composes this primitive
2997 /// as a fixed tag `metric-axes-required` on
2998 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2999 /// surface's `metric-axes-required` fixed tag on
3000 /// `POINT_FIXED_TAG_ARMS` via
3001 /// [`Classification::horizon_requires_metric_axes`] directly. The
3002 /// two-surface parity contract holds by construction: both
3003 /// surfaces route through the SAME
3004 /// [`Classification::horizon_requires_metric_axes`] primitive
3005 /// after the ephemeral surface pays ONE resolver hop — a future
3006 /// [`crate::classification::HorizonKind`] variant or a future
3007 /// normalization at the substrate primitive lands at ONE site and
3008 /// both surfaces' `metric-axes-required` fixed tags inherit the
3009 /// shift mechanically.
3010 ///
3011 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3012 /// preserves proofs; the classification-axis derived-nullary-
3013 /// boolean probe body composes ONE resolver primitive
3014 /// ([`Self::resolved_classification`]) with ONE
3015 /// [`Classification`] primitive
3016 /// ([`Classification::horizon_requires_metric_axes`]) so every
3017 /// downstream (`metric-axes-required` fixed tags on both
3018 /// surfaces in tatara-check, future scheduler / metric-
3019 /// provisioning validators, future variant additions on
3020 /// [`crate::classification::HorizonKind`]) binds through the
3021 /// SAME `horizon_requires_metric_axes()` shape rather than
3022 /// restating either the resolver walk or the closed-set
3023 /// projection composition at the callsite. THEORY.md §VI.1 —
3024 /// generation over composition; a future
3025 /// [`crate::classification::HorizonKind`] variant lands at ONE
3026 /// `ALL` entry + ONE `requires_metric_axes` arm on the closed
3027 /// set and both surfaces pick it up mechanically.
3028 #[must_use]
3029 pub fn horizon_requires_metric_axes(&self) -> bool {
3030 self.resolved_classification()
3031 .horizon_requires_metric_axes()
3032 }
3033
3034 /// Derived-boolean predicate — does this ephemeral spec's
3035 /// resolved [`Classification`]'s [`crate::classification::CalmClassification`]
3036 /// project to `true` under
3037 /// [`crate::classification::CalmClassification::requires_coordination`]?
3038 /// Byte-for-byte peer of
3039 /// [`Classification::calm_requires_coordination`] wrapped through
3040 /// the [`Self::resolved_classification`] resolver so an operator-
3041 /// omitted `:classification` slot on `(defephemeral …)` still
3042 /// answers via the substrate default. The ONE ephemeral-surface
3043 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3044 /// derived-nullary-boolean walk on the coordination-required
3045 /// question over the classification-calm axis.
3046 ///
3047 /// # Third derived-nullary-boolean peer on the ephemeral surface
3048 ///
3049 /// Peer of [`Self::horizon_terminates`] and
3050 /// [`Self::horizon_requires_metric_axes`] on the ephemeral
3051 /// surface's (resolver-hop × derived-nullary-bool) shape — the
3052 /// FIRST peer threading the classification-calm axis rather than
3053 /// the classification-horizon axis. Distinct from both prior
3054 /// derived-nullary peers by ONE structural degree at the underlying
3055 /// [`Classification`] primitive: [`Self::horizon_terminates`] +
3056 /// [`Self::horizon_requires_metric_axes`] both walk the nested
3057 /// `.horizon.kind` sub-slot's derived projection, while this probe
3058 /// walks the direct scalar `.calm` field's derived projection.
3059 /// The resolver-hop shape is byte-identical.
3060 ///
3061 /// # Semantics — resolver hop + derived-nullary-boolean
3062 ///
3063 /// `calm_requires_coordination()` returns `true` iff
3064 /// `self.resolved_classification().calm_requires_coordination()`.
3065 /// The resolver returns the authored [`Classification`] when
3066 /// present and the substrate default
3067 /// [`Classification::gate_compute`] on absence. Because
3068 /// [`Classification::gate_compute`] carries
3069 /// [`crate::classification::CalmClassification::default = Monotone`],
3070 /// a bare ephemeral spec with no `:classification` slot answers
3071 /// `false` — the default-arm short-circuit propagates through TWO
3072 /// layers of `Default` ([`Classification::gate_compute`] →
3073 /// [`crate::classification::CalmClassification::default`]) to this
3074 /// predicate's answer. Distinct from the two `horizon_*` peers on
3075 /// this surface, which short-circuit through THREE layers of
3076 /// `Default` ([`Classification::gate_compute`] → [`Horizon::default`]
3077 /// → [`HorizonKind::default`]) because the horizon axis has a
3078 /// nested-struct wrapper between the classification field and the
3079 /// closed-set discriminator. A regression that dropped the
3080 /// resolver hop, probed [`Classification::has_calm`] directly
3081 /// (dropping the `.requires_coordination()` projection), or
3082 /// inverted the projection (silently promoting the Monotone
3083 /// baseline to "requires coordination") fails HERE at ONE narrow
3084 /// substrate site before drifting through every unadorned
3085 /// ephemeral spec's baseline coordination-mode answer.
3086 ///
3087 /// # Compounding
3088 ///
3089 /// The ephemeral require-tag classifier composes this primitive
3090 /// as a fixed tag `coordination-required` on
3091 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3092 /// surface's `coordination-required` fixed tag on
3093 /// `POINT_FIXED_TAG_ARMS` via
3094 /// [`Classification::calm_requires_coordination`] directly. The
3095 /// two-surface parity contract holds by construction: both
3096 /// surfaces route through the SAME
3097 /// [`Classification::calm_requires_coordination`] primitive after
3098 /// the ephemeral surface pays ONE resolver hop — a future
3099 /// [`crate::classification::CalmClassification`] variant or a
3100 /// future normalization at the substrate primitive lands at ONE
3101 /// site and both surfaces' `coordination-required` fixed tags
3102 /// inherit the shift mechanically.
3103 ///
3104 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3105 /// preserves proofs; the classification-axis derived-nullary-
3106 /// boolean probe body composes ONE resolver primitive
3107 /// ([`Self::resolved_classification`]) with ONE
3108 /// [`Classification`] primitive
3109 /// ([`Classification::calm_requires_coordination`]) so every
3110 /// downstream (`coordination-required` fixed tags on both
3111 /// surfaces in tatara-check, future scheduler / coordination-mode
3112 /// validators, future variant additions on
3113 /// [`crate::classification::CalmClassification`]) binds through
3114 /// the SAME `calm_requires_coordination()` shape rather than
3115 /// restating either the resolver walk or the closed-set
3116 /// projection composition at the callsite. THEORY.md §VI.1 —
3117 /// generation over composition; a future
3118 /// [`crate::classification::CalmClassification`] variant lands at
3119 /// ONE `ALL` entry + ONE `requires_coordination` arm on the
3120 /// closed set and both surfaces pick it up mechanically.
3121 #[must_use]
3122 pub fn calm_requires_coordination(&self) -> bool {
3123 self.resolved_classification().calm_requires_coordination()
3124 }
3125
3126 /// Derived-boolean predicate — does this ephemeral spec's
3127 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
3128 /// project to `true` under
3129 /// [`crate::classification::DataClassification::is_regulated`]?
3130 /// Byte-for-byte peer of
3131 /// [`Classification::data_is_regulated`] wrapped through the
3132 /// [`Self::resolved_classification`] resolver so an operator-
3133 /// omitted `:classification` slot on `(defephemeral …)` still
3134 /// answers via the substrate default. The ONE ephemeral-surface
3135 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3136 /// derived-nullary-boolean walk on the regulated-data question
3137 /// over the classification-data axis.
3138 ///
3139 /// # Fourth derived-nullary-boolean peer on the ephemeral surface
3140 ///
3141 /// Peer of [`Self::horizon_terminates`],
3142 /// [`Self::horizon_requires_metric_axes`], and
3143 /// [`Self::calm_requires_coordination`] on the ephemeral surface's
3144 /// (resolver-hop × derived-nullary-bool) shape — the FIRST peer
3145 /// threading the classification-data axis rather than the horizon
3146 /// or calm axes. Structural byte-for-byte peer of
3147 /// [`Self::calm_requires_coordination`]: both walk a DIRECT scalar
3148 /// closed-set field's derived projection on the resolved
3149 /// [`Classification`] (`.calm.requires_coordination()` /
3150 /// `.data_classification.is_regulated()`) — TWO layers of
3151 /// `Default` short-circuit ([`Classification::gate_compute`] →
3152 /// the direct scalar child's `#[default]`) — distinct from the
3153 /// two `horizon_*` peers which walk a NESTED-STRUCT projection
3154 /// (`.horizon.kind`) with THREE layers of `Default`. The resolver-
3155 /// hop shape is byte-identical across all four peers.
3156 ///
3157 /// # Semantics — resolver hop + derived-nullary-boolean
3158 ///
3159 /// `data_is_regulated()` returns `true` iff
3160 /// `self.resolved_classification().data_is_regulated()`. The
3161 /// resolver returns the authored [`Classification`] when present
3162 /// and the substrate default [`Classification::gate_compute`] on
3163 /// absence. Because [`Classification::gate_compute`] carries
3164 /// [`crate::classification::DataClassification::default = Internal`],
3165 /// a bare ephemeral spec with no `:classification` slot answers
3166 /// `false` — the default-arm short-circuit propagates through TWO
3167 /// layers of `Default` ([`Classification::gate_compute`] →
3168 /// [`crate::classification::DataClassification::default`]) to
3169 /// this predicate's answer, mirror-image of
3170 /// [`Self::calm_requires_coordination`]'s Monotone-default
3171 /// short-circuit through the same structural depth. Distinct
3172 /// from the two `horizon_*` peers on this surface which short-
3173 /// circuit through THREE layers of `Default` because the horizon
3174 /// axis has a nested-struct wrapper. A regression that dropped
3175 /// the resolver hop, probed [`Classification::has_data_classification`]
3176 /// directly (dropping the `.is_regulated()` projection), or
3177 /// inverted the projection (silently promoting the Internal
3178 /// baseline to "regulated") fails HERE at ONE narrow substrate
3179 /// site before drifting through every unadorned ephemeral spec's
3180 /// baseline regulatory-regime answer.
3181 ///
3182 /// # Compounding
3183 ///
3184 /// The ephemeral require-tag classifier composes this primitive
3185 /// as a fixed tag `data-regulated` on `EPHEMERAL_FIXED_TAG_ARMS`
3186 /// — byte-for-byte peer of the point surface's `data-regulated`
3187 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3188 /// [`Classification::data_is_regulated`] directly. The two-
3189 /// surface parity contract holds by construction: both surfaces
3190 /// route through the SAME
3191 /// [`Classification::data_is_regulated`] primitive after the
3192 /// ephemeral surface pays ONE resolver hop — a future
3193 /// [`crate::classification::DataClassification`] variant or a
3194 /// future normalization at the substrate primitive lands at ONE
3195 /// site and both surfaces' `data-regulated` fixed tags inherit
3196 /// the shift mechanically.
3197 ///
3198 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3199 /// preserves proofs; the classification-data-axis derived-nullary-
3200 /// boolean probe body composes ONE resolver primitive
3201 /// ([`Self::resolved_classification`]) with ONE
3202 /// [`Classification`] primitive
3203 /// ([`Classification::data_is_regulated`]) so every downstream
3204 /// (`data-regulated` fixed tags on both surfaces in tatara-check,
3205 /// future compliance-baseline / regulatory-regime validators,
3206 /// future variant additions on
3207 /// [`crate::classification::DataClassification`]) binds through
3208 /// the SAME `data_is_regulated()` shape rather than restating
3209 /// either the resolver walk or the closed-set projection
3210 /// composition at the callsite. THEORY.md §VI.1 — generation
3211 /// over composition; a future
3212 /// [`crate::classification::DataClassification`] variant lands
3213 /// at ONE `ALL` entry + ONE `is_regulated` arm on the closed set
3214 /// and both surfaces pick it up mechanically.
3215 #[must_use]
3216 pub fn data_is_regulated(&self) -> bool {
3217 self.resolved_classification().data_is_regulated()
3218 }
3219
3220 /// Derived-boolean predicate — does this ephemeral spec's
3221 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
3222 /// project to `true` under
3223 /// [`crate::classification::DataClassification::is_restricted`]?
3224 /// Byte-for-byte peer of
3225 /// [`Classification::data_is_restricted`] wrapped through the
3226 /// [`Self::resolved_classification`] resolver so an operator-
3227 /// omitted `:classification` slot on `(defephemeral …)` still
3228 /// answers via the substrate default. The ONE ephemeral-surface
3229 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3230 /// derived-nullary-boolean walk on the restricted-data question
3231 /// over the classification-data axis.
3232 ///
3233 /// # Fifth derived-nullary-boolean peer on the ephemeral surface
3234 ///
3235 /// Peer of [`Self::horizon_terminates`],
3236 /// [`Self::horizon_requires_metric_axes`],
3237 /// [`Self::calm_requires_coordination`], and
3238 /// [`Self::data_is_regulated`] on the ephemeral surface's
3239 /// (resolver-hop × derived-nullary-bool) shape — the SECOND peer
3240 /// threading the classification-data axis after
3241 /// [`Self::data_is_regulated`] opened it, pinning the data axis
3242 /// as a proven-repeatable structural sub-corner across TWO sibling
3243 /// closed-set projections (`is_regulated` / `is_restricted`).
3244 /// Structural byte-for-byte peer of
3245 /// [`Self::data_is_regulated`]: both walk the SAME DIRECT scalar
3246 /// closed-set field's derived projection on the resolved
3247 /// [`Classification`] (`.data_classification.is_regulated()` /
3248 /// `.is_restricted()`) — TWO layers of `Default` short-circuit
3249 /// ([`Classification::gate_compute`] → [`crate::classification::DataClassification::default = Internal`])
3250 /// — distinct from the two `horizon_*` peers which walk a NESTED-
3251 /// STRUCT projection (`.horizon.kind`) with THREE layers of
3252 /// `Default`. The resolver-hop shape is byte-identical across all
3253 /// five peers.
3254 ///
3255 /// # Semantics — resolver hop + derived-nullary-boolean
3256 ///
3257 /// `data_is_restricted()` returns `true` iff
3258 /// `self.resolved_classification().data_is_restricted()`. The
3259 /// resolver returns the authored [`Classification`] when present
3260 /// and the substrate default [`Classification::gate_compute`] on
3261 /// absence. Because [`Classification::gate_compute`] carries
3262 /// [`crate::classification::DataClassification::default = Internal`],
3263 /// a bare ephemeral spec with no `:classification` slot answers
3264 /// `true` — the default-arm short-circuit propagates through TWO
3265 /// layers of `Default` ([`Classification::gate_compute`] →
3266 /// [`crate::classification::DataClassification::default`]) to
3267 /// this predicate's answer. FIRST direct-scalar ephemeral-surface
3268 /// peer whose absent-classification default answers `true`, not
3269 /// `false` (`data_is_regulated` and `calm_requires_coordination`
3270 /// both project `false` on the same absent classification),
3271 /// mirror-image of [`Self::horizon_terminates`]'s `Bounded`-default
3272 /// `true` baseline on the nested-struct sub-corner. A regression
3273 /// that dropped the resolver hop, probed
3274 /// [`Classification::has_data_classification`] directly (dropping
3275 /// the `.is_restricted()` projection), or inverted the projection
3276 /// (silently demoting the Internal baseline to "unrestricted")
3277 /// fails HERE at ONE narrow substrate site before drifting
3278 /// through every unadorned ephemeral spec's baseline access-
3279 /// control-mandatory answer.
3280 ///
3281 /// # Compounding
3282 ///
3283 /// The ephemeral require-tag classifier composes this primitive
3284 /// as a fixed tag `data-restricted` on `EPHEMERAL_FIXED_TAG_ARMS`
3285 /// — byte-for-byte peer of the point surface's `data-restricted`
3286 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3287 /// [`Classification::data_is_restricted`] directly. The two-
3288 /// surface parity contract holds by construction: both surfaces
3289 /// route through the SAME
3290 /// [`Classification::data_is_restricted`] primitive after the
3291 /// ephemeral surface pays ONE resolver hop — a future
3292 /// [`crate::classification::DataClassification`] variant or a
3293 /// future normalization at the substrate primitive lands at ONE
3294 /// site and both surfaces' `data-restricted` fixed tags inherit
3295 /// the shift mechanically. The closed-set-internal implication
3296 /// `is_regulated() ⇒ is_restricted()` composes through the
3297 /// resolver hop to
3298 /// `data_is_regulated() ⇒ data_is_restricted()` at this surface
3299 /// too.
3300 ///
3301 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3302 /// preserves proofs; the classification-data-axis derived-nullary-
3303 /// boolean probe body composes ONE resolver primitive
3304 /// ([`Self::resolved_classification`]) with ONE
3305 /// [`Classification`] primitive
3306 /// ([`Classification::data_is_restricted`]) so every downstream
3307 /// (`data-restricted` fixed tags on both surfaces in tatara-check,
3308 /// future compliance-baseline / access-control-mandatory
3309 /// validators, future variant additions on
3310 /// [`crate::classification::DataClassification`]) binds through
3311 /// the SAME `data_is_restricted()` shape rather than restating
3312 /// either the resolver walk or the closed-set projection
3313 /// composition at the callsite. THEORY.md §VI.1 — generation
3314 /// over composition; a future
3315 /// [`crate::classification::DataClassification`] variant lands
3316 /// at ONE `ALL` entry + ONE `is_restricted` arm on the closed set
3317 /// and both surfaces pick it up mechanically.
3318 #[must_use]
3319 pub fn data_is_restricted(&self) -> bool {
3320 self.resolved_classification().data_is_restricted()
3321 }
3322
3323 /// Derived-boolean predicate — does this ephemeral spec's
3324 /// resolved [`Classification`]'s
3325 /// [`crate::classification::ConvergencePointType`] project to
3326 /// `true` under
3327 /// [`crate::classification::ConvergencePointType::is_endomorphic`]?
3328 /// Byte-for-byte peer of
3329 /// [`Classification::point_is_endomorphic`] wrapped through the
3330 /// [`Self::resolved_classification`] resolver so an operator-
3331 /// omitted `:classification` slot on `(defephemeral …)` still
3332 /// answers via the substrate default. The ONE ephemeral-surface
3333 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3334 /// derived-nullary-boolean walk on the 1→1 topology-bucket
3335 /// question over the classification-`point_type` axis.
3336 ///
3337 /// # Sixth derived-nullary-boolean peer on the ephemeral surface
3338 ///
3339 /// Peer of [`Self::horizon_terminates`],
3340 /// [`Self::horizon_requires_metric_axes`],
3341 /// [`Self::calm_requires_coordination`],
3342 /// [`Self::data_is_regulated`], and [`Self::data_is_restricted`]
3343 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
3344 /// shape — the FIRST peer threading the classification-`point_type`
3345 /// axis after the two `horizon_*`, one `calm_*`, and two `data_*`
3346 /// peers populated the horizon, calm, and data axes. Direct-scalar
3347 /// peer of the sibling `data_*` and `calm_*` arms but distinct by
3348 /// ONE structural degree at the underlying [`Classification`]
3349 /// primitive: [`crate::classification::ConvergencePointType`] has
3350 /// NO [`Default`] impl, so the absent-`:classification` baseline
3351 /// answers `false` via the resolver's substrate default
3352 /// [`Classification::gate_compute`] carrying its chosen
3353 /// `point_type: Gate` field (not via a `#[default]` short-circuit
3354 /// on the point-type axis itself). The resolver-hop shape is
3355 /// byte-identical across all six peers.
3356 ///
3357 /// # Semantics — resolver hop + derived-nullary-boolean
3358 ///
3359 /// `point_is_endomorphic()` returns `true` iff
3360 /// `self.resolved_classification().point_is_endomorphic()`. The
3361 /// resolver returns the authored [`Classification`] when present
3362 /// and the substrate default [`Classification::gate_compute`] on
3363 /// absence. Because [`Classification::gate_compute`] carries
3364 /// [`crate::classification::ConvergencePointType::Gate`] (a
3365 /// convergent barrier point, not a 1→1 endomorphism), a bare
3366 /// ephemeral spec with no `:classification` slot answers `false`.
3367 /// A regression that dropped the resolver hop, probed the wrong
3368 /// closed-set arm, or inverted the projection fails HERE at ONE
3369 /// narrow substrate site before drifting through every unadorned
3370 /// ephemeral spec's DAG-composition answer.
3371 ///
3372 /// # Compounding
3373 ///
3374 /// The ephemeral require-tag classifier composes this primitive
3375 /// as a fixed tag `endomorphic-point` on
3376 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3377 /// surface's `endomorphic-point` fixed tag on
3378 /// `POINT_FIXED_TAG_ARMS` via
3379 /// [`Classification::point_is_endomorphic`] directly. The two-
3380 /// surface parity contract holds by construction: both surfaces
3381 /// route through the SAME
3382 /// [`Classification::point_is_endomorphic`] primitive after the
3383 /// ephemeral surface pays ONE resolver hop — a future
3384 /// [`crate::classification::ConvergencePointType`] variant or a
3385 /// future normalization at the substrate primitive lands at ONE
3386 /// site and both surfaces' `endomorphic-point` fixed tags inherit
3387 /// the shift mechanically. Sibling projections
3388 /// [`crate::classification::ConvergencePointType::is_diffusive`]
3389 /// and [`crate::classification::ConvergencePointType::is_convergent`]
3390 /// compose byte-identically as future seventh + eighth ephemeral-
3391 /// surface peers; when all three land the three-way partition
3392 /// contract sealed on the closed set by
3393 /// `convergence_point_type_buckets_cover_every_variant` composes
3394 /// through the resolver-hop layer as a substrate-wide theorem.
3395 ///
3396 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3397 /// preserves proofs; the classification-`point_type`-axis derived-
3398 /// nullary-boolean probe body composes ONE resolver primitive
3399 /// ([`Self::resolved_classification`]) with ONE
3400 /// [`Classification`] primitive
3401 /// ([`Classification::point_is_endomorphic`]) so every downstream
3402 /// (`endomorphic-point` fixed tags on both surfaces in tatara-check,
3403 /// future DAG composition / edge-cardinality validators, future
3404 /// variant additions on
3405 /// [`crate::classification::ConvergencePointType`]) binds through
3406 /// the SAME `point_is_endomorphic()` shape rather than restating
3407 /// either the resolver walk or the closed-set projection
3408 /// composition at the callsite. THEORY.md §VI.1 — generation over
3409 /// composition; a future
3410 /// [`crate::classification::ConvergencePointType`] variant lands
3411 /// at ONE `ALL` entry + ONE `is_endomorphic` arm on the closed
3412 /// set and both surfaces pick it up mechanically.
3413 #[must_use]
3414 pub fn point_is_endomorphic(&self) -> bool {
3415 self.resolved_classification().point_is_endomorphic()
3416 }
3417
3418 /// Derived-boolean predicate — does this ephemeral spec's
3419 /// resolved [`Classification`]'s
3420 /// [`crate::classification::ConvergencePointType`] project to
3421 /// `true` under
3422 /// [`crate::classification::ConvergencePointType::is_diffusive`]?
3423 /// Byte-for-byte peer of
3424 /// [`Classification::point_is_diffusive`] wrapped through the
3425 /// [`Self::resolved_classification`] resolver so an operator-
3426 /// omitted `:classification` slot on `(defephemeral …)` still
3427 /// answers via the substrate default. The ONE ephemeral-surface
3428 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3429 /// derived-nullary-boolean walk on the 1→N fan-out topology-bucket
3430 /// question over the classification-`point_type` axis.
3431 ///
3432 /// # Seventh derived-nullary-boolean peer on the ephemeral surface
3433 ///
3434 /// Peer of [`Self::horizon_terminates`],
3435 /// [`Self::horizon_requires_metric_axes`],
3436 /// [`Self::calm_requires_coordination`],
3437 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`], and
3438 /// [`Self::point_is_endomorphic`] on the ephemeral surface's
3439 /// (resolver-hop × derived-nullary-bool) shape — the SEVENTH peer
3440 /// overall and the SECOND peer threading the classification-
3441 /// `point_type` axis. Direct-scalar peer of
3442 /// [`Self::point_is_endomorphic`]: both compose the SAME resolver
3443 /// hop and the SAME closed-set carrier through the SAME chosen-
3444 /// field baseline discipline (`Gate.is_diffusive() = false`,
3445 /// mirror-image of `Gate.is_endomorphic() = false`). The
3446 /// resolver-hop shape is byte-identical across all seven peers.
3447 ///
3448 /// # Semantics — resolver hop + derived-nullary-boolean
3449 ///
3450 /// `point_is_diffusive()` returns `true` iff
3451 /// `self.resolved_classification().point_is_diffusive()`. The
3452 /// resolver returns the authored [`Classification`] when present
3453 /// and the substrate default [`Classification::gate_compute`] on
3454 /// absence. Because [`Classification::gate_compute`] carries
3455 /// [`crate::classification::ConvergencePointType::Gate`] (a
3456 /// convergent barrier, not a fan-out), a bare ephemeral spec with
3457 /// no `:classification` slot answers `false`. A regression that
3458 /// dropped the resolver hop, probed the wrong closed-set arm, or
3459 /// inverted the projection fails HERE at ONE narrow substrate
3460 /// site before drifting through every unadorned ephemeral spec's
3461 /// DAG-composition answer.
3462 ///
3463 /// # Compounding — first ephemeral-surface corner-peer mutex on the `point_type` axis
3464 ///
3465 /// The ephemeral require-tag classifier composes this primitive
3466 /// as a fixed tag `diffusive-point` on `EPHEMERAL_FIXED_TAG_ARMS`
3467 /// — byte-for-byte peer of the point surface's `diffusive-point`
3468 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3469 /// [`Classification::point_is_diffusive`] directly. The two-
3470 /// surface parity contract holds by construction: both surfaces
3471 /// route through the SAME
3472 /// [`Classification::point_is_diffusive`] primitive after the
3473 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
3474 /// surface corner-peer pair on the `point_type` axis (with
3475 /// [`Self::point_is_endomorphic`]) whose two projections carry a
3476 /// non-trivial closed-set-internal MUTEX relationship
3477 /// (`point_is_endomorphic ⇒ ¬point_is_diffusive`), distinct from
3478 /// the sibling `data`-axis ephemeral corner-peer pair whose two
3479 /// projections carry a non-trivial IMPLICATION relationship. When
3480 /// the third sibling [`Self::point_is_convergent`] lands, the
3481 /// mutex closes into the full three-way XOR partition composed
3482 /// through the resolver-hop layer as a substrate-wide theorem.
3483 ///
3484 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3485 /// preserves proofs; the classification-`point_type`-axis derived-
3486 /// nullary-boolean probe body composes ONE resolver primitive
3487 /// ([`Self::resolved_classification`]) with ONE
3488 /// [`Classification`] primitive
3489 /// ([`Classification::point_is_diffusive`]) so every downstream
3490 /// (`diffusive-point` fixed tags on both surfaces in tatara-check,
3491 /// future DAG composition / edge-cardinality validators, future
3492 /// variant additions on
3493 /// [`crate::classification::ConvergencePointType`]) binds through
3494 /// the SAME `point_is_diffusive()` shape rather than restating
3495 /// either the resolver walk or the closed-set projection
3496 /// composition at the callsite. THEORY.md §VI.1 — generation over
3497 /// composition; a future
3498 /// [`crate::classification::ConvergencePointType`] variant lands
3499 /// at ONE `ALL` entry + ONE `is_diffusive` arm on the closed set
3500 /// and both surfaces pick it up mechanically.
3501 #[must_use]
3502 pub fn point_is_diffusive(&self) -> bool {
3503 self.resolved_classification().point_is_diffusive()
3504 }
3505
3506 /// Derived-boolean predicate — does this ephemeral spec's
3507 /// resolved [`Classification`]'s
3508 /// [`crate::classification::ConvergencePointType`] project to
3509 /// `true` under
3510 /// [`crate::classification::ConvergencePointType::is_convergent`]?
3511 /// Byte-for-byte peer of
3512 /// [`Classification::point_is_convergent`] wrapped through the
3513 /// [`Self::resolved_classification`] resolver so an operator-
3514 /// omitted `:classification` slot on `(defephemeral …)` still
3515 /// answers via the substrate default. The ONE ephemeral-surface
3516 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3517 /// derived-nullary-boolean walk on the N→1 fan-in topology-bucket
3518 /// question over the classification-`point_type` axis.
3519 ///
3520 /// # Eighth derived-nullary-boolean peer on the ephemeral surface
3521 ///
3522 /// Peer of [`Self::horizon_terminates`],
3523 /// [`Self::horizon_requires_metric_axes`],
3524 /// [`Self::calm_requires_coordination`],
3525 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3526 /// [`Self::point_is_endomorphic`], and [`Self::point_is_diffusive`]
3527 /// on the ephemeral surface's (resolver-hop × derived-nullary-
3528 /// bool) shape — the EIGHTH peer overall and the THIRD peer
3529 /// threading the classification-`point_type` axis. Direct-scalar
3530 /// peer of [`Self::point_is_endomorphic`] and
3531 /// [`Self::point_is_diffusive`]: the three compose the SAME
3532 /// resolver hop and the SAME closed-set carrier through the SAME
3533 /// chosen-field baseline discipline, but the answer flips on the
3534 /// baseline — `Gate.is_convergent() = true`, so an ephemeral spec
3535 /// with no `:classification` slot answers `true` HERE (mirror-
3536 /// inverted from the two sibling probes which answer `false`).
3537 /// The resolver-hop shape is byte-identical across all eight
3538 /// peers.
3539 ///
3540 /// # Semantics — resolver hop + derived-nullary-boolean
3541 ///
3542 /// `point_is_convergent()` returns `true` iff
3543 /// `self.resolved_classification().point_is_convergent()`. The
3544 /// resolver returns the authored [`Classification`] when present
3545 /// and the substrate default [`Classification::gate_compute`] on
3546 /// absence. Because [`Classification::gate_compute`] carries
3547 /// [`crate::classification::ConvergencePointType::Gate`] (the
3548 /// canonical convergent barrier), a bare ephemeral spec with no
3549 /// `:classification` slot answers `true` — a regression that
3550 /// dropped the resolver hop, probed the wrong closed-set arm, or
3551 /// inverted the projection fails HERE at ONE narrow substrate
3552 /// site before drifting through every unadorned ephemeral spec's
3553 /// DAG-composition answer.
3554 ///
3555 /// # Compounding — closes the three-way XOR partition on the ephemeral surface
3556 ///
3557 /// The ephemeral require-tag classifier composes this primitive
3558 /// as a fixed tag `convergent-point` on `EPHEMERAL_FIXED_TAG_ARMS`
3559 /// — byte-for-byte peer of the point surface's `convergent-point`
3560 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3561 /// [`Classification::point_is_convergent`] directly. The two-
3562 /// surface parity contract holds by construction: both surfaces
3563 /// route through the SAME
3564 /// [`Classification::point_is_convergent`] primitive after the
3565 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
3566 /// surface peer on the `point_type` axis closing the mutex pair
3567 /// [`Self::point_is_endomorphic`] / [`Self::point_is_diffusive`]
3568 /// into the FULL three-way XOR partition contract composed
3569 /// through the resolver-hop layer as a substrate-wide theorem.
3570 ///
3571 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3572 /// preserves proofs; the classification-`point_type`-axis derived-
3573 /// nullary-boolean probe body composes ONE resolver primitive
3574 /// ([`Self::resolved_classification`]) with ONE
3575 /// [`Classification`] primitive
3576 /// ([`Classification::point_is_convergent`]) so every downstream
3577 /// (`convergent-point` fixed tags on both surfaces in tatara-check,
3578 /// future DAG composition / edge-cardinality validators, future
3579 /// variant additions on
3580 /// [`crate::classification::ConvergencePointType`]) binds through
3581 /// the SAME `point_is_convergent()` shape rather than restating
3582 /// either the resolver walk or the closed-set projection
3583 /// composition at the callsite. THEORY.md §VI.1 — generation over
3584 /// composition; a future
3585 /// [`crate::classification::ConvergencePointType`] variant lands
3586 /// at ONE `ALL` entry + ONE `is_convergent` arm on the closed set
3587 /// and both surfaces pick it up mechanically.
3588 #[must_use]
3589 pub fn point_is_convergent(&self) -> bool {
3590 self.resolved_classification().point_is_convergent()
3591 }
3592
3593 /// Derived-boolean predicate — does this ephemeral spec's
3594 /// resolved [`Classification`]'s
3595 /// [`crate::classification::SubstrateType`] project to `true`
3596 /// under [`crate::classification::SubstrateType::is_resource`]?
3597 /// Byte-for-byte peer of
3598 /// [`Classification::substrate_is_resource`] wrapped through the
3599 /// [`Self::resolved_classification`] resolver so an operator-
3600 /// omitted `:classification` slot on `(defephemeral …)` still
3601 /// answers via the substrate default. The ONE ephemeral-surface
3602 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3603 /// derived-nullary-boolean walk on the resource-plane bucket
3604 /// question over the classification-`substrate` axis.
3605 ///
3606 /// # Ninth derived-nullary-boolean peer on the ephemeral surface
3607 ///
3608 /// Peer of [`Self::horizon_terminates`],
3609 /// [`Self::horizon_requires_metric_axes`],
3610 /// [`Self::calm_requires_coordination`],
3611 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3612 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3613 /// and [`Self::point_is_convergent`] on the ephemeral surface's
3614 /// (resolver-hop × derived-nullary-bool) shape — the NINTH peer
3615 /// overall and the FIRST peer threading the classification-
3616 /// `substrate` axis (the fourth of six classification axes
3617 /// participating on this corner, after `horizon`, `calm`,
3618 /// `data_classification`, and `point_type`). The resolver-hop
3619 /// shape is byte-identical across all nine peers.
3620 ///
3621 /// # Semantics — resolver hop + derived-nullary-boolean
3622 ///
3623 /// `substrate_is_resource()` returns `true` iff
3624 /// `self.resolved_classification().substrate_is_resource()`. The
3625 /// resolver returns the authored [`Classification`] when present
3626 /// and the substrate default [`Classification::gate_compute`] on
3627 /// absence. Because [`Classification::gate_compute`] carries
3628 /// [`crate::classification::SubstrateType::Compute`] (the
3629 /// canonical resource-plane substrate), a bare ephemeral spec
3630 /// with no `:classification` slot answers `true` — a regression
3631 /// that dropped the resolver hop, probed the wrong closed-set
3632 /// arm, or inverted the projection fails HERE at ONE narrow
3633 /// substrate site before drifting through every unadorned
3634 /// ephemeral spec's plane-baseline answer.
3635 ///
3636 /// # Compounding — opens the substrate axis on the ephemeral surface
3637 ///
3638 /// The ephemeral require-tag classifier composes this primitive
3639 /// as a fixed tag `resource-substrate` on
3640 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3641 /// surface's `resource-substrate` fixed tag on
3642 /// `POINT_FIXED_TAG_ARMS` via
3643 /// [`Classification::substrate_is_resource`] directly. The two-
3644 /// surface parity contract holds by construction: both surfaces
3645 /// route through the SAME
3646 /// [`Classification::substrate_is_resource`] primitive after the
3647 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
3648 /// surface peer on the `substrate` axis — future sibling
3649 /// projections [`crate::classification::SubstrateType::is_policy`]
3650 /// and [`crate::classification::SubstrateType::is_telemetry`]
3651 /// compose byte-identically as future tenth + eleventh peers,
3652 /// closing the axis into a proven-repeatable three-peer sub-
3653 /// corner exactly as the `point_type` axis was closed on this
3654 /// surface by
3655 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3656 ///
3657 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3658 /// preserves proofs; the classification-`substrate`-axis derived-
3659 /// nullary-boolean probe body composes ONE resolver primitive
3660 /// ([`Self::resolved_classification`]) with ONE
3661 /// [`Classification`] primitive
3662 /// ([`Classification::substrate_is_resource`]) so every
3663 /// downstream (`resource-substrate` fixed tags on both surfaces
3664 /// in tatara-check, future plane-baseline / compliance-baseline
3665 /// selectors, future variant additions on
3666 /// [`crate::classification::SubstrateType`]) binds through the
3667 /// SAME `substrate_is_resource()` shape rather than restating
3668 /// either the resolver walk or the closed-set projection
3669 /// composition at the callsite. THEORY.md §VI.1 — generation
3670 /// over composition; a future
3671 /// [`crate::classification::SubstrateType`] variant lands at ONE
3672 /// `ALL` entry + ONE `is_resource` arm on the closed set and
3673 /// both surfaces pick it up mechanically.
3674 #[must_use]
3675 pub fn substrate_is_resource(&self) -> bool {
3676 self.resolved_classification().substrate_is_resource()
3677 }
3678
3679 /// Derived-boolean predicate — does this ephemeral spec's
3680 /// resolved [`Classification`]'s
3681 /// [`crate::classification::SubstrateType`] project to `true`
3682 /// under [`crate::classification::SubstrateType::is_policy`]?
3683 /// Byte-for-byte peer of
3684 /// [`Classification::substrate_is_policy`] wrapped through the
3685 /// [`Self::resolved_classification`] resolver so an operator-
3686 /// omitted `:classification` slot on `(defephemeral …)` still
3687 /// answers via the substrate default. The ONE ephemeral-surface
3688 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3689 /// derived-nullary-boolean walk on the policy-plane bucket
3690 /// question over the classification-`substrate` axis.
3691 ///
3692 /// # Tenth derived-nullary-boolean peer on the ephemeral surface
3693 ///
3694 /// Peer of [`Self::horizon_terminates`],
3695 /// [`Self::horizon_requires_metric_axes`],
3696 /// [`Self::calm_requires_coordination`],
3697 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3698 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3699 /// [`Self::point_is_convergent`], and
3700 /// [`Self::substrate_is_resource`] on the ephemeral surface's
3701 /// (resolver-hop × derived-nullary-bool) shape — the TENTH peer
3702 /// overall and the SECOND peer threading the classification-
3703 /// `substrate` axis, promoting that axis on this surface from a
3704 /// proven-repeatable one-off to a proven-repeatable pair.
3705 /// FIRST ephemeral-surface substrate-axis corner-peer pair
3706 /// carrying a non-trivial closed-set-internal MUTEX relationship
3707 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`), structural
3708 /// twin of the sibling `point_type`-axis MUTEX pair sealed on
3709 /// this surface by
3710 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
3711 /// The resolver-hop shape is byte-identical across all ten peers.
3712 ///
3713 /// # Semantics — resolver hop + derived-nullary-boolean
3714 ///
3715 /// `substrate_is_policy()` returns `true` iff
3716 /// `self.resolved_classification().substrate_is_policy()`. The
3717 /// resolver returns the authored [`Classification`] when present
3718 /// and the substrate default [`Classification::gate_compute`] on
3719 /// absence. Because [`Classification::gate_compute`] carries
3720 /// [`crate::classification::SubstrateType::Compute`] (the
3721 /// canonical resource-plane substrate, NOT a policy plane), a
3722 /// bare ephemeral spec with no `:classification` slot answers
3723 /// `false` — a regression that dropped the resolver hop, probed
3724 /// the wrong closed-set arm, or inverted the projection fails
3725 /// HERE at ONE narrow substrate site before drifting through
3726 /// every unadorned ephemeral spec's plane-baseline answer.
3727 ///
3728 /// # Compounding — second substrate-axis peer on the ephemeral surface
3729 ///
3730 /// The ephemeral require-tag classifier composes this primitive
3731 /// as a fixed tag `policy-substrate` on
3732 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3733 /// surface's `policy-substrate` fixed tag on
3734 /// `POINT_FIXED_TAG_ARMS` via
3735 /// [`Classification::substrate_is_policy`] directly. The two-
3736 /// surface parity contract holds by construction: both surfaces
3737 /// route through the SAME
3738 /// [`Classification::substrate_is_policy`] primitive after the
3739 /// ephemeral surface pays ONE resolver hop. SECOND ephemeral-
3740 /// surface peer on the `substrate` axis — sibling projection
3741 /// [`crate::classification::SubstrateType::is_telemetry`]
3742 /// composes byte-identically as a future eleventh peer, closing
3743 /// the axis into a proven-repeatable three-peer sub-corner
3744 /// exactly as the `point_type` axis was closed on this surface
3745 /// by
3746 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3747 ///
3748 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3749 /// preserves proofs; the classification-`substrate`-axis derived-
3750 /// nullary-boolean probe body composes ONE resolver primitive
3751 /// ([`Self::resolved_classification`]) with ONE
3752 /// [`Classification`] primitive
3753 /// ([`Classification::substrate_is_policy`]) so every
3754 /// downstream (`policy-substrate` fixed tags on both surfaces
3755 /// in tatara-check, future plane-baseline / compliance-baseline
3756 /// selectors, future variant additions on
3757 /// [`crate::classification::SubstrateType`]) binds through the
3758 /// SAME `substrate_is_policy()` shape rather than restating
3759 /// either the resolver walk or the closed-set projection
3760 /// composition at the callsite. THEORY.md §VI.1 — generation
3761 /// over composition; a future
3762 /// [`crate::classification::SubstrateType`] variant lands at ONE
3763 /// `ALL` entry + ONE `is_policy` arm on the closed set and
3764 /// both surfaces pick it up mechanically.
3765 #[must_use]
3766 pub fn substrate_is_policy(&self) -> bool {
3767 self.resolved_classification().substrate_is_policy()
3768 }
3769
3770 /// Derived-boolean predicate — does this ephemeral spec's
3771 /// resolved [`Classification`]'s
3772 /// [`crate::classification::SubstrateType`] project to `true`
3773 /// under [`crate::classification::SubstrateType::is_telemetry`]?
3774 /// Byte-for-byte peer of
3775 /// [`Classification::substrate_is_telemetry`] wrapped through
3776 /// the [`Self::resolved_classification`] resolver so an operator-
3777 /// omitted `:classification` slot on `(defephemeral …)` still
3778 /// answers via the substrate default. The ONE ephemeral-surface
3779 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3780 /// derived-nullary-boolean walk on the telemetry-plane bucket
3781 /// question over the classification-`substrate` axis.
3782 ///
3783 /// # Eleventh derived-nullary-boolean peer on the ephemeral surface — CLOSES the substrate axis
3784 ///
3785 /// Peer of [`Self::horizon_terminates`],
3786 /// [`Self::horizon_requires_metric_axes`],
3787 /// [`Self::calm_requires_coordination`],
3788 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3789 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3790 /// [`Self::point_is_convergent`], [`Self::substrate_is_resource`],
3791 /// and [`Self::substrate_is_policy`] on the ephemeral surface's
3792 /// (resolver-hop × derived-nullary-bool) shape — the ELEVENTH
3793 /// peer overall and the THIRD peer threading the classification-
3794 /// `substrate` axis. This peer CLOSES the substrate axis on the
3795 /// ephemeral surface into the FULL three-way XOR partition
3796 /// contract `substrate_is_resource ⊕ substrate_is_policy ⊕
3797 /// substrate_is_telemetry` — sealed on this surface by
3798 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
3799 /// the resolver-hop peer of the parent-composed
3800 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`.
3801 /// Structural twin of the sibling `point_type`-axis ternary lift
3802 /// sealed on this surface by
3803 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3804 /// The resolver-hop shape is byte-identical across all eleven
3805 /// peers.
3806 ///
3807 /// # Semantics — resolver hop + derived-nullary-boolean
3808 ///
3809 /// `substrate_is_telemetry()` returns `true` iff
3810 /// `self.resolved_classification().substrate_is_telemetry()`.
3811 /// The resolver returns the authored [`Classification`] when
3812 /// present and the substrate default [`Classification::gate_compute`]
3813 /// on absence. Because [`Classification::gate_compute`] carries
3814 /// [`crate::classification::SubstrateType::Compute`] (the
3815 /// canonical resource-plane substrate, NOT a telemetry plane),
3816 /// a bare ephemeral spec with no `:classification` slot answers
3817 /// `false` — a regression that dropped the resolver hop, probed
3818 /// the wrong closed-set arm, or inverted the projection fails
3819 /// HERE at ONE narrow substrate site before drifting through
3820 /// every unadorned ephemeral spec's plane-baseline answer.
3821 ///
3822 /// # Compounding — CLOSES the substrate axis on the ephemeral surface
3823 ///
3824 /// The ephemeral require-tag classifier composes this primitive
3825 /// as a fixed tag `telemetry-substrate` on
3826 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3827 /// surface's `telemetry-substrate` fixed tag on
3828 /// `POINT_FIXED_TAG_ARMS` via
3829 /// [`Classification::substrate_is_telemetry`] directly. The two-
3830 /// surface parity contract holds by construction: both surfaces
3831 /// route through the SAME
3832 /// [`Classification::substrate_is_telemetry`] primitive after the
3833 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
3834 /// surface peer on the `substrate` axis — closes the axis into a
3835 /// proven-repeatable three-peer sub-corner exactly as the
3836 /// `point_type` axis was closed on this surface by
3837 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3838 ///
3839 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3840 /// preserves proofs; the classification-`substrate`-axis derived-
3841 /// nullary-boolean probe body composes ONE resolver primitive
3842 /// ([`Self::resolved_classification`]) with ONE
3843 /// [`Classification`] primitive
3844 /// ([`Classification::substrate_is_telemetry`]) so every
3845 /// downstream (`telemetry-substrate` fixed tags on both surfaces
3846 /// in tatara-check, future plane-baseline / compliance-baseline
3847 /// selectors, future variant additions on
3848 /// [`crate::classification::SubstrateType`]) binds through the
3849 /// SAME `substrate_is_telemetry()` shape rather than restating
3850 /// either the resolver walk or the closed-set projection
3851 /// composition at the callsite. THEORY.md §VI.1 — generation
3852 /// over composition; a future
3853 /// [`crate::classification::SubstrateType`] variant lands at ONE
3854 /// `ALL` entry + ONE `is_telemetry` arm on the closed set and
3855 /// both surfaces pick it up mechanically.
3856 #[must_use]
3857 pub fn substrate_is_telemetry(&self) -> bool {
3858 self.resolved_classification().substrate_is_telemetry()
3859 }
3860
3861 /// Derived-boolean predicate — does this ephemeral spec's
3862 /// resolved [`Classification`]'s
3863 /// [`crate::classification::CalmClassification`] project to `true`
3864 /// under [`crate::classification::CalmClassification::is_monotone`]?
3865 /// Byte-for-byte peer of [`Classification::calm_is_monotone`]
3866 /// wrapped through the [`Self::resolved_classification`] resolver
3867 /// so an operator-omitted `:classification` slot on
3868 /// `(defephemeral …)` still answers via the substrate default.
3869 /// The ONE ephemeral-surface substrate primitive that owns the
3870 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3871 /// CALM-monotone-plane question — the positive framing peer of
3872 /// [`Self::calm_requires_coordination`].
3873 ///
3874 /// # Twelfth derived-nullary-boolean peer on the ephemeral surface — CLOSES the calm axis
3875 ///
3876 /// Peer of [`Self::horizon_terminates`],
3877 /// [`Self::horizon_requires_metric_axes`],
3878 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3879 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3880 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3881 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3882 /// and [`Self::substrate_is_telemetry`] on the ephemeral
3883 /// surface's (resolver-hop × derived-nullary-bool) shape — the
3884 /// TWELFTH peer overall and the SECOND peer threading the
3885 /// classification-`calm` axis. This peer CLOSES the calm axis
3886 /// on the ephemeral surface into the FULL binary XOR partition
3887 /// contract `calm_is_monotone ⊕ calm_requires_coordination` —
3888 /// sealed on this surface by
3889 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
3890 /// the resolver-hop peer of the parent-composed
3891 /// `classification_calm_probes_form_binary_xor_partition_over_all`.
3892 /// Structural twin of the sibling horizon-axis binary XOR
3893 /// sealed on the closed set by
3894 /// `horizon_kind_terminate_xor_requires_metric_axes`, lifted
3895 /// through the resolver hop to the ephemeral surface. The
3896 /// resolver-hop shape is byte-identical across all twelve peers.
3897 ///
3898 /// # Semantics — resolver hop + derived-nullary-boolean
3899 ///
3900 /// `calm_is_monotone()` returns `true` iff
3901 /// `self.resolved_classification().calm_is_monotone()`. The
3902 /// resolver returns the authored [`Classification`] when present
3903 /// and the substrate default [`Classification::gate_compute`] on
3904 /// absence. Because [`Classification::gate_compute`] carries
3905 /// [`crate::classification::CalmClassification::default =
3906 /// Monotone`] via `#[default]`, a bare ephemeral spec with no
3907 /// `:classification` slot answers `true` — every unadorned
3908 /// `(defephemeral …)` reads as gossip-eligible under the
3909 /// positive CALM framing, safe under Hellerstein's theorem
3910 /// (monotone operations distribute without coordination). A
3911 /// regression that dropped the resolver hop, probed the wrong
3912 /// closed-set arm, or inverted the projection fails HERE at ONE
3913 /// narrow substrate site before drifting through every
3914 /// unadorned ephemeral spec's positive-CALM-framing answer.
3915 /// Mirror-inverted from the sibling
3916 /// `calm_requires_coordination_probes_false_on_absent_classification`
3917 /// (both walk the SAME defaulted `calm` field, so
3918 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
3919 /// closed set's disjoint XOR partition).
3920 ///
3921 /// # Compounding — CLOSES the calm axis on the ephemeral surface
3922 ///
3923 /// The ephemeral require-tag classifier composes this primitive
3924 /// as a fixed tag `monotone-calm` on `EPHEMERAL_FIXED_TAG_ARMS`
3925 /// — byte-for-byte peer of the point surface's `monotone-calm`
3926 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3927 /// [`Classification::calm_is_monotone`] directly. The two-
3928 /// surface parity contract holds by construction: both surfaces
3929 /// route through the SAME [`Classification::calm_is_monotone`]
3930 /// primitive after the ephemeral surface pays ONE resolver hop.
3931 /// SECOND ephemeral-surface peer on the `calm` axis — CLOSES the
3932 /// axis into a proven-repeatable two-peer sub-corner exactly as
3933 /// the `horizon` axis is closed on the closed-set layer by
3934 /// `horizon_kind_terminate_xor_requires_metric_axes`.
3935 ///
3936 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3937 /// preserves proofs; the classification-`calm`-axis derived-
3938 /// nullary-boolean probe body composes ONE resolver primitive
3939 /// ([`Self::resolved_classification`]) with ONE
3940 /// [`Classification`] primitive
3941 /// ([`Classification::calm_is_monotone`]) so every downstream
3942 /// (`monotone-calm` fixed tags on both surfaces in tatara-check,
3943 /// future scheduler / gossip-eligibility validators reading the
3944 /// positive CALM framing, future variant additions on
3945 /// [`crate::classification::CalmClassification`]) binds through
3946 /// the SAME `calm_is_monotone()` shape rather than restating
3947 /// either the resolver walk or the closed-set projection
3948 /// composition at the callsite. THEORY.md §VI.1 — generation
3949 /// over composition; a future
3950 /// [`crate::classification::CalmClassification`] variant lands
3951 /// at ONE `ALL` entry + ONE `is_monotone` arm on the closed set
3952 /// and both surfaces pick it up mechanically.
3953 #[must_use]
3954 pub fn calm_is_monotone(&self) -> bool {
3955 self.resolved_classification().calm_is_monotone()
3956 }
3957
3958 /// Derived-boolean predicate — does this ephemeral spec's
3959 /// resolved [`Classification`]'s
3960 /// [`crate::classification::DataClassification`] project to `true`
3961 /// under [`crate::classification::DataClassification::is_public`]?
3962 /// Byte-for-byte peer of [`Classification::data_is_public`]
3963 /// wrapped through the [`Self::resolved_classification`] resolver
3964 /// so an operator-omitted `:classification` slot on
3965 /// `(defephemeral …)` still answers via the substrate default.
3966 /// The ONE ephemeral-surface substrate primitive that owns the
3967 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3968 /// freely-distributable-data question — the positive framing peer
3969 /// of [`Self::data_is_restricted`].
3970 ///
3971 /// # Thirteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the data axis
3972 ///
3973 /// Peer of [`Self::horizon_terminates`],
3974 /// [`Self::horizon_requires_metric_axes`],
3975 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3976 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3977 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3978 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3979 /// [`Self::substrate_is_telemetry`], and [`Self::calm_is_monotone`]
3980 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
3981 /// shape — the THIRTEENTH peer overall and the THIRD peer
3982 /// threading the classification-`data_classification` axis. This
3983 /// peer CLOSES the data axis on the ephemeral surface into the
3984 /// FULL binary XOR partition contract
3985 /// `data_is_public ⊕ data_is_restricted` — sealed on this surface
3986 /// by `ephemeral_data_probes_form_binary_xor_partition_over_all`,
3987 /// the resolver-hop peer of the parent-composed
3988 /// `classification_data_probes_form_binary_xor_partition_over_all`.
3989 /// Structural twin of the sibling calm-axis binary XOR sealed on
3990 /// this surface by
3991 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
3992 /// lifted through the resolver hop from the six-variant data-axis
3993 /// closed set to the ephemeral surface. The resolver-hop shape is
3994 /// byte-identical across all thirteen peers.
3995 ///
3996 /// # Semantics — resolver hop + derived-nullary-boolean
3997 ///
3998 /// `data_is_public()` returns `true` iff
3999 /// `self.resolved_classification().data_is_public()`. The
4000 /// resolver returns the authored [`Classification`] when present
4001 /// and the substrate default [`Classification::gate_compute`] on
4002 /// absence. Because [`Classification::gate_compute`] carries
4003 /// [`crate::classification::DataClassification::default =
4004 /// Internal`] via `#[default]`, a bare ephemeral spec with no
4005 /// `:classification` slot answers `false` — every unadorned
4006 /// `(defephemeral …)` reads as access-controlled by default (safe
4007 /// under compliance baseline: an operator must deliberately opt
4008 /// the dataset into public distribution rather than the substrate
4009 /// silently promoting an unadorned Process onto the freely-
4010 /// distributable path). A regression that dropped the resolver
4011 /// hop, probed the wrong closed-set arm, or inverted the
4012 /// projection fails HERE at ONE narrow substrate site before
4013 /// drifting through every unadorned ephemeral spec's positive-
4014 /// distribution-framing answer. Mirror-inverted from the sibling
4015 /// `data_is_restricted_probes_true_on_absent_classification`
4016 /// (both walk the SAME defaulted `data_classification` field, so
4017 /// `is_restricted = true` ⇒ `is_public = false` on the closed
4018 /// set's disjoint XOR partition).
4019 ///
4020 /// # Compounding — CLOSES the data axis on the ephemeral surface
4021 ///
4022 /// The ephemeral require-tag classifier composes this primitive
4023 /// as a fixed tag `public-data` on `EPHEMERAL_FIXED_TAG_ARMS`
4024 /// — byte-for-byte peer of the point surface's `public-data`
4025 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4026 /// [`Classification::data_is_public`] directly. The two-
4027 /// surface parity contract holds by construction: both surfaces
4028 /// route through the SAME [`Classification::data_is_public`]
4029 /// primitive after the ephemeral surface pays ONE resolver hop.
4030 /// THIRD ephemeral-surface peer on the `data_classification` axis
4031 /// — CLOSES the axis into a proven-repeatable three-peer sub-
4032 /// corner (data_is_regulated, data_is_restricted, data_is_public)
4033 /// whose complementary XOR partition seals on the closed set by
4034 /// `data_classification_public_xor_restricted` and composes
4035 /// through the resolver hop as a substrate-wide theorem.
4036 ///
4037 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4038 /// preserves proofs; the classification-`data_classification`-axis
4039 /// derived-nullary-boolean probe body composes ONE resolver
4040 /// primitive ([`Self::resolved_classification`]) with ONE
4041 /// [`Classification`] primitive
4042 /// ([`Classification::data_is_public`]) so every downstream
4043 /// (`public-data` fixed tags on both surfaces in tatara-check,
4044 /// future compliance-baseline / audit-log-optional validators
4045 /// reading the positive distribution framing, future variant
4046 /// additions on
4047 /// [`crate::classification::DataClassification`]) binds through
4048 /// the SAME `data_is_public()` shape rather than restating either
4049 /// the resolver walk or the closed-set projection composition at
4050 /// the callsite. THEORY.md §VI.1 — generation over composition; a
4051 /// future [`crate::classification::DataClassification`] variant
4052 /// lands at ONE `ALL` entry + ONE `is_public` arm on the closed
4053 /// set and both surfaces pick it up mechanically.
4054 #[must_use]
4055 pub fn data_is_public(&self) -> bool {
4056 self.resolved_classification().data_is_public()
4057 }
4058
4059 /// Derived-boolean predicate — does this ephemeral spec's resolved
4060 /// [`Classification`]'s
4061 /// [`crate::classification::Horizon::direction`] slot (defaulted
4062 /// through [`crate::classification::OptimizationDirection::default =
4063 /// Minimize`] on absence) project to `true` under
4064 /// [`crate::classification::OptimizationDirection::prefers_lower`]?
4065 /// Byte-for-byte peer of
4066 /// [`crate::classification::Classification::direction_prefers_lower`]
4067 /// wrapped through the [`Self::resolved_classification`] resolver so
4068 /// an operator-omitted `:classification` slot on
4069 /// `(defephemeral …)` still answers via the substrate default. The
4070 /// ONE ephemeral-surface substrate primitive that owns the
4071 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4072 /// lower-is-better optimization-polarity question.
4073 ///
4074 /// # Fourteenth derived-nullary-boolean peer on the ephemeral surface — opens the optimization-direction axis
4075 ///
4076 /// Peer of the thirteen prior nullary-boolean substrate primitives
4077 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4078 /// [`Self::horizon_requires_metric_axes`],
4079 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4080 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4081 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4082 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4083 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4084 /// [`Self::data_is_public`]) on the ephemeral surface's
4085 /// (resolver-hop × derived-nullary-bool) shape — the FOURTEENTH
4086 /// peer overall and the FIRST peer threading the classification-
4087 /// `horizon.direction` axis on this surface. Opens the SIXTH
4088 /// classification axis into the ephemeral fixed-tag algebra after
4089 /// the horizon, calm, data, point, and substrate axes. The
4090 /// resolver-hop shape is byte-identical across all fourteen peers.
4091 ///
4092 /// # Semantics — resolver hop + derived-nullary-boolean
4093 ///
4094 /// `direction_prefers_lower()` returns `true` iff
4095 /// `self.resolved_classification().direction_prefers_lower()`. The
4096 /// resolver returns the authored [`Classification`] when present
4097 /// and the substrate default [`Classification::gate_compute`] on
4098 /// absence. Because [`Classification::gate_compute`] carries
4099 /// `horizon: Horizon::default()` whose `direction` field is `None`,
4100 /// and [`crate::classification::OptimizationDirection::default =
4101 /// Minimize`] projects `prefers_lower = true`, a bare ephemeral
4102 /// spec with no `:classification` slot answers `true` — every
4103 /// unadorned `(defephemeral …)` reads as lower-is-better under the
4104 /// substrate polarity default (safe under the asymptotic-health
4105 /// rate-window evaluator's convention: an operator must
4106 /// deliberately opt into Maximize polarity rather than the
4107 /// substrate silently flipping every unadorned Process onto the
4108 /// higher-is-better path). A regression that dropped the resolver
4109 /// hop, probed the wrong closed-set arm, or inverted the projection
4110 /// fails HERE at ONE narrow substrate site before drifting through
4111 /// every unadorned ephemeral spec's rate-window evaluator polarity.
4112 ///
4113 /// # Compounding — opens the optimization-direction axis on the ephemeral surface
4114 ///
4115 /// The ephemeral require-tag classifier composes this primitive as
4116 /// a fixed tag `prefers-lower-direction` on
4117 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4118 /// surface's `prefers-lower-direction` fixed tag on
4119 /// `POINT_FIXED_TAG_ARMS` via
4120 /// [`Classification::direction_prefers_lower`] directly. The
4121 /// two-surface parity contract holds by construction: both surfaces
4122 /// route through the SAME [`Classification::direction_prefers_lower`]
4123 /// primitive after the ephemeral surface pays ONE resolver hop.
4124 /// A future antisymmetric peer (`direction_prefers_higher`) closes
4125 /// the binary XOR partition on this axis — mirror of the calm-axis
4126 /// (`monotone-calm ⊕ coordination-required`) and data-axis
4127 /// (`public-data ⊕ data-restricted`) closures on this surface.
4128 ///
4129 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4130 /// preserves proofs; the classification-`horizon.direction`-axis
4131 /// derived-nullary-boolean probe body composes ONE resolver
4132 /// primitive ([`Self::resolved_classification`]) with ONE
4133 /// [`Classification`] primitive
4134 /// ([`Classification::direction_prefers_lower`]) so every
4135 /// downstream (the `prefers-lower-direction` fixed tags on both
4136 /// surfaces in tatara-check, future asymptotic-health rate-window
4137 /// / regression-detector evaluators, future variant additions on
4138 /// [`crate::classification::OptimizationDirection`]) binds through
4139 /// the SAME `direction_prefers_lower()` shape rather than restating
4140 /// either the resolver walk or the closed-set projection
4141 /// composition at the callsite. THEORY.md §VI.1 — generation over
4142 /// composition; a future
4143 /// [`crate::classification::OptimizationDirection`] variant lands
4144 /// at ONE `ALL` entry + ONE `prefers_lower` arm on the closed set
4145 /// and both surfaces pick it up mechanically.
4146 #[must_use]
4147 pub fn direction_prefers_lower(&self) -> bool {
4148 self.resolved_classification().direction_prefers_lower()
4149 }
4150
4151 /// POSITIVE-FRAMING PEER of [`Self::direction_prefers_lower`] —
4152 /// does this ephemeral spec's resolved [`Classification`]'s
4153 /// [`crate::classification::Horizon::direction`] slot (defaulted
4154 /// through [`crate::classification::OptimizationDirection::default =
4155 /// Minimize`] on absence) project to `true` under
4156 /// [`crate::classification::OptimizationDirection::prefers_higher`]?
4157 /// Byte-for-byte peer of
4158 /// [`crate::classification::Classification::direction_prefers_higher`]
4159 /// wrapped through the [`Self::resolved_classification`] resolver
4160 /// so an operator-omitted `:classification` slot on
4161 /// `(defephemeral …)` still answers via the substrate default. The
4162 /// ONE ephemeral-surface substrate primitive that owns the
4163 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4164 /// higher-is-better optimization-polarity question.
4165 ///
4166 /// # Fifteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the optimization-direction axis
4167 ///
4168 /// Peer of the fourteen prior nullary-boolean substrate primitives
4169 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4170 /// [`Self::horizon_requires_metric_axes`],
4171 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4172 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4173 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4174 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4175 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4176 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`]) on
4177 /// the ephemeral surface's (resolver-hop × derived-nullary-bool)
4178 /// shape — the FIFTEENTH peer overall and the SECOND peer
4179 /// threading the classification-`horizon.direction` axis on this
4180 /// surface. CLOSES the SIXTH classification axis into a binary XOR
4181 /// partition on the ephemeral surface after the horizon, calm,
4182 /// data, point, and substrate axes — completing the axis-coverage
4183 /// milestone on this surface: ALL SIX classification axes now
4184 /// have their partitions closed at the ephemeral-surface derived-
4185 /// nullary corner. The resolver-hop shape is byte-identical across
4186 /// all fifteen peers.
4187 ///
4188 /// # Semantics — resolver hop + derived-nullary-boolean
4189 ///
4190 /// `direction_prefers_higher()` returns `true` iff
4191 /// `self.resolved_classification().direction_prefers_higher()`.
4192 /// The resolver returns the authored [`Classification`] when
4193 /// present and the substrate default
4194 /// [`Classification::gate_compute`] on absence. Because
4195 /// [`Classification::gate_compute`] carries `horizon:
4196 /// Horizon::default()` whose `direction` field is `None`, and
4197 /// [`crate::classification::OptimizationDirection::default =
4198 /// Minimize`] projects `prefers_higher = false`, a bare ephemeral
4199 /// spec with no `:classification` slot answers `false` — every
4200 /// unadorned `(defephemeral …)` reads as lower-is-better under the
4201 /// substrate polarity default (safe under the asymptotic-health
4202 /// rate-window evaluator's convention: an operator must
4203 /// deliberately opt into Maximize polarity rather than the
4204 /// substrate silently flipping every unadorned Process onto the
4205 /// higher-is-better path). A regression that dropped the resolver
4206 /// hop, probed the wrong closed-set arm, or inverted the
4207 /// projection fails HERE at ONE narrow substrate site before
4208 /// drifting through every unadorned ephemeral spec's rate-window
4209 /// evaluator polarity.
4210 ///
4211 /// # Compounding — CLOSES the optimization-direction axis on the ephemeral surface
4212 ///
4213 /// The ephemeral require-tag classifier composes this primitive as
4214 /// a fixed tag `prefers-higher-direction` on
4215 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4216 /// surface's `prefers-higher-direction` fixed tag on
4217 /// `POINT_FIXED_TAG_ARMS` via
4218 /// [`Classification::direction_prefers_higher`] directly. The
4219 /// two-surface parity contract holds by construction: both
4220 /// surfaces route through the SAME
4221 /// [`Classification::direction_prefers_higher`] primitive after
4222 /// the ephemeral surface pays ONE resolver hop. SECOND
4223 /// optimization-direction-axis peer CLOSES the axis into the FULL
4224 /// binary XOR partition contract on this surface — the resolver-
4225 /// hop peer of the parent-composed
4226 /// `classification_direction_probes_form_binary_xor_partition_over_all`,
4227 /// mirror of the calm-axis (`monotone-calm ⊕ coordination-required`)
4228 /// and data-axis (`public-data ⊕ data-restricted`) closures on
4229 /// this surface.
4230 ///
4231 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4232 /// preserves proofs; the classification-`horizon.direction`-axis
4233 /// derived-nullary-boolean probe body composes ONE resolver
4234 /// primitive ([`Self::resolved_classification`]) with ONE
4235 /// [`Classification`] primitive
4236 /// ([`Classification::direction_prefers_higher`]) so every
4237 /// downstream (the `prefers-higher-direction` fixed tags on both
4238 /// surfaces in tatara-check, future asymptotic-health rate-window
4239 /// / regression-detector evaluators, future variant additions on
4240 /// [`crate::classification::OptimizationDirection`]) binds through
4241 /// the SAME `direction_prefers_higher()` shape rather than
4242 /// restating either the resolver walk or the closed-set projection
4243 /// composition at the callsite. THEORY.md §VI.1 — generation over
4244 /// composition; a future
4245 /// [`crate::classification::OptimizationDirection`] variant lands
4246 /// at ONE `ALL` entry + ONE `prefers_higher` arm on the closed set
4247 /// and both surfaces pick it up mechanically.
4248 #[must_use]
4249 pub fn direction_prefers_higher(&self) -> bool {
4250 self.resolved_classification().direction_prefers_higher()
4251 }
4252
4253 /// Derived-boolean predicate — does this ephemeral spec's resolved
4254 /// [`Classification`]'s `point_type` slot project to `Arity::One`
4255 /// under
4256 /// [`crate::classification::ConvergencePointType::input_arity`]?
4257 /// Byte-for-byte peer of
4258 /// [`crate::classification::Classification::input_arity_is_one`]
4259 /// wrapped through the [`Self::resolved_classification`] resolver
4260 /// so an operator-omitted `:classification` slot on
4261 /// `(defephemeral …)` still answers via the substrate default. The
4262 /// ONE ephemeral-surface substrate primitive that owns the
4263 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4264 /// single-input side of the DAG-composition input-arity projection.
4265 ///
4266 /// # Sixteenth derived-nullary-boolean peer on the ephemeral surface — opens the input-arity axis
4267 ///
4268 /// Peer of the fifteen prior nullary-boolean substrate primitives
4269 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4270 /// [`Self::horizon_requires_metric_axes`],
4271 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4272 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4273 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4274 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4275 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4276 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4277 /// [`Self::direction_prefers_higher`]) on the ephemeral surface's
4278 /// (resolver-hop × derived-nullary-bool) shape — the SIXTEENTH
4279 /// peer overall and the FIRST peer threading the classification-
4280 /// `point_type`-derived input-arity axis on this surface. Opens
4281 /// the SEVENTH classification axis into the ephemeral fixed-tag
4282 /// algebra after the horizon, calm, data, point-type, substrate,
4283 /// and optimization-direction axes. First peer on the derived-
4284 /// typed-projection stratum of the ephemeral surface — composes
4285 /// an extra closed-set-level projection hop
4286 /// ([`crate::classification::ConvergencePointType::input_arity`])
4287 /// compared to the sibling `point_is_*` triple that walks the raw
4288 /// `point_type` slot through the resolver. The resolver-hop shape
4289 /// is byte-identical across all sixteen peers.
4290 ///
4291 /// # Semantics — resolver hop + derived-nullary-boolean
4292 ///
4293 /// `input_arity_is_one()` returns `true` iff
4294 /// `self.resolved_classification().input_arity_is_one()`. The
4295 /// resolver returns the authored [`Classification`] when present
4296 /// and the substrate default [`Classification::gate_compute`] on
4297 /// absence. Because [`Classification::gate_compute`] carries
4298 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
4299 /// ephemeral spec with no `:classification` slot answers `false` —
4300 /// every unadorned `(defephemeral …)` lands in the multi-input
4301 /// bucket under the substrate default (`Gate` gates a
4302 /// many-to-one bucket dispatch, so the single-input bucket only
4303 /// applies to operator-authored specs on the `Transform | Fork |
4304 /// Broadcast | Observe` arms). A regression that dropped the
4305 /// resolver hop, probed the wrong closed-set arm, or crossed the
4306 /// wires with the sibling
4307 /// [`crate::classification::ConvergencePointType::output_arity`]
4308 /// projection (which disagrees on six of the eight variants) fails
4309 /// HERE at ONE narrow substrate site before drifting through
4310 /// every unadorned ephemeral spec's DAG-composition input-arity
4311 /// audit.
4312 ///
4313 /// # Compounding — opens the input-arity axis on the ephemeral surface
4314 ///
4315 /// The ephemeral require-tag classifier will compose this
4316 /// primitive as a fixed tag `single-input-arity` on
4317 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4318 /// surface's `single-input-arity` fixed tag on
4319 /// `POINT_FIXED_TAG_ARMS` via
4320 /// [`Classification::input_arity_is_one`] directly. The
4321 /// two-surface parity contract holds by construction: both
4322 /// surfaces route through the SAME
4323 /// [`Classification::input_arity_is_one`] primitive after the
4324 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
4325 /// peer ([`Self::input_arity_is_many`]) closes the binary XOR
4326 /// partition on this axis — mirror of the calm-axis
4327 /// (`monotone-calm ⊕ coordination-required`), data-axis
4328 /// (`public-data ⊕ data-restricted`), and optimization-direction-
4329 /// axis (`prefers-lower-direction ⊕ prefers-higher-direction`)
4330 /// closures on this surface.
4331 ///
4332 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4333 /// preserves proofs; the classification-`point_type`-derived
4334 /// input-arity-axis derived-nullary-boolean probe body composes
4335 /// ONE resolver primitive ([`Self::resolved_classification`])
4336 /// with ONE [`Classification`] primitive
4337 /// ([`Classification::input_arity_is_one`]) so every downstream
4338 /// (the future `single-input-arity` fixed tag on the ephemeral
4339 /// surface in tatara-check, future DAG-composition input-arity
4340 /// validators keying on the single-input framing, future variant
4341 /// additions on
4342 /// [`crate::classification::ConvergencePointType`]) binds through
4343 /// the SAME `input_arity_is_one()` shape rather than restating
4344 /// either the resolver walk or the two-hop closed-set projection
4345 /// composition at the callsite. THEORY.md §VI.1 — generation over
4346 /// composition; a future
4347 /// [`crate::classification::ConvergencePointType`] variant lands
4348 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
4349 /// and both surfaces pick it up mechanically.
4350 #[must_use]
4351 pub fn input_arity_is_one(&self) -> bool {
4352 self.resolved_classification().input_arity_is_one()
4353 }
4354
4355 /// ANTISYMMETRIC PEER of [`Self::input_arity_is_one`] — does
4356 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
4357 /// slot project to `Arity::Many` under
4358 /// [`crate::classification::ConvergencePointType::input_arity`]?
4359 /// Byte-for-byte peer of
4360 /// [`crate::classification::Classification::input_arity_is_many`]
4361 /// wrapped through the [`Self::resolved_classification`] resolver
4362 /// so an operator-omitted `:classification` slot on
4363 /// `(defephemeral …)` still answers via the substrate default. The
4364 /// ONE ephemeral-surface substrate primitive that owns the
4365 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4366 /// multi-input side of the DAG-composition input-arity projection.
4367 ///
4368 /// # Seventeenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the input-arity axis
4369 ///
4370 /// Peer of the sixteen prior nullary-boolean substrate primitives
4371 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4372 /// [`Self::horizon_requires_metric_axes`],
4373 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4374 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4375 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4376 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4377 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4378 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4379 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`])
4380 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4381 /// bool) shape — the SEVENTEENTH peer overall and the SECOND peer
4382 /// threading the classification-`point_type`-derived input-arity
4383 /// axis on this surface. CLOSES the SEVENTH classification axis
4384 /// into the FULL binary XOR partition contract
4385 /// `input_arity_is_one ⊕ input_arity_is_many` on the ephemeral
4386 /// surface — the resolver-hop peer of the parent-composed
4387 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`.
4388 /// The resolver-hop shape is byte-identical across all seventeen
4389 /// peers.
4390 ///
4391 /// # Semantics — resolver hop + derived-nullary-boolean
4392 ///
4393 /// `input_arity_is_many()` returns `true` iff
4394 /// `self.resolved_classification().input_arity_is_many()`. The
4395 /// resolver returns the authored [`Classification`] when present
4396 /// and the substrate default [`Classification::gate_compute`] on
4397 /// absence. Because [`Classification::gate_compute`] carries
4398 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
4399 /// ephemeral spec with no `:classification` slot answers `true` —
4400 /// every unadorned `(defephemeral …)` lands in the multi-input
4401 /// bucket under the substrate default. Direct antisymmetric
4402 /// mirror of [`Self::input_arity_is_one`] on the SAME resolver
4403 /// walk + SAME projection through the SAME closed set.
4404 ///
4405 /// # Compounding — CLOSES the input-arity axis on the ephemeral surface
4406 ///
4407 /// The ephemeral require-tag classifier will compose this
4408 /// primitive as a fixed tag `multi-input-arity` on
4409 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4410 /// surface's `multi-input-arity` fixed tag on
4411 /// `POINT_FIXED_TAG_ARMS` via
4412 /// [`Classification::input_arity_is_many`] directly. The
4413 /// two-surface parity contract holds by construction: both
4414 /// surfaces route through the SAME
4415 /// [`Classification::input_arity_is_many`] primitive after the
4416 /// ephemeral surface pays ONE resolver hop. SECOND input-arity-
4417 /// axis peer CLOSES the axis into the FULL binary XOR partition
4418 /// contract on this surface — the resolver-hop peer of the
4419 /// parent-composed
4420 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`,
4421 /// mirror of the calm-axis (`monotone-calm ⊕
4422 /// coordination-required`), data-axis (`public-data ⊕
4423 /// data-restricted`), and optimization-direction-axis
4424 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
4425 /// closures on this surface — the SEVENTH classification axis to
4426 /// reach the closed XOR partition landmark on the ephemeral
4427 /// resolver-hop surface, opening the derived-typed-projection
4428 /// stratum on this surface for the first time.
4429 ///
4430 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4431 /// preserves proofs; the classification-`point_type`-derived
4432 /// input-arity-axis derived-nullary-boolean probe body composes
4433 /// ONE resolver primitive ([`Self::resolved_classification`])
4434 /// with ONE [`Classification`] primitive
4435 /// ([`Classification::input_arity_is_many`]) so every downstream
4436 /// (the future `multi-input-arity` fixed tag on the ephemeral
4437 /// surface in tatara-check, future DAG-composition input-arity
4438 /// validators keying on the multi-input framing, future variant
4439 /// additions on
4440 /// [`crate::classification::ConvergencePointType`]) binds through
4441 /// the SAME `input_arity_is_many()` shape rather than restating
4442 /// either `!self.input_arity_is_one()` or the two-hop
4443 /// `self.resolved_classification().point_type.input_arity().is_many()`
4444 /// chain at each callsite. THEORY.md §VI.1 — generation over
4445 /// composition; a future
4446 /// [`crate::classification::ConvergencePointType`] variant lands
4447 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
4448 /// and both surfaces pick it up mechanically.
4449 #[must_use]
4450 pub fn input_arity_is_many(&self) -> bool {
4451 self.resolved_classification().input_arity_is_many()
4452 }
4453
4454 /// Derived-boolean predicate — does this ephemeral spec's resolved
4455 /// [`Classification`]'s `point_type` slot project to `Arity::One`
4456 /// under
4457 /// [`crate::classification::ConvergencePointType::output_arity`]?
4458 /// Byte-for-byte peer of
4459 /// [`crate::classification::Classification::output_arity_is_one`]
4460 /// wrapped through the [`Self::resolved_classification`] resolver
4461 /// so an operator-omitted `:classification` slot on
4462 /// `(defephemeral …)` still answers via the substrate default. The
4463 /// ONE ephemeral-surface substrate primitive that owns the
4464 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4465 /// single-output side of the DAG-composition output-arity projection.
4466 ///
4467 /// # Eighteenth derived-nullary-boolean peer on the ephemeral surface — opens the output-arity axis
4468 ///
4469 /// Peer of the seventeen prior nullary-boolean substrate primitives
4470 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4471 /// [`Self::horizon_requires_metric_axes`],
4472 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4473 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4474 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4475 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4476 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4477 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4478 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
4479 /// [`Self::input_arity_is_many`]) on the ephemeral surface's
4480 /// (resolver-hop × derived-nullary-bool) shape — the EIGHTEENTH
4481 /// peer overall and the FIRST peer threading the classification-
4482 /// `point_type`-derived OUTPUT-arity axis on this surface. Opens
4483 /// the EIGHTH classification axis into the ephemeral fixed-tag
4484 /// algebra after the horizon, calm, data, point-type, substrate,
4485 /// optimization-direction, and input-arity axes. SECOND peer on
4486 /// the derived-typed-projection stratum of the ephemeral surface
4487 /// (after [`Self::input_arity_is_one`]) — composes an extra
4488 /// closed-set-level projection hop
4489 /// ([`crate::classification::ConvergencePointType::output_arity`])
4490 /// compared to the sibling `point_is_*` triple that walks the raw
4491 /// `point_type` slot through the resolver. The resolver-hop shape
4492 /// is byte-identical across all eighteen peers.
4493 ///
4494 /// # Distinctness from the input-arity axis
4495 ///
4496 /// The input-arity and output-arity axes carve the eight-variant
4497 /// [`crate::classification::ConvergencePointType`] closed set into
4498 /// DISTINCT partitions — six of the eight variants (`Fork |
4499 /// Broadcast | Join | Gate | Select | Reduce`) DISAGREE between the
4500 /// two projections, and only the two endomorphic variants
4501 /// (`Transform | Observe` — both `(One, One)`) agree. The ephemeral
4502 /// resolver-hop surface inherits this distinctness verbatim: the
4503 /// absent-classification baseline (`gate_compute` → `point_type:
4504 /// Gate`) FLIPS between the two axes — `input_arity_is_one` is
4505 /// `false` on the baseline but `output_arity_is_one` is `true`.
4506 /// So `output_arity_is_one` is NOT a redundant restatement of
4507 /// `input_arity_is_one` even after both wrap through the SAME
4508 /// resolver.
4509 ///
4510 /// # Semantics — resolver hop + derived-nullary-boolean
4511 ///
4512 /// `output_arity_is_one()` returns `true` iff
4513 /// `self.resolved_classification().output_arity_is_one()`. The
4514 /// resolver returns the authored [`Classification`] when present
4515 /// and the substrate default [`Classification::gate_compute`] on
4516 /// absence. Because [`Classification::gate_compute`] carries
4517 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
4518 /// ephemeral spec with no `:classification` slot answers `true` —
4519 /// every unadorned `(defephemeral …)` lands in the single-output
4520 /// bucket under the substrate default (`Gate` gates a many-to-one
4521 /// bucket dispatch, so the multi-output bucket only applies to
4522 /// operator-authored specs on the `Fork | Broadcast` arms). A
4523 /// regression that dropped the resolver hop, probed the wrong
4524 /// closed-set arm, or crossed the wires with the sibling
4525 /// [`crate::classification::ConvergencePointType::input_arity`]
4526 /// projection (which disagrees on six of the eight variants) fails
4527 /// HERE at ONE narrow substrate site before drifting through every
4528 /// unadorned ephemeral spec's DAG-composition output-arity audit.
4529 ///
4530 /// # Compounding — opens the output-arity axis on the ephemeral surface
4531 ///
4532 /// The ephemeral require-tag classifier will compose this
4533 /// primitive as a fixed tag `single-output-arity` on
4534 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4535 /// surface's `single-output-arity` fixed tag on
4536 /// `POINT_FIXED_TAG_ARMS` via
4537 /// [`Classification::output_arity_is_one`] directly. The
4538 /// two-surface parity contract holds by construction: both
4539 /// surfaces route through the SAME
4540 /// [`Classification::output_arity_is_one`] primitive after the
4541 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
4542 /// peer ([`Self::output_arity_is_many`]) closes the binary XOR
4543 /// partition on this axis — mirror of the input-arity-axis
4544 /// (`input_arity_is_one ⊕ input_arity_is_many`), the calm-axis
4545 /// (`monotone-calm ⊕ coordination-required`), the data-axis
4546 /// (`public-data ⊕ data-restricted`), and the optimization-
4547 /// direction-axis (`prefers-lower-direction ⊕
4548 /// prefers-higher-direction`) closures on this surface,
4549 /// completing the DAG-composition arity PAIR on the ephemeral
4550 /// derived-typed-projection stratum.
4551 ///
4552 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4553 /// preserves proofs; the classification-`point_type`-derived
4554 /// output-arity-axis derived-nullary-boolean probe body composes
4555 /// ONE resolver primitive ([`Self::resolved_classification`])
4556 /// with ONE [`Classification`] primitive
4557 /// ([`Classification::output_arity_is_one`]) so every downstream
4558 /// (the future `single-output-arity` fixed tag on the ephemeral
4559 /// surface in tatara-check, future DAG-composition output-arity
4560 /// validators keying on the single-output framing, future variant
4561 /// additions on
4562 /// [`crate::classification::ConvergencePointType`]) binds through
4563 /// the SAME `output_arity_is_one()` shape rather than restating
4564 /// either the resolver walk or the two-hop closed-set projection
4565 /// composition at the callsite. THEORY.md §VI.1 — generation over
4566 /// composition; a future
4567 /// [`crate::classification::ConvergencePointType`] variant lands
4568 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
4569 /// and both surfaces pick it up mechanically.
4570 #[must_use]
4571 pub fn output_arity_is_one(&self) -> bool {
4572 self.resolved_classification().output_arity_is_one()
4573 }
4574
4575 /// ANTISYMMETRIC PEER of [`Self::output_arity_is_one`] — does
4576 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
4577 /// slot project to `Arity::Many` under
4578 /// [`crate::classification::ConvergencePointType::output_arity`]?
4579 /// Byte-for-byte peer of
4580 /// [`crate::classification::Classification::output_arity_is_many`]
4581 /// wrapped through the [`Self::resolved_classification`] resolver
4582 /// so an operator-omitted `:classification` slot on
4583 /// `(defephemeral …)` still answers via the substrate default. The
4584 /// ONE ephemeral-surface substrate primitive that owns the
4585 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4586 /// multi-output side of the DAG-composition output-arity projection.
4587 ///
4588 /// # Nineteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the output-arity axis
4589 ///
4590 /// Peer of the eighteen prior nullary-boolean substrate primitives
4591 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4592 /// [`Self::horizon_requires_metric_axes`],
4593 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4594 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4595 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4596 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4597 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4598 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4599 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
4600 /// [`Self::input_arity_is_many`], [`Self::output_arity_is_one`])
4601 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4602 /// bool) shape — the NINETEENTH peer overall and the SECOND peer
4603 /// threading the classification-`point_type`-derived OUTPUT-arity
4604 /// axis on this surface. CLOSES the EIGHTH classification axis
4605 /// into the FULL binary XOR partition contract
4606 /// `output_arity_is_one ⊕ output_arity_is_many` on the ephemeral
4607 /// surface — the resolver-hop peer of the parent-composed
4608 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`.
4609 /// The resolver-hop shape is byte-identical across all nineteen
4610 /// peers. Completes the DAG-composition arity PAIR on the
4611 /// ephemeral derived-typed-projection stratum
4612 /// (`input_arity_is_{one,many}` + `output_arity_is_{one,many}` on
4613 /// the SAME resolver walk through the SAME closed set).
4614 ///
4615 /// # Semantics — resolver hop + derived-nullary-boolean
4616 ///
4617 /// `output_arity_is_many()` returns `true` iff
4618 /// `self.resolved_classification().output_arity_is_many()`. The
4619 /// resolver returns the authored [`Classification`] when present
4620 /// and the substrate default [`Classification::gate_compute`] on
4621 /// absence. Because [`Classification::gate_compute`] carries
4622 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
4623 /// ephemeral spec with no `:classification` slot answers `false` —
4624 /// every unadorned `(defephemeral …)` lands in the single-output
4625 /// bucket under the substrate default. Direct antisymmetric
4626 /// mirror of [`Self::output_arity_is_one`] on the SAME resolver
4627 /// walk + SAME projection through the SAME closed set.
4628 ///
4629 /// # Compounding — CLOSES the output-arity axis on the ephemeral surface
4630 ///
4631 /// The ephemeral require-tag classifier will compose this
4632 /// primitive as a fixed tag `multi-output-arity` on
4633 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4634 /// surface's `multi-output-arity` fixed tag on
4635 /// `POINT_FIXED_TAG_ARMS` via
4636 /// [`Classification::output_arity_is_many`] directly. The
4637 /// two-surface parity contract holds by construction: both
4638 /// surfaces route through the SAME
4639 /// [`Classification::output_arity_is_many`] primitive after the
4640 /// ephemeral surface pays ONE resolver hop. SECOND output-arity-
4641 /// axis peer CLOSES the axis into the FULL binary XOR partition
4642 /// contract on this surface — the resolver-hop peer of the
4643 /// parent-composed
4644 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`,
4645 /// mirror of the input-arity-axis (`input_arity_is_one ⊕
4646 /// input_arity_is_many`), the calm-axis (`monotone-calm ⊕
4647 /// coordination-required`), the data-axis (`public-data ⊕
4648 /// data-restricted`), and the optimization-direction-axis
4649 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
4650 /// closures on this surface — the EIGHTH classification axis to
4651 /// reach the closed XOR partition landmark on the ephemeral
4652 /// resolver-hop surface, completing the DAG-composition arity
4653 /// PAIR on the derived-typed-projection stratum of this surface.
4654 ///
4655 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4656 /// preserves proofs; the classification-`point_type`-derived
4657 /// output-arity-axis derived-nullary-boolean probe body composes
4658 /// ONE resolver primitive ([`Self::resolved_classification`])
4659 /// with ONE [`Classification`] primitive
4660 /// ([`Classification::output_arity_is_many`]) so every downstream
4661 /// (the future `multi-output-arity` fixed tag on the ephemeral
4662 /// surface in tatara-check, future DAG-composition output-arity
4663 /// validators keying on the multi-output framing, future variant
4664 /// additions on
4665 /// [`crate::classification::ConvergencePointType`]) binds through
4666 /// the SAME `output_arity_is_many()` shape rather than restating
4667 /// either `!self.output_arity_is_one()` or the two-hop
4668 /// `self.resolved_classification().point_type.output_arity().is_many()`
4669 /// chain at each callsite. THEORY.md §VI.1 — generation over
4670 /// composition; a future
4671 /// [`crate::classification::ConvergencePointType`] variant lands
4672 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
4673 /// and both surfaces pick it up mechanically.
4674 #[must_use]
4675 pub fn output_arity_is_many(&self) -> bool {
4676 self.resolved_classification().output_arity_is_many()
4677 }
4678
4679 /// True iff this ephemeral spec's [`Self::routing`] slot is
4680 /// populated AND the inner [`RoutingSpec`]'s derived
4681 /// [`RoutingForm`] equals `kind` — the substrate primitive that
4682 /// owns the (`&EphemeralSpec`, [`RoutingForm`]) → `bool` presence-
4683 /// probe shape on the sugar-surface type.
4684 ///
4685 /// # Peer to [`crate::routing::RoutingSpec::has_form`]
4686 ///
4687 /// [`RoutingSpec::has_form`] carries the same `(&self, RoutingForm)
4688 /// -> bool` signature on the inner routing carrier reached through
4689 /// the Option gate; this peer composes byte-identical semantics on
4690 /// [`EphemeralSpec`]'s direct `routing: Option<RoutingSpec>` slot,
4691 /// so both surfaces' `routing-form-<kind>` require-tag families
4692 /// route through the SAME `RoutingSpec::has_form` primitive. A
4693 /// future normalization at the probe shape (a widened return
4694 /// carrying the derived [`RoutingForm`] variant, a debug-build
4695 /// assertion on operator-set vs defaulted overrides on the
4696 /// `stable_name_claim` bool, a fleet-wide warn on `Stable`
4697 /// combined with content-hashed hostnames) lands at ONE site per
4698 /// surface and every downstream `routing-form-<kind>` require-tag
4699 /// family + closed-set audit dispatcher picks it up mechanically.
4700 ///
4701 /// # Semantics — Option-gated derived-scalar match
4702 ///
4703 /// [`EphemeralSpec::routing`] is an `Option<RoutingSpec>`: `None`
4704 /// on an in-cluster-only ephemeral env (no per-instance edges
4705 /// declared), `Some(_)` when the operator authored the
4706 /// `:routing (…)` slot. `has_routing_form(kind)` returns `true`
4707 /// iff the slot is `Some(spec)` AND `spec.has_form(kind)` — the
4708 /// Option-parent gate short-circuits `false` on `None` regardless
4709 /// of `kind`, and the reachable arm reads the DERIVED
4710 /// [`RoutingForm`] through the ONE substrate composer
4711 /// [`RoutingForm::from_is_stable`] over the child
4712 /// `stable_name_claim` bool (a `false` default projects to
4713 /// [`RoutingForm::Instance`], a `true` operator override projects
4714 /// to [`RoutingForm::Stable`]).
4715 ///
4716 /// # Corner — (Option-parent × derived-scalar-child)
4717 ///
4718 /// SAME corner as the point surface's `routing-form-<kind>`
4719 /// family (via [`crate::routing::RoutingSpec::has_form`] reached
4720 /// through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`)
4721 /// — both surfaces' Option-parent hop threads through the SAME
4722 /// `Option<RoutingSpec>` field name on their respective sugar
4723 /// structs. The [`From<EphemeralSpec>`] lowering copies
4724 /// `e.routing → ProcessSpec::routing` byte-for-byte at the
4725 /// [`From`] impl in this module (see the `routing: e.routing`
4726 /// line), so the SAME `Option<RoutingSpec>` reaches both
4727 /// surfaces' `routing-form-<kind>` families through the SAME
4728 /// [`RoutingSpec::has_form`] walk. Distinct from
4729 /// [`Self::has_teardown_policy`] on this same surface, which
4730 /// walks a required-scalar-child through no Option-parent hop.
4731 ///
4732 /// # Compounding
4733 ///
4734 /// The ephemeral require-tag classifier composes this primitive
4735 /// with the closed-set `FromStr` autoderived on [`RoutingForm`]
4736 /// through the `strip_and_classify_prefixed_kind` substrate to
4737 /// publish a `routing-form-<kind>` prefix family byte-for-byte
4738 /// symmetrical with the point surface's family via
4739 /// [`crate::routing::RoutingSpec::has_form`]. A future third
4740 /// [`RoutingForm`] variant added to `ALL` (a hypothetical
4741 /// `Anchored` for "hold the claim only for a specific
4742 /// generation") reaches BOTH surfaces' `routing-form-<kind>`
4743 /// prefix families through the SAME closed-set walk with no
4744 /// per-caller edit — the two-surface symmetry means adding a
4745 /// variant on the closed set publishes it in lockstep across
4746 /// every downstream consumer.
4747 ///
4748 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
4749 /// preserves proofs — the Option-gated derived-scalar-carrier
4750 /// presence-probe body lives at ONE substrate site per surface
4751 /// so every downstream (`routing-form-<kind>` require-tag families
4752 /// on both surfaces in tatara-check, closed-set audit dispatchers,
4753 /// future variant additions on [`RoutingForm`]) binds through the
4754 /// SAME `has(kind)` shape rather than restating the
4755 /// `spec.routing.as_ref().is_some_and(|r| r.has_form(kind))`
4756 /// closure body at each call site). THEORY.md §VI.1 (generation
4757 /// over composition — a future variant lands at ONE `ALL` entry +
4758 /// one `as_str` arm on the closed set and the probe picks it up
4759 /// mechanically without further per-consumer edits).
4760 #[must_use]
4761 pub fn has_routing_form(&self, kind: RoutingForm) -> bool {
4762 self.routing.as_ref().is_some_and(|r| r.has_form(kind))
4763 }
4764
4765 /// True iff at least one declared export in `self.exports` would
4766 /// fire on the given terminal-reached [`ProcessPhase`] — the peer
4767 /// of [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4768 /// on the [`EphemeralSpec`] surface.
4769 ///
4770 /// # Semantics — byte-identical to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4771 ///
4772 /// Both surfaces walk the SAME slice-level substrate primitive
4773 /// [`ExportSpecSliceExt::has_applicable_at`] on their respective
4774 /// `Vec<ExportSpec>` slot: [`EphemeralSpec`]'s `exports` field is
4775 /// copied byte-for-byte into `EphemeralLifetime::exports` at the
4776 /// `From<EphemeralSpec>` lowering, so a `has_applicable_exports_at`
4777 /// query on the authored ephemeral spec answers identically to a
4778 /// `has_applicable_exports` query on the lowered `EphemeralLifetime`.
4779 /// A regression at the compound `(when, phase) → fires_on(phase)`
4780 /// walk fails at [`ExportSpecSliceExt::has_applicable_at`]'s tests
4781 /// rather than as silent drift at either surface's inherent method.
4782 ///
4783 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4784 ///
4785 /// Same shape, same axis, same body — the point-domain surface
4786 /// composes through `spec.lifetime.resolved_ephemeral().is_some_and(
4787 /// |e| e.exports.has_applicable_at(phase))`; the ephemeral sugar
4788 /// surface reads `self.exports.has_applicable_at(phase)` directly
4789 /// because `EphemeralSpec` stores `exports: Vec<ExportSpec>` as a
4790 /// top-level field. Both routes bind through THIS ONE slice-level
4791 /// primitive so a future normalization (widening the trigger from
4792 /// a stored discriminator to a computed predicate, adding a phase
4793 /// that composes across multiple trigger arms, threading a
4794 /// per-export justification back for editor tooltips) lands at ONE
4795 /// site and every downstream inherits the shift by construction.
4796 ///
4797 /// # Compounding
4798 ///
4799 /// The ephemeral require-tag classifier composes this primitive
4800 /// with the closed-set [`ProcessPhase`]'s autoderived `FromStr`
4801 /// through the `strip_and_classify_prefixed_kind` substrate to
4802 /// publish an `exports-fire-on-<phase>` closed-set prefix family
4803 /// byte-for-byte symmetrical with the point surface's family via
4804 /// `spec.lifetime.resolved_ephemeral().is_some_and(|e|
4805 /// e.exports.has_applicable_at(phase))`. A future twelfth
4806 /// [`ProcessPhase`] variant reaches BOTH surfaces' prefix families
4807 /// through the ONE [`crate::export::ExportTrigger::fires_on`]
4808 /// exhaustive match — either the new phase inherits a per-trigger
4809 /// fire rule at that single substrate site or it collapses to
4810 /// `false` for every trigger (the current non-terminal tail),
4811 /// without a per-caller edit anywhere else.
4812 ///
4813 /// A future normalization at the compound `(when, phase) →
4814 /// fires_on(phase)` walk (a widening that returns the applicable
4815 /// exports themselves rather than a bool, a debug-build assertion
4816 /// on redundant `Always`-triggered exports coexisting with an
4817 /// `OnAttested` peer, a fleet-wide warn on empty-export ephemerals
4818 /// declaring `OnAttested` postconditions) lands at the ONE
4819 /// slice-level substrate primitive [`ExportSpecSliceExt::has_applicable_at`]
4820 /// both this method and [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4821 /// compose against — so the two struct-level union methods stay
4822 /// symmetric by construction.
4823 ///
4824 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
4825 /// proofs — the walk composes the SAME slice-level substrate
4826 /// primitive on both this ephemeral surface and the
4827 /// [`crate::lifetime::EphemeralLifetime`] surface, so a regression
4828 /// at the compound `(when, phase) → fires_on(phase)` chain fails
4829 /// at ONE site rather than as silent drift between the two peers).
4830 /// THEORY.md §VI.1 (generation over composition — a future
4831 /// [`ProcessPhase`] variant or a future [`crate::export::ExportTrigger`]
4832 /// variant reaches both `exports-fire-on-<phase>` require-tag
4833 /// surfaces mechanically through the SAME closed-set walk).
4834 #[must_use]
4835 pub fn has_applicable_exports_at(&self, phase: ProcessPhase) -> bool {
4836 self.exports.has_applicable_at(phase)
4837 }
4838}
4839
4840impl From<EphemeralSpec> for ProcessSpec {
4841 fn from(e: EphemeralSpec) -> Self {
4842 let classification = e.classification.unwrap_or_else(default_ephemeral_class);
4843 let mut spec = Self {
4844 identity: crate::spec::IdentitySpec {
4845 parent: e.parent,
4846 name_override: None,
4847 },
4848 classification,
4849 intent: Intent {
4850 aplicacao: Some(e.aplicacao),
4851 ..Intent::default()
4852 },
4853 boundary: Boundary {
4854 preconditions: e.preconditions,
4855 postconditions: e.postconditions,
4856 timeout: e.verify_timeout,
4857 },
4858 compliance: Default::default(),
4859 depends_on: vec![],
4860 signals: Default::default(),
4861 // Routes through the ONE substrate composer
4862 // [`Lifetime::ephemeral`] — pre-lift this was one of
4863 // ELEVEN+ hand-authored `Lifetime { ephemeral: Some(<e>),
4864 // .. }` sites past the ★★ PRIME-DIRECTIVE ≥ 2 threshold.
4865 // See the composer's doc-comment for the full migration
4866 // rationale.
4867 lifetime: Lifetime::ephemeral(EphemeralLifetime {
4868 ttl: e.ttl,
4869 teardown_policy: e.teardown,
4870 max_concurrent: e.max_concurrent,
4871 exports: e.exports,
4872 }),
4873 // R5 — propagate routing template (None = no edges).
4874 routing: e.routing,
4875 // EncapsulatesSpec isn't exposed via EphemeralSpec sugar;
4876 // operators wanting Adopt/Observe author the full
4877 // (defpoint …) form. Sugar path stays greenfield-Manage.
4878 encapsulates: None,
4879 suspended: false,
4880 };
4881 // Belt-and-suspenders: make sure exactly-one Intent invariant holds.
4882 spec.intent.nix = None;
4883 spec.intent.flux = None;
4884 spec.intent.lisp = None;
4885 spec.intent.container = None;
4886 spec.intent.guest = None;
4887 spec
4888 }
4889}
4890
4891fn default_ephemeral_class() -> Classification {
4892 // Delegates through the substrate `(Gate, Compute)` baseline owner
4893 // so the shape lives at ONE workspace-wide site — see
4894 // [`Classification::gate_compute`] for the pre-lift ten-callsite
4895 // duplication history and the sibling-default correspondence
4896 // pinned there.
4897 Classification::gate_compute()
4898}
4899
4900/// Compile a `(defephemeral …)` Lisp source into named `EphemeralSpec` values.
4901pub fn compile_ephemeral_source(
4902 src: &str,
4903) -> tatara_lisp::Result<Vec<tatara_lisp::NamedDefinition<EphemeralSpec>>> {
4904 tatara_lisp::compile_named::<EphemeralSpec>(src)
4905}
4906
4907#[cfg(test)]
4908mod tests {
4909 use super::*;
4910 use crate::boundary::{assert_slice_refinement_composition_laws, ConditionKind};
4911 use crate::classification::{
4912 Arity, CalmClassification, ConvergencePointType, DataClassification, Horizon, HorizonKind,
4913 OptimizationDirection, SubstrateType,
4914 };
4915 use crate::intent::IntentVariant;
4916 use crate::lifetime::LifetimeVariant;
4917
4918 /// LANDMARK PIN — the (ephemeral-surface test-fixture ×
4919 /// [`Classification::gate_compute_with_axis`] on horizon-nested
4920 /// axes) sweep equivalence. Nine ephemeral-surface probe-sweep
4921 /// tests in this module (`has_horizon_kind_*`,
4922 /// `has_optimization_direction_*`, `horizon_terminates_*`,
4923 /// `horizon_requires_metric_axes_*`, `horizon_terminates_xor_*`)
4924 /// pre-sweep restated the SAME `let mut c =
4925 /// Classification::gate_compute(); c.horizon = Horizon { <slot>:
4926 /// populated, ..Horizon::default() }` five-line fixture at each
4927 /// callsite, mutating exactly ONE horizon-nested slot to
4928 /// `populated`; post-sweep each callsite reads
4929 /// [`Classification::gate_compute_with_axis(populated)`] — one
4930 /// line — and the four-baseline-slot restatement lives at ONE
4931 /// substrate primitive. This pin asserts byte-parity between the
4932 /// pre-sweep hand-authored `Horizon` struct-literal shape (both
4933 /// the [`HorizonKind::kind`] mutation shape AND the
4934 /// [`OptimizationDirection`]-into-`Some(_)` mutation shape) and
4935 /// the post-sweep composer output on every variant of each closed
4936 /// set, so a regression that either (a) changed
4937 /// [`ClassificationAxis for HorizonKind`] to stomp a non-`kind`
4938 /// sub-slot, (b) changed [`ClassificationAxis for OptimizationDirection`]
4939 /// to drop the `Some(...)` wrap, or (c) reintroduced a whole-
4940 /// `Horizon`-reset shape that dropped a sibling sub-slot would
4941 /// fail HERE at ONE landmark site before landing at the peer
4942 /// probe-sweep pins that use the composer.
4943 ///
4944 /// Byte-for-byte peer of the sibling landmark
4945 /// `with_axis_optimization_direction_overlay_wraps_variant_in_some`
4946 /// on the point-surface classification-module tests — this pin
4947 /// carries the same substrate contract through to the ephemeral-
4948 /// surface tests that consume the composer.
4949 #[test]
4950 fn gate_compute_with_axis_on_horizon_nested_axes_matches_hand_authored_shape() {
4951 for kind in HorizonKind::ALL {
4952 let via_composer = Classification::gate_compute_with_axis(kind);
4953 let mut via_hand_authored = Classification::gate_compute();
4954 via_hand_authored.horizon = Horizon {
4955 kind,
4956 ..Horizon::default()
4957 };
4958 assert_eq!(
4959 via_composer, via_hand_authored,
4960 "HorizonKind::{kind:?}: composer vs pre-sweep hand-authored struct-literal drift",
4961 );
4962 }
4963 for direction in OptimizationDirection::ALL {
4964 let via_composer = Classification::gate_compute_with_axis(direction);
4965 let mut via_hand_authored = Classification::gate_compute();
4966 via_hand_authored.horizon = Horizon {
4967 direction: Some(direction),
4968 ..Horizon::default()
4969 };
4970 assert_eq!(
4971 via_composer, via_hand_authored,
4972 "OptimizationDirection::{direction:?}: composer vs pre-sweep hand-authored struct-literal drift",
4973 );
4974 }
4975 }
4976
4977 /// Primitive-owner pin — `EphemeralSpec::with_classification_axis`
4978 /// on a `classification: None` carrier produces an ephemeral spec
4979 /// whose `classification` slot is
4980 /// `Some(Classification::gate_compute_with_axis(axis))` byte-for-
4981 /// byte on every axis-variant, and preserves every non-
4982 /// classification slot at its pre-call value. A regression that
4983 /// (a) failed to wrap the composed [`Classification`] in `Some(_)`
4984 /// on the `None`-arm, (b) mutated a sibling slot on `EphemeralSpec`
4985 /// through the axis overlay, or (c) picked a different `None`-arm
4986 /// fill-through than the sibling
4987 /// [`Self::resolved_classification`] resolver would fail HERE.
4988 #[test]
4989 fn with_classification_axis_on_none_arm_fills_through_gate_compute() {
4990 fn baseline() -> EphemeralSpec {
4991 EphemeralSpec {
4992 aplicacao: demo_overlay(),
4993 ttl: "2h".into(),
4994 teardown: TeardownPolicy::OnAttested,
4995 max_concurrent: 3,
4996 postconditions: vec![],
4997 preconditions: vec![],
4998 verify_timeout: Some("30m".into()),
4999 classification: None,
5000 parent: Some("seph.1".into()),
5001 exports: vec![],
5002 routing: None,
5003 }
5004 }
5005 // Direct-scalar axes: composer output matches
5006 // `Classification::gate_compute_with_axis(axis)` byte-for-byte,
5007 // wrapped in `Some(_)`.
5008 for kind in ConvergencePointType::ALL {
5009 let via_composer = baseline().with_classification_axis(kind);
5010 assert_eq!(
5011 via_composer.classification,
5012 Some(Classification::gate_compute_with_axis(kind)),
5013 "ConvergencePointType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5014 );
5015 }
5016 for kind in SubstrateType::ALL {
5017 let via_composer = baseline().with_classification_axis(kind);
5018 assert_eq!(
5019 via_composer.classification,
5020 Some(Classification::gate_compute_with_axis(kind)),
5021 "SubstrateType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5022 );
5023 }
5024 for kind in CalmClassification::ALL {
5025 let via_composer = baseline().with_classification_axis(kind);
5026 assert_eq!(
5027 via_composer.classification,
5028 Some(Classification::gate_compute_with_axis(kind)),
5029 "CalmClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5030 );
5031 }
5032 for kind in DataClassification::ALL {
5033 let via_composer = baseline().with_classification_axis(kind);
5034 assert_eq!(
5035 via_composer.classification,
5036 Some(Classification::gate_compute_with_axis(kind)),
5037 "DataClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5038 );
5039 }
5040 // Horizon-nested axes: same shape through the trait's
5041 // sub-slot overlay.
5042 for kind in HorizonKind::ALL {
5043 let via_composer = baseline().with_classification_axis(kind);
5044 assert_eq!(
5045 via_composer.classification,
5046 Some(Classification::gate_compute_with_axis(kind)),
5047 "HorizonKind::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5048 );
5049 }
5050 for direction in OptimizationDirection::ALL {
5051 let via_composer = baseline().with_classification_axis(direction);
5052 assert_eq!(
5053 via_composer.classification,
5054 Some(Classification::gate_compute_with_axis(direction)),
5055 "OptimizationDirection::{direction:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
5056 );
5057 }
5058 // Non-classification slots: every one preserved byte-for-byte
5059 // across the overlay on every axis. Compare through JSON
5060 // round-trip since `AplicacaoIntent` / `ExportSpec` /
5061 // `RoutingSpec` do not carry `PartialEq`.
5062 for kind in ConvergencePointType::ALL {
5063 let via_composer = baseline().with_classification_axis(kind);
5064 let baseline_ref = baseline();
5065 assert_eq!(
5066 serde_json::to_string(&via_composer.aplicacao).unwrap(),
5067 serde_json::to_string(&baseline_ref.aplicacao).unwrap(),
5068 "aplicacao slot drifted under axis overlay for kind={kind:?}",
5069 );
5070 assert_eq!(via_composer.ttl, baseline_ref.ttl);
5071 assert_eq!(via_composer.teardown, baseline_ref.teardown);
5072 assert_eq!(via_composer.max_concurrent, baseline_ref.max_concurrent);
5073 assert_eq!(
5074 via_composer.postconditions.len(),
5075 baseline_ref.postconditions.len()
5076 );
5077 assert_eq!(
5078 via_composer.preconditions.len(),
5079 baseline_ref.preconditions.len()
5080 );
5081 assert_eq!(via_composer.verify_timeout, baseline_ref.verify_timeout);
5082 assert_eq!(via_composer.parent, baseline_ref.parent);
5083 assert_eq!(via_composer.exports.len(), baseline_ref.exports.len());
5084 assert!(via_composer.routing.is_none());
5085 }
5086 }
5087
5088 /// Primitive-owner pin —
5089 /// `EphemeralSpec::with_classification_axis` on a
5090 /// `classification: Some(prior)` carrier composes the axis
5091 /// overlay onto `prior` via [`ClassificationAxis::overlay`],
5092 /// preserving every OTHER axis slot on `prior`. Distinct from the
5093 /// `None`-arm pin above: the `Some(prior)` arm does NOT reset
5094 /// through [`Classification::gate_compute`], and consecutive
5095 /// `.with_classification_axis(...)` calls compose arbitrary
5096 /// N-axis conjunctions on the ephemeral surface with the same
5097 /// order-independence guarantee [`Classification::with_axis`]
5098 /// carries on distinct-slot axes.
5099 #[test]
5100 fn with_classification_axis_on_some_arm_chains_onto_prior() {
5101 fn baseline() -> EphemeralSpec {
5102 EphemeralSpec {
5103 aplicacao: demo_overlay(),
5104 ttl: "1h".into(),
5105 teardown: TeardownPolicy::Always,
5106 max_concurrent: 0,
5107 postconditions: vec![],
5108 preconditions: vec![],
5109 verify_timeout: None,
5110 classification: None,
5111 parent: None,
5112 exports: vec![],
5113 routing: None,
5114 }
5115 }
5116 // Prior authored point_type = Fork; overlay substrate = Storage
5117 // preserves the Fork point_type on the composed classification.
5118 let seeded = baseline().with_classification_axis(ConvergencePointType::Fork);
5119 let composed = seeded.with_classification_axis(SubstrateType::Storage);
5120 let classification = composed
5121 .classification
5122 .as_ref()
5123 .expect("with_classification_axis populates Some(_)");
5124 assert_eq!(classification.point_type, ConvergencePointType::Fork);
5125 assert_eq!(classification.substrate, SubstrateType::Storage);
5126 // Order independence on distinct-slot axes: swapping the axis
5127 // chain reads the SAME final classification.
5128 let forward = baseline()
5129 .with_classification_axis(ConvergencePointType::Fork)
5130 .with_classification_axis(SubstrateType::Storage)
5131 .with_classification_axis(CalmClassification::NonMonotone)
5132 .with_classification_axis(DataClassification::Pii)
5133 .classification
5134 .unwrap();
5135 let reverse = baseline()
5136 .with_classification_axis(DataClassification::Pii)
5137 .with_classification_axis(CalmClassification::NonMonotone)
5138 .with_classification_axis(SubstrateType::Storage)
5139 .with_classification_axis(ConvergencePointType::Fork)
5140 .classification
5141 .unwrap();
5142 assert_eq!(
5143 forward, reverse,
5144 "with_classification_axis chain must be order-independent on distinct-slot axes",
5145 );
5146 // Nested horizon-sub-slot overlays compose onto the same
5147 // carrier without stomping each other: the (kind, direction)
5148 // pair rides both chains.
5149 let paired = baseline()
5150 .with_classification_axis(HorizonKind::Asymptotic)
5151 .with_classification_axis(OptimizationDirection::Maximize)
5152 .classification
5153 .unwrap();
5154 assert_eq!(paired.horizon.kind, HorizonKind::Asymptotic);
5155 assert_eq!(
5156 paired.horizon.direction,
5157 Some(OptimizationDirection::Maximize)
5158 );
5159 }
5160
5161 /// Primitive-owner pin —
5162 /// `EphemeralSpec::with_classification_axis` composes byte-for-
5163 /// byte with the pre-sweep hand-authored two-shape callsite
5164 /// pattern that recurred at ~36 sites in
5165 /// `tatara-reconciler::bin::tatara-check`: either
5166 /// `let mut c = Classification::gate_compute(); c.<axis> =
5167 /// populated; EphemeralSpec { classification: Some(c), ..
5168 /// baseline }`, or the newer `let c =
5169 /// Classification::gate_compute_with_axis(populated); EphemeralSpec
5170 /// { classification: Some(c), ..baseline }`. Both restated
5171 /// pre-sweep shapes classify identically to
5172 /// `baseline.with_classification_axis(populated)` on every
5173 /// [`ClassificationAxis`] impl. A regression that drifted the
5174 /// composer body away from the pre-sweep shape (a stray reset of a
5175 /// non-classification slot, a stomping of a nested horizon sub-
5176 /// slot on the direct-scalar axes) fails HERE at ONE landmark site
5177 /// before drifting through the ~36 swept callsites in tatara-
5178 /// check.rs.
5179 #[test]
5180 fn with_classification_axis_matches_pre_sweep_hand_authored_shape() {
5181 fn baseline() -> EphemeralSpec {
5182 EphemeralSpec {
5183 aplicacao: demo_overlay(),
5184 ttl: "1h".into(),
5185 teardown: TeardownPolicy::Always,
5186 max_concurrent: 0,
5187 postconditions: vec![],
5188 preconditions: vec![],
5189 verify_timeout: None,
5190 classification: None,
5191 parent: None,
5192 exports: vec![],
5193 routing: None,
5194 }
5195 }
5196 // Direct-scalar axes: `<eph>.with_classification_axis(kind)`
5197 // matches the pre-sweep two-shape callsite pattern on every
5198 // ConvergencePointType variant.
5199 for kind in ConvergencePointType::ALL {
5200 let via_composer = baseline().with_classification_axis(kind);
5201 let mut hand_classification = Classification::gate_compute();
5202 hand_classification.point_type = kind;
5203 let via_hand = EphemeralSpec {
5204 classification: Some(hand_classification),
5205 ..baseline()
5206 };
5207 assert_eq!(
5208 via_composer.classification, via_hand.classification,
5209 "ConvergencePointType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5210 );
5211 }
5212 for kind in SubstrateType::ALL {
5213 let via_composer = baseline().with_classification_axis(kind);
5214 let mut hand_classification = Classification::gate_compute();
5215 hand_classification.substrate = kind;
5216 let via_hand = EphemeralSpec {
5217 classification: Some(hand_classification),
5218 ..baseline()
5219 };
5220 assert_eq!(
5221 via_composer.classification, via_hand.classification,
5222 "SubstrateType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5223 );
5224 }
5225 for kind in CalmClassification::ALL {
5226 let via_composer = baseline().with_classification_axis(kind);
5227 let mut hand_classification = Classification::gate_compute();
5228 hand_classification.calm = kind;
5229 let via_hand = EphemeralSpec {
5230 classification: Some(hand_classification),
5231 ..baseline()
5232 };
5233 assert_eq!(
5234 via_composer.classification, via_hand.classification,
5235 "CalmClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5236 );
5237 }
5238 for kind in DataClassification::ALL {
5239 let via_composer = baseline().with_classification_axis(kind);
5240 let mut hand_classification = Classification::gate_compute();
5241 hand_classification.data_classification = kind;
5242 let via_hand = EphemeralSpec {
5243 classification: Some(hand_classification),
5244 ..baseline()
5245 };
5246 assert_eq!(
5247 via_composer.classification, via_hand.classification,
5248 "DataClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5249 );
5250 }
5251 // Horizon-nested axes: composer matches the newer
5252 // `gate_compute_with_axis` shape used on the horizon-nested
5253 // sweep sites in tatara-check.rs.
5254 for kind in HorizonKind::ALL {
5255 let via_composer = baseline().with_classification_axis(kind);
5256 let via_hand = EphemeralSpec {
5257 classification: Some(Classification::gate_compute_with_axis(kind)),
5258 ..baseline()
5259 };
5260 assert_eq!(
5261 via_composer.classification, via_hand.classification,
5262 "HorizonKind::{kind:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
5263 );
5264 }
5265 for direction in OptimizationDirection::ALL {
5266 let via_composer = baseline().with_classification_axis(direction);
5267 let via_hand = EphemeralSpec {
5268 classification: Some(Classification::gate_compute_with_axis(direction)),
5269 ..baseline()
5270 };
5271 assert_eq!(
5272 via_composer.classification, via_hand.classification,
5273 "OptimizationDirection::{direction:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
5274 );
5275 }
5276 }
5277
5278 fn demo_overlay() -> AplicacaoIntent {
5279 AplicacaoIntent {
5280 chart_ref: "oci://ghcr.io/pleme-io/charts/lareira-demo-app".into(),
5281 version: "0.5.5".into(),
5282 profile: "all-in-one".into(),
5283 values_overlay: serde_json::json!({
5284 "cluster": { "name": "ephemeral-test-01", "namespace": "demo-test" },
5285 "data": { "mysql": { "persistence": { "enabled": false } } },
5286 "compliance": { "overlays": [] }
5287 }),
5288 release_name: Some("demo-app-consolidated".into()),
5289 target_namespace: Some("demo-test".into()),
5290 install_timeout: Some("25m".into()),
5291 }
5292 }
5293
5294 #[test]
5295 fn defaults_resolve_for_ephemeral_spec() {
5296 let e = EphemeralSpec {
5297 aplicacao: demo_overlay(),
5298 ttl: crate::lifetime::default_ephemeral_ttl(),
5299 teardown: TeardownPolicy::default(),
5300 max_concurrent: crate::lifetime::default_ephemeral_max_concurrent(),
5301 postconditions: vec![],
5302 preconditions: vec![],
5303 verify_timeout: None,
5304 classification: None,
5305 parent: None,
5306 exports: vec![],
5307 routing: None,
5308 };
5309 let ps: ProcessSpec = e.into();
5310 // Intent must resolve to Aplicacao.
5311 match ps.intent.variant().unwrap() {
5312 IntentVariant::Aplicacao(a) => {
5313 assert_eq!(a.profile, "all-in-one");
5314 assert_eq!(a.install_timeout.as_deref(), Some("25m"));
5315 }
5316 other => panic!("expected Aplicacao, got {other:?}"),
5317 }
5318 // Lifetime must resolve to Ephemeral with defaults.
5319 match ps.lifetime.variant().unwrap() {
5320 LifetimeVariant::Ephemeral(e) => {
5321 assert_eq!(e.ttl, "1h");
5322 assert_eq!(e.teardown_policy, TeardownPolicy::Always);
5323 }
5324 other => panic!("expected ephemeral, got {other:?}"),
5325 }
5326 // Default classification gates the Process at Compute/Internal.
5327 assert_eq!(ps.classification.point_type, ConvergencePointType::Gate);
5328 assert_eq!(ps.classification.substrate, SubstrateType::Compute);
5329 }
5330
5331 #[test]
5332 fn ephemeral_lisp_round_trip() {
5333 let src = r#"
5334 (defephemeral closed-loop-attest
5335 :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
5336 :version "0.5.5"
5337 :profile "all-in-one"
5338 :values-overlay (:cluster (:name "ephemeral-test-01")
5339 :data (:mysql (:persistence (:enabled #f)))
5340 :compliance (:overlays []))
5341 :release-name "demo-app-consolidated"
5342 :target-namespace "demo-test"
5343 :install-timeout "25m")
5344 :ttl "1h"
5345 :teardown OnAttested
5346 :max-concurrent 1
5347 :postconditions
5348 ((:kind HelmReleaseReleased
5349 :params (:name "demo-app-consolidated"
5350 :namespace "demo-test"))
5351 (:kind ClosedLoopAuth
5352 :params (:issuer (:service "demo-app-issuer" :port 8080)
5353 :consumer (:service "demo-app-gateway" :port 8000)
5354 :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
5355 "#;
5356 let defs = compile_ephemeral_source(src).expect("compile");
5357 assert_eq!(defs.len(), 1);
5358 let d = &defs[0];
5359 assert_eq!(d.name, "closed-loop-attest");
5360
5361 // Aplicacao body landed correctly.
5362 assert_eq!(
5363 d.spec.aplicacao.chart_ref,
5364 "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
5365 );
5366 assert_eq!(d.spec.aplicacao.profile, "all-in-one");
5367 assert_eq!(
5368 d.spec.aplicacao.target_namespace.as_deref(),
5369 Some("demo-test")
5370 );
5371 // values-overlay JSON is preserved.
5372 assert_eq!(
5373 d.spec.aplicacao.values_overlay["cluster"]["name"],
5374 "ephemeral-test-01"
5375 );
5376 // Boolean #f is preserved as a typed JSON bool (not the string "false").
5377 // tatara-lisp uses Scheme syntax for bools — `#t` / `#f`.
5378 assert_eq!(
5379 d.spec.aplicacao.values_overlay["data"]["mysql"]["persistence"]["enabled"],
5380 false
5381 );
5382
5383 // Lifetime knobs.
5384 assert_eq!(d.spec.ttl, "1h");
5385 assert_eq!(d.spec.teardown, TeardownPolicy::OnAttested);
5386 assert_eq!(d.spec.max_concurrent, 1);
5387
5388 // Two postconditions, both typed.
5389 assert_eq!(d.spec.postconditions.len(), 2);
5390 assert_eq!(
5391 d.spec.postconditions[0].kind,
5392 ConditionKind::HelmReleaseReleased
5393 );
5394 assert_eq!(d.spec.postconditions[1].kind, ConditionKind::ClosedLoopAuth);
5395
5396 // Lowers to ProcessSpec with the right shape.
5397 let ps: ProcessSpec = d.spec.clone().into();
5398 assert!(matches!(
5399 ps.intent.variant().unwrap(),
5400 IntentVariant::Aplicacao(_)
5401 ));
5402 assert!(matches!(
5403 ps.lifetime.variant().unwrap(),
5404 LifetimeVariant::Ephemeral(_)
5405 ));
5406 assert_eq!(ps.boundary.postconditions.len(), 2);
5407 }
5408
5409 /// End-to-end: the `:exports` slot on `(defephemeral …)` compiles
5410 /// into typed `ExportSpec` values via the Universal-Deserialize
5411 /// fallthrough — no per-domain keyword handlers needed.
5412 ///
5413 /// Receipts (empty-body source) is exercised via the Rust serde
5414 /// path only (see `export::tests::export_spec_serde_round_trip`).
5415 /// tatara-lisp's empty-kw-form `(:)` currently parses as a single-
5416 /// element array rather than a JSON `{}`; the same limitation
5417 /// affects `(:permanent)` on Lifetime. Tracked: extend the reader
5418 /// to accept `(:foo (:))` ⇒ `{"foo": {}}` as a typed-empty form,
5419 /// then re-enable Receipts here.
5420 #[test]
5421 fn exports_lisp_round_trip() {
5422 use crate::export::{ArtifactVariant, ChannelVariant, ExportTrigger, ReportFormat};
5423 let src = r#"
5424 (defephemeral closed-loop-attest
5425 :aplicacao (:chart-ref "oci://x"
5426 :version "1.0.0"
5427 :profile "minimal"
5428 :values-overlay ())
5429 :ttl "30m"
5430 :teardown OnAttested
5431 :exports
5432 ((:source (:test-report (:configmap "junit-results"
5433 :key "junit.xml"
5434 :format Junit))
5435 :channel (:nats-subject (:subject "pleme.pleme-dev.ephemeral.r1.test-report"
5436 :stream "EPHEMERAL_TEST_REPORTS"))
5437 :when OnAttested)
5438 (:source (:test-report (:configmap "junit-results"
5439 :key "junit.xml"
5440 :format Junit))
5441 :channel (:http-event (:signal-type "test-report"))
5442 :when Always)
5443 (:source (:run-marker (:labels (:run-id "r1" :phase "end")))
5444 :channel (:http-event (:signal-type "ephemeral-marker"))
5445 :when Always)))
5446 "#;
5447 let defs = compile_ephemeral_source(src).expect("compile");
5448 assert_eq!(defs.len(), 1);
5449 let d = &defs[0];
5450 assert_eq!(d.spec.exports.len(), 3);
5451
5452 // First export — TestReport → NATS subject + OnAttested
5453 let r = &d.spec.exports[0];
5454 match r.source.variant().unwrap() {
5455 ArtifactVariant::TestReport(tr) => {
5456 assert_eq!(tr.configmap, "junit-results");
5457 assert_eq!(tr.format, ReportFormat::Junit);
5458 }
5459 other => panic!("expected TestReport, got {other:?}"),
5460 }
5461 match r.channel.variant().unwrap() {
5462 ChannelVariant::NatsSubject(n) => {
5463 assert_eq!(n.subject, "pleme.pleme-dev.ephemeral.r1.test-report");
5464 assert_eq!(n.stream, "EPHEMERAL_TEST_REPORTS");
5465 }
5466 other => panic!("expected NatsSubject, got {other:?}"),
5467 }
5468 assert_eq!(r.when, ExportTrigger::OnAttested);
5469
5470 // Second export — TestReport → HTTP + Always
5471 let t = &d.spec.exports[1];
5472 match t.channel.variant().unwrap() {
5473 ChannelVariant::HttpEvent(h) => assert_eq!(h.signal_type, "test-report"),
5474 other => panic!("expected HttpEvent, got {other:?}"),
5475 }
5476 assert_eq!(t.when, ExportTrigger::Always);
5477
5478 // Third export — RunMarker (BTreeMap<String,String> round-trip).
5479 // tatara-lisp lowercases + normalizes keyword keys before
5480 // handing off to serde_json — kebab `:run-id` may land as
5481 // either `run-id` or `runId` depending on the reader path.
5482 // Accept either; the round-trip property under test is
5483 // "label survives compile" not "exact case-form".
5484 let m = &d.spec.exports[2];
5485 match m.source.variant().unwrap() {
5486 ArtifactVariant::RunMarker(rm) => {
5487 assert_eq!(rm.labels.len(), 2);
5488 let run_id = rm
5489 .labels
5490 .get("run-id")
5491 .or_else(|| rm.labels.get("runId"))
5492 .or_else(|| rm.labels.get("run_id"))
5493 .expect("run-id label present under some normalization");
5494 assert_eq!(run_id, "r1");
5495 assert_eq!(rm.labels.get("phase").map(String::as_str), Some("end"));
5496 }
5497 other => panic!("expected RunMarker, got {other:?}"),
5498 }
5499
5500 // Lowered ProcessSpec carries the exports through unchanged.
5501 let ps: ProcessSpec = d.spec.clone().into();
5502 assert_eq!(ps.lifetime.ephemeral.as_ref().unwrap().exports.len(), 3);
5503 }
5504
5505 // ── EphemeralSpec::has_condition_kind substrate pins ─────────────
5506 //
5507 // Fail-before-pass-after granularity:
5508 // `EphemeralSpec::has_condition_kind` did not exist before this
5509 // commit — the (preconditions ∪ postconditions .iter().any(|c|
5510 // c.kind == K)) union-probe shape lived at ONE struct-level site
5511 // (`Boundary::has_condition_kind` on the point surface's nested
5512 // [`Boundary`] slot). The lift adds the peer inherent method on the
5513 // [`EphemeralSpec`] sugar-surface so both struct-level union
5514 // callers compose against the SAME slice-level substrate primitive
5515 // [`ConditionSliceExt::has_kind`] in lockstep. A regression that
5516 // (a) hard-coded the arm to a single kind, (b) dropped the pre-
5517 // condition side of the OR (a re-inheritance of the pre-lift
5518 // ephemeral `closed-loop-auth` post-only shape at the union-tag
5519 // level), or (c) probed the wrong slot fails HERE at the substrate
5520 // primitive rather than as silent operator-facing drift at the
5521 // ephemeral `condition-<kind>` require-tag surface.
5522
5523 fn empty_ephemeral() -> EphemeralSpec {
5524 EphemeralSpec {
5525 aplicacao: AplicacaoIntent::chart_only("oci://ghcr.io/x", "1"),
5526 ttl: "1h".into(),
5527 teardown: TeardownPolicy::Always,
5528 max_concurrent: 0,
5529 postconditions: vec![],
5530 preconditions: vec![],
5531 verify_timeout: None,
5532 classification: None,
5533 parent: None,
5534 exports: vec![],
5535 routing: None,
5536 }
5537 }
5538
5539 fn cond(kind: ConditionKind) -> Condition {
5540 Condition {
5541 kind,
5542 params: serde_json::json!({}),
5543 }
5544 }
5545
5546 /// EMPTY-SPEC pin — a default [`EphemeralSpec`] (empty
5547 /// preconditions, empty postconditions) returns `false` for EVERY
5548 /// [`ConditionKind`]. Sweep `ConditionKind::ALL` so a new variant
5549 /// added without a matching arm in the presence probe surfaces at
5550 /// rustc's exhaustiveness gate on the ALL literal (arity forced by
5551 /// `[Self; 8]`) rather than as a silent false-positive at every
5552 /// downstream `condition-<kind>` ephemeral require-tag callsite.
5553 /// Byte-for-byte peer of
5554 /// `has_condition_kind_returns_false_on_empty_boundary_for_every_kind`
5555 /// on the [`Boundary`] surface.
5556 #[test]
5557 fn has_condition_kind_returns_false_on_empty_ephemeral_for_every_kind() {
5558 let spec = empty_ephemeral();
5559 for kind in ConditionKind::ALL {
5560 assert!(
5561 !spec.has_condition_kind(kind),
5562 "empty ephemeral spec must return false for {kind:?}",
5563 );
5564 }
5565 }
5566
5567 /// POSTCONDITION-only pin — an ephemeral spec that carries the
5568 /// kind on ONLY postconditions returns `true` for that kind,
5569 /// `false` for every other variant. Sweep the ALL × ALL cross so
5570 /// a regression that hard-coded the arm to a single kind or
5571 /// probed the wrong slot fails HERE at the substrate primitive.
5572 #[test]
5573 fn has_condition_kind_reads_ephemeral_postconditions_per_kind() {
5574 for populated in ConditionKind::ALL {
5575 let mut spec = empty_ephemeral();
5576 spec.postconditions.push(cond(populated));
5577 for query in ConditionKind::ALL {
5578 let expected = query == populated;
5579 assert_eq!(
5580 spec.has_condition_kind(query),
5581 expected,
5582 "ephemeral postcondition populated={populated:?}: \
5583 query {query:?} drifted",
5584 );
5585 }
5586 }
5587 }
5588
5589 /// PRECONDITION-only pin — mirrors the postcondition sweep on the
5590 /// other half of the union. Locks the union semantics on both
5591 /// halves separately so a regression that dropped the pre-
5592 /// condition side of the OR fails here even though the
5593 /// postcondition-side pin above passes.
5594 #[test]
5595 fn has_condition_kind_reads_ephemeral_preconditions_per_kind() {
5596 for populated in ConditionKind::ALL {
5597 let mut spec = empty_ephemeral();
5598 spec.preconditions.push(cond(populated));
5599 for query in ConditionKind::ALL {
5600 let expected = query == populated;
5601 assert_eq!(
5602 spec.has_condition_kind(query),
5603 expected,
5604 "ephemeral precondition populated={populated:?}: \
5605 query {query:?} drifted",
5606 );
5607 }
5608 }
5609 }
5610
5611 /// UNION pin — a kind that appears on preconditions returns
5612 /// `true` even when postconditions carries a DIFFERENT kind, and
5613 /// vice versa. Pins the OR-composition of the two halves so a
5614 /// regression that collapsed the union to an intersection (AND)
5615 /// silently reclassifies pre-only or post-only kinds as absent.
5616 /// Byte-for-byte peer of
5617 /// `has_condition_kind_unions_pre_and_post_condition_arms` on the
5618 /// [`Boundary`] surface.
5619 #[test]
5620 fn has_condition_kind_unions_pre_and_post_ephemeral_condition_arms() {
5621 let mut spec = empty_ephemeral();
5622 spec.preconditions
5623 .push(cond(ConditionKind::KustomizationHealthy));
5624 spec.postconditions
5625 .push(cond(ConditionKind::ClosedLoopAuth));
5626 assert!(
5627 spec.has_condition_kind(ConditionKind::KustomizationHealthy),
5628 "pre-only kind must resolve through the union",
5629 );
5630 assert!(
5631 spec.has_condition_kind(ConditionKind::ClosedLoopAuth),
5632 "post-only kind must resolve through the union",
5633 );
5634 assert!(
5635 !spec.has_condition_kind(ConditionKind::PromQL),
5636 "an absent kind must return false even with populated halves",
5637 );
5638 }
5639
5640 /// COMPOSITION pin — [`EphemeralSpec::has_condition_kind`] equals
5641 /// the OR of the two slice-level probes on the pre/post fields.
5642 /// The struct-level union body composes ONLY [`ConditionSliceExt::has_kind`]
5643 /// on each half; a regression that inlined a wide-net predicate
5644 /// (`.iter().any(|c| c.kind != kind).not()`, an `all` instead of
5645 /// `any`) drifts from the slice-level primitive here. Byte-for-
5646 /// byte peer of the
5647 /// `boundary_has_condition_kind_equals_or_of_half_slice_probes`
5648 /// composition pin on the [`Boundary`] surface.
5649 #[test]
5650 fn ephemeral_has_condition_kind_equals_or_of_half_slice_probes() {
5651 // Sweep every ConditionKind on both halves independently so the
5652 // cross of half-slice probes reaches the OR-composition body
5653 // exhaustively.
5654 for populated in ConditionKind::ALL {
5655 let mut spec = empty_ephemeral();
5656 spec.preconditions.push(cond(populated));
5657 spec.postconditions.push(cond(ConditionKind::PromQL));
5658 for query in ConditionKind::ALL {
5659 let via_or_of_halves =
5660 spec.preconditions.has_kind(query) || spec.postconditions.has_kind(query);
5661 assert_eq!(
5662 spec.has_condition_kind(query),
5663 via_or_of_halves,
5664 "populated={populated:?} query={query:?}: struct-level \
5665 union drifted from OR of slice-level probes",
5666 );
5667 }
5668 }
5669 }
5670
5671 // ── EphemeralSpec::has_(pre|post)condition_kind substrate pins ──
5672 //
5673 // Fail-before-pass-after granularity: the two half-slice arms did
5674 // not exist on the ephemeral surface before this commit — the
5675 // ephemeral require-tag classifier in `tatara-check` and the
5676 // `closed-loop-auth` fixed-tag arm reached
5677 // `spec.postconditions.has_kind(K)` through direct field access,
5678 // asymmetric with the union-arm [`EphemeralSpec::has_condition_kind`]
5679 // that already routed through the named struct method. The lift
5680 // closes the (precondition, postcondition, union) triad on the
5681 // ephemeral sugar surface so a future normalization at the
5682 // presence-probe shape lands at ONE site per surface for all
5683 // three arms.
5684
5685 /// EMPTY-SPEC pin — an ephemeral spec with no preconditions and
5686 /// no postconditions returns `false` for EVERY [`ConditionKind`]
5687 /// on both half-slice arms. Sweep `ConditionKind::ALL` so a new
5688 /// variant added without a matching arm surfaces at rustc's
5689 /// exhaustiveness gate on the ALL literal (arity forced by the
5690 /// closed-set array) rather than as a silent false-positive at
5691 /// every downstream require-tag callsite on the ephemeral
5692 /// surface.
5693 #[test]
5694 fn ephemeral_has_precondition_and_postcondition_kind_return_false_on_empty_spec() {
5695 let spec = empty_ephemeral();
5696 for kind in ConditionKind::ALL {
5697 assert!(
5698 !spec.has_precondition_kind(kind),
5699 "empty ephemeral must return false on precondition arm for {kind:?}",
5700 );
5701 assert!(
5702 !spec.has_postcondition_kind(kind),
5703 "empty ephemeral must return false on postcondition arm for {kind:?}",
5704 );
5705 }
5706 }
5707
5708 /// SLICE-SELECTIVITY pin (precondition arm) — an ephemeral spec
5709 /// with a kind on the precondition side ONLY resolves `true` at
5710 /// [`EphemeralSpec::has_precondition_kind`] and `false` at
5711 /// [`EphemeralSpec::has_postcondition_kind`]. Locks the (side-
5712 /// select, kind-select) partition so a regression that pointed
5713 /// the precondition arm at `self.postconditions` (a copy-paste
5714 /// from the sibling arm during the lift) surfaces HERE.
5715 #[test]
5716 fn ephemeral_has_precondition_kind_reads_preconditions_slice_only() {
5717 for populated in ConditionKind::ALL {
5718 let mut spec = empty_ephemeral();
5719 spec.preconditions.push(cond(populated));
5720 for query in ConditionKind::ALL {
5721 let expected_pre = query == populated;
5722 assert_eq!(
5723 spec.has_precondition_kind(query),
5724 expected_pre,
5725 "precondition-only populated={populated:?}: query {query:?} \
5726 drifted on ephemeral precondition arm",
5727 );
5728 assert!(
5729 !spec.has_postcondition_kind(query),
5730 "precondition-only populated={populated:?}: query {query:?} must \
5731 return false on ephemeral postcondition arm (postconditions is empty)",
5732 );
5733 }
5734 }
5735 }
5736
5737 /// SLICE-SELECTIVITY pin (postcondition arm) — mirror of the
5738 /// precondition-only sweep on the other half. Locks the
5739 /// postcondition arm's binding to `self.postconditions` so a
5740 /// regression that pointed it at `self.preconditions` fails HERE
5741 /// even though the precondition-arm pin above passes.
5742 #[test]
5743 fn ephemeral_has_postcondition_kind_reads_postconditions_slice_only() {
5744 for populated in ConditionKind::ALL {
5745 let mut spec = empty_ephemeral();
5746 spec.postconditions.push(cond(populated));
5747 for query in ConditionKind::ALL {
5748 let expected_post = query == populated;
5749 assert_eq!(
5750 spec.has_postcondition_kind(query),
5751 expected_post,
5752 "postcondition-only populated={populated:?}: query {query:?} \
5753 drifted on ephemeral postcondition arm",
5754 );
5755 assert!(
5756 !spec.has_precondition_kind(query),
5757 "postcondition-only populated={populated:?}: query {query:?} must \
5758 return false on ephemeral precondition arm (preconditions is empty)",
5759 );
5760 }
5761 }
5762 }
5763
5764 /// COMPOSITION-LAW pin — [`EphemeralSpec::has_condition_kind`]
5765 /// equals `has_precondition_kind(k) || has_postcondition_kind(k)`
5766 /// at EVERY (pre-populated, post-populated, query) triple on
5767 /// `ConditionKind::ALL`. Byte-for-byte peer of the
5768 /// `boundary_has_condition_kind_composes_precondition_and_postcondition_arms`
5769 /// composition-law pin on the [`Boundary`] surface — the
5770 /// two-surface parity contract binds the ephemeral sugar type
5771 /// and the point-domain boundary type through the SAME
5772 /// (`condition_kind = precondition_kind ∨ postcondition_kind`)
5773 /// composition, so every downstream `condition-<K>` require-tag
5774 /// classifier on either surface inherits the composition
5775 /// mechanically.
5776 #[test]
5777 fn ephemeral_has_condition_kind_composes_precondition_and_postcondition_arms() {
5778 for pre_kind in ConditionKind::ALL {
5779 for post_kind in ConditionKind::ALL {
5780 let mut spec = empty_ephemeral();
5781 spec.preconditions.push(cond(pre_kind));
5782 spec.postconditions.push(cond(post_kind));
5783 for query in ConditionKind::ALL {
5784 let via_arms =
5785 spec.has_precondition_kind(query) || spec.has_postcondition_kind(query);
5786 assert_eq!(
5787 spec.has_condition_kind(query),
5788 via_arms,
5789 "ephemeral union arm drifted from OR of half-slice arms: \
5790 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5791 );
5792 }
5793 }
5794 }
5795 }
5796
5797 /// SUBSTRATE-DELEGATION pin — the two half-slice arms on the
5798 /// ephemeral surface delegate verbatim to
5799 /// [`crate::boundary::ConditionSliceExt::has_kind`] on the
5800 /// underlying [`Vec<Condition>`] slice, no inline reimplementation.
5801 /// Sweep the full `ConditionKind::ALL` × `ConditionKind::ALL`
5802 /// cross so a regression that inlined a divergent walk at either
5803 /// arm surfaces HERE at the substrate boundary rather than as
5804 /// silent skew between the struct-level arm and the slice-level
5805 /// primitive.
5806 #[test]
5807 fn ephemeral_has_precondition_and_postcondition_kind_delegate_to_slice_has_kind() {
5808 for populated in ConditionKind::ALL {
5809 let mut spec = empty_ephemeral();
5810 spec.preconditions.push(cond(populated));
5811 spec.postconditions.push(cond(populated));
5812 for query in ConditionKind::ALL {
5813 assert_eq!(
5814 spec.has_precondition_kind(query),
5815 spec.preconditions.has_kind(query),
5816 "ephemeral precondition arm must delegate to preconditions.has_kind: \
5817 populated={populated:?} query={query:?}",
5818 );
5819 assert_eq!(
5820 spec.has_postcondition_kind(query),
5821 spec.postconditions.has_kind(query),
5822 "ephemeral postcondition arm must delegate to postconditions.has_kind: \
5823 populated={populated:?} query={query:?}",
5824 );
5825 }
5826 }
5827 }
5828
5829 // ── EphemeralSpec::find_(pre|post|)condition_kind widened triad ──
5830 //
5831 // Fail-before-pass-after granularity: the three widened
5832 // `find_*_kind` arms did not exist on the ephemeral surface before
5833 // this commit — the (widened `Option<&Condition>` return) axis
5834 // lived at ONE struct-level site (`Boundary::find_condition_kind`
5835 // on the point surface's nested [`Boundary`] slot). The lift adds
5836 // the peer inherent methods on the [`EphemeralSpec`] sugar-surface
5837 // so both struct-level widened callers compose against the SAME
5838 // slice-level substrate primitive
5839 // [`crate::boundary::ConditionSliceExt::find_kind`] in lockstep.
5840 // A regression that (a) hard-coded the arm to a single kind, (b)
5841 // reversed the walk order on the union (postcondition first), or
5842 // (c) collapsed `or_else` to `and_then` (silently narrowing the
5843 // union to an intersection) fails HERE at the substrate primitive
5844 // rather than as silent operator-facing drift at the ephemeral
5845 // require-tag surface.
5846
5847 /// EMPTY-SPEC pin (find-triad) — a default [`EphemeralSpec`]
5848 /// (empty preconditions, empty postconditions) returns `None`
5849 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
5850 /// `ConditionKind::ALL` × three-arm cross so a new variant added
5851 /// without a matching arm surfaces at rustc's exhaustiveness gate
5852 /// on the ALL literal (arity forced by the closed-set array)
5853 /// rather than as a silent false-`Some` at every downstream
5854 /// widened callsite on the ephemeral surface.
5855 #[test]
5856 fn ephemeral_find_condition_kind_triad_returns_none_on_empty_spec() {
5857 let spec = empty_ephemeral();
5858 for kind in ConditionKind::ALL {
5859 assert!(
5860 spec.find_precondition_kind(kind).is_none(),
5861 "empty ephemeral must return None on precondition find arm for {kind:?}",
5862 );
5863 assert!(
5864 spec.find_postcondition_kind(kind).is_none(),
5865 "empty ephemeral must return None on postcondition find arm for {kind:?}",
5866 );
5867 assert!(
5868 spec.find_condition_kind(kind).is_none(),
5869 "empty ephemeral must return None on union find arm for {kind:?}",
5870 );
5871 }
5872 }
5873
5874 /// SUBSTRATE-DELEGATION pin (ephemeral find-triad) — the three
5875 /// widened `find_*_kind` methods on [`EphemeralSpec`] delegate
5876 /// verbatim to [`crate::boundary::ConditionSliceExt::find_kind`]
5877 /// on the underlying [`Vec<Condition>`] slices, no inline
5878 /// reimplementation. The `find_condition_kind` union walks
5879 /// preconditions first then postconditions via `Option::or_else`.
5880 /// Sweep `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
5881 /// so a regression that (a) inlined a divergent walk at either
5882 /// half-slice arm, (b) reversed the union walk order on the
5883 /// ephemeral surface only (breaking two-surface parity with
5884 /// [`crate::boundary::Boundary::find_condition_kind`]), or (c)
5885 /// collapsed `or_else` to `and_then` surfaces HERE at the substrate
5886 /// boundary. Byte-for-byte peer of the point-domain
5887 /// `find_condition_kind_triad_delegates_to_slice_find_kind` pin.
5888 #[test]
5889 fn ephemeral_find_condition_kind_triad_delegates_to_slice_find_kind() {
5890 for pre_kind in ConditionKind::ALL {
5891 for post_kind in ConditionKind::ALL {
5892 let mut spec = empty_ephemeral();
5893 spec.preconditions.push(cond(pre_kind));
5894 spec.postconditions.push(cond(post_kind));
5895 for query in ConditionKind::ALL {
5896 let via_pre = spec.preconditions.find_kind(query);
5897 let via_post = spec.postconditions.find_kind(query);
5898 assert_eq!(
5899 spec.find_precondition_kind(query).map(|c| c.kind),
5900 via_pre.map(|c| c.kind),
5901 "ephemeral precondition find arm must delegate: \
5902 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5903 );
5904 assert_eq!(
5905 spec.find_postcondition_kind(query).map(|c| c.kind),
5906 via_post.map(|c| c.kind),
5907 "ephemeral postcondition find arm must delegate: \
5908 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5909 );
5910 let expected_union = via_pre.or(via_post).map(|c| c.kind);
5911 assert_eq!(
5912 spec.find_condition_kind(query).map(|c| c.kind),
5913 expected_union,
5914 "ephemeral union find arm must equal precondition.or_else(postcondition): \
5915 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5916 );
5917 }
5918 }
5919 }
5920 }
5921
5922 /// PRECONDITION-PRECEDENCE pin (ephemeral) — a kind authored on
5923 /// BOTH sides returns the precondition-side [`Condition`] from
5924 /// `find_condition_kind`. Byte-for-byte peer of the point-domain
5925 /// `find_condition_kind_returns_precondition_side_on_dual_populated`
5926 /// pin, so the two-surface parity contract binds the walk order
5927 /// on both surfaces through ONE composition law. Uses two params-
5928 /// distinguishable [`Condition`]s so a regression on the ephemeral
5929 /// surface only that reversed the walk order surfaces at the
5930 /// returned params payload rather than silently at the presence
5931 /// bit.
5932 #[test]
5933 fn ephemeral_find_condition_kind_returns_precondition_side_on_dual_populated() {
5934 let mut spec = empty_ephemeral();
5935 spec.preconditions.push(Condition {
5936 kind: ConditionKind::ClosedLoopAuth,
5937 params: serde_json::json!({ "side": "pre" }),
5938 });
5939 spec.postconditions.push(Condition {
5940 kind: ConditionKind::ClosedLoopAuth,
5941 params: serde_json::json!({ "side": "post" }),
5942 });
5943 let hit = spec
5944 .find_condition_kind(ConditionKind::ClosedLoopAuth)
5945 .expect("dual-populated ephemeral spec must resolve Some");
5946 assert_eq!(
5947 hit.params.get("side").and_then(serde_json::Value::as_str),
5948 Some("pre"),
5949 "ephemeral find_condition_kind must walk preconditions first",
5950 );
5951 }
5952
5953 /// STRUCT-LEVEL DELEGATION pin (ephemeral has ↔ find) — the three
5954 /// [`EphemeralSpec`] `has_*_kind` arms equal their widened peers'
5955 /// `.is_some()` projection at EVERY (pre-populated, post-populated,
5956 /// query) triple on `ConditionKind::ALL`. Byte-for-byte peer of
5957 /// the point-domain
5958 /// `boundary_has_triad_equals_find_triad_is_some_projection` pin,
5959 /// so both surfaces' has/find refinement bridge stays symmetric by
5960 /// construction — a future consumer that reads
5961 /// `spec.has_condition_kind(k)` as sugar for
5962 /// `spec.find_condition_kind(k).is_some()` on either surface stays
5963 /// typed against the SAME truth table across the two-surface
5964 /// parity contract.
5965 #[test]
5966 fn ephemeral_has_triad_equals_find_triad_is_some_projection() {
5967 for pre_kind in ConditionKind::ALL {
5968 for post_kind in ConditionKind::ALL {
5969 let mut spec = empty_ephemeral();
5970 spec.preconditions.push(cond(pre_kind));
5971 spec.postconditions.push(cond(post_kind));
5972 for query in ConditionKind::ALL {
5973 assert_eq!(
5974 spec.has_precondition_kind(query),
5975 spec.find_precondition_kind(query).is_some(),
5976 "ephemeral precondition has/find bridge drifted: \
5977 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5978 );
5979 assert_eq!(
5980 spec.has_postcondition_kind(query),
5981 spec.find_postcondition_kind(query).is_some(),
5982 "ephemeral postcondition has/find bridge drifted: \
5983 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5984 );
5985 assert_eq!(
5986 spec.has_condition_kind(query),
5987 spec.find_condition_kind(query).is_some(),
5988 "ephemeral union has/find bridge drifted: \
5989 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5990 );
5991 }
5992 }
5993 }
5994 }
5995
5996 // ── EphemeralSpec::iter_(pre|post|)condition_kind widened triad ──
5997 //
5998 // Fail-before-pass-after granularity: the three widened
5999 // `iter_*_kind` arms did not exist on the ephemeral surface before
6000 // this commit — the (widened `impl Iterator<Item = &Condition>`
6001 // stream) axis lived at ONE struct-level site
6002 // (`Boundary::iter_condition_kind` on the point surface's nested
6003 // [`Boundary`] slot). The lift adds the peer inherent methods on
6004 // the [`EphemeralSpec`] sugar-surface so both struct-level widened
6005 // callers compose against the SAME slice-level substrate primitive
6006 // [`crate::boundary::ConditionSliceExt::iter_kind`] in lockstep.
6007 // A regression that (a) hard-coded the arm to a single kind, (b)
6008 // reversed the chain order on the union (postcondition first), or
6009 // (c) collapsed the chain to a `.zip(...)` (silently narrowing the
6010 // union to an intersection-by-position) fails HERE at the
6011 // substrate primitive rather than as silent operator-facing drift
6012 // at the ephemeral require-tag surface.
6013
6014 /// EMPTY-SPEC pin (iter-triad) — a default [`EphemeralSpec`]
6015 /// (empty preconditions, empty postconditions) yields nothing
6016 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
6017 /// `ConditionKind::ALL` × three-arm cross so a new variant added
6018 /// without a matching arm surfaces at rustc's exhaustiveness gate
6019 /// on the ALL literal rather than as a silent phantom-yield at
6020 /// every downstream widened callsite on the ephemeral surface.
6021 #[test]
6022 fn ephemeral_iter_condition_kind_triad_yields_nothing_on_empty_spec() {
6023 let spec = empty_ephemeral();
6024 for kind in ConditionKind::ALL {
6025 assert_eq!(
6026 spec.iter_precondition_kind(kind).count(),
6027 0,
6028 "empty ephemeral must yield nothing on precondition iter arm for {kind:?}",
6029 );
6030 assert_eq!(
6031 spec.iter_postcondition_kind(kind).count(),
6032 0,
6033 "empty ephemeral must yield nothing on postcondition iter arm for {kind:?}",
6034 );
6035 assert_eq!(
6036 spec.iter_condition_kind(kind).count(),
6037 0,
6038 "empty ephemeral must yield nothing on union iter arm for {kind:?}",
6039 );
6040 }
6041 }
6042
6043 /// SUBSTRATE-DELEGATION pin (ephemeral iter-triad) — the three
6044 /// widened `iter_*_kind` methods on [`EphemeralSpec`] delegate
6045 /// verbatim to [`crate::boundary::ConditionSliceExt::iter_kind`]
6046 /// on the underlying [`Vec<Condition>`] slices, no inline
6047 /// reimplementation. The `iter_condition_kind` union chains
6048 /// preconditions first then postconditions via
6049 /// [`Iterator::chain`]. Sweep
6050 /// `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
6051 /// so a regression that (a) inlined a divergent walk at either
6052 /// half-slice arm, (b) reversed the chain order on the ephemeral
6053 /// surface only (breaking two-surface parity with
6054 /// [`crate::boundary::Boundary::iter_condition_kind`]), or (c)
6055 /// collapsed the chain to a `.zip(...)` surfaces HERE at the
6056 /// substrate boundary. Byte-for-byte peer of the point-domain
6057 /// `iter_condition_kind_triad_delegates_to_slice_iter_kind` pin.
6058 #[test]
6059 fn ephemeral_iter_condition_kind_triad_delegates_to_slice_iter_kind() {
6060 for pre_kind in ConditionKind::ALL {
6061 for post_kind in ConditionKind::ALL {
6062 let mut spec = empty_ephemeral();
6063 spec.preconditions.push(cond(pre_kind));
6064 spec.postconditions.push(cond(post_kind));
6065 for query in ConditionKind::ALL {
6066 let via_pre: Vec<_> = spec
6067 .preconditions
6068 .iter_kind(query)
6069 .map(|c| c.kind)
6070 .collect();
6071 let via_post: Vec<_> = spec
6072 .postconditions
6073 .iter_kind(query)
6074 .map(|c| c.kind)
6075 .collect();
6076 assert_eq!(
6077 spec.iter_precondition_kind(query)
6078 .map(|c| c.kind)
6079 .collect::<Vec<_>>(),
6080 via_pre,
6081 "ephemeral precondition iter arm must delegate: \
6082 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6083 );
6084 assert_eq!(
6085 spec.iter_postcondition_kind(query)
6086 .map(|c| c.kind)
6087 .collect::<Vec<_>>(),
6088 via_post,
6089 "ephemeral postcondition iter arm must delegate: \
6090 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6091 );
6092 let mut expected_union = via_pre.clone();
6093 expected_union.extend(via_post.iter().copied());
6094 assert_eq!(
6095 spec.iter_condition_kind(query)
6096 .map(|c| c.kind)
6097 .collect::<Vec<_>>(),
6098 expected_union,
6099 "ephemeral union iter arm must chain precondition ⨟ postcondition: \
6100 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6101 );
6102 }
6103 }
6104 }
6105 }
6106
6107 /// PRECONDITION-PRECEDENCE pin (ephemeral iter) — a kind
6108 /// authored on BOTH sides yields precondition-side matches
6109 /// FIRST in the union chain. Byte-for-byte peer of the
6110 /// point-domain
6111 /// `iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated`
6112 /// pin — the two-surface parity contract binds the chain order
6113 /// on both surfaces through ONE composition law. Uses two
6114 /// params-distinguishable [`Condition`]s so a regression on the
6115 /// ephemeral surface only that reversed the chain order surfaces
6116 /// at the returned params payload rather than silently at the
6117 /// count.
6118 #[test]
6119 fn ephemeral_iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated()
6120 {
6121 let mut spec = empty_ephemeral();
6122 spec.preconditions.push(Condition {
6123 kind: ConditionKind::ClosedLoopAuth,
6124 params: serde_json::json!({ "side": "pre-1" }),
6125 });
6126 spec.postconditions.push(Condition {
6127 kind: ConditionKind::ClosedLoopAuth,
6128 params: serde_json::json!({ "side": "post-1" }),
6129 });
6130 spec.postconditions.push(Condition {
6131 kind: ConditionKind::ClosedLoopAuth,
6132 params: serde_json::json!({ "side": "post-2" }),
6133 });
6134 let sides: Vec<_> = spec
6135 .iter_condition_kind(ConditionKind::ClosedLoopAuth)
6136 .map(|c| {
6137 c.params
6138 .get("side")
6139 .and_then(serde_json::Value::as_str)
6140 .unwrap_or_default()
6141 .to_owned()
6142 })
6143 .collect();
6144 assert_eq!(
6145 sides,
6146 vec!["pre-1".to_owned(), "post-1".to_owned(), "post-2".to_owned(),],
6147 "ephemeral iter_condition_kind must yield every precondition-side match before \
6148 any postcondition-side match (chain order pinned by two-surface parity)",
6149 );
6150 }
6151
6152 /// STRUCT-LEVEL DELEGATION pin (find ↔ iter on EphemeralSpec) —
6153 /// the three [`EphemeralSpec`] `find_*_kind` arms equal their
6154 /// widened peers' `.next()` projection at EVERY (pre-populated,
6155 /// post-populated, query) triple on `ConditionKind::ALL`.
6156 /// Byte-for-byte peer of the point-domain
6157 /// `boundary_find_triad_equals_iter_triad_next_projection` pin,
6158 /// so both surfaces' find/iter refinement bridge stays symmetric
6159 /// by construction across the two-surface parity contract.
6160 #[test]
6161 fn ephemeral_find_triad_equals_iter_triad_next_projection() {
6162 for pre_kind in ConditionKind::ALL {
6163 for post_kind in ConditionKind::ALL {
6164 let mut spec = empty_ephemeral();
6165 spec.preconditions.push(cond(pre_kind));
6166 spec.postconditions.push(cond(post_kind));
6167 for query in ConditionKind::ALL {
6168 assert_eq!(
6169 spec.find_precondition_kind(query).map(|c| c.kind),
6170 spec.iter_precondition_kind(query).next().map(|c| c.kind),
6171 "ephemeral precondition find/iter bridge drifted: \
6172 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6173 );
6174 assert_eq!(
6175 spec.find_postcondition_kind(query).map(|c| c.kind),
6176 spec.iter_postcondition_kind(query).next().map(|c| c.kind),
6177 "ephemeral postcondition find/iter bridge drifted: \
6178 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6179 );
6180 assert_eq!(
6181 spec.find_condition_kind(query).map(|c| c.kind),
6182 spec.iter_condition_kind(query).next().map(|c| c.kind),
6183 "ephemeral union find/iter bridge drifted: \
6184 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6185 );
6186 }
6187 }
6188 }
6189 }
6190
6191 // ── EphemeralSpec count triad — scalar cardinality peers ─────────
6192 //
6193 // Byte-for-byte peers of the point-domain `Boundary`
6194 // `count_(pre|post|)condition_kind` triad, tested at the ephemeral
6195 // sugar surface. Same SUM composition on the union arm, same
6196 // slice-level substrate delegation, same composition-law bridge
6197 // against the widened iter refinement.
6198
6199 /// EMPTY-SPEC pin (count-triad) — a default [`EphemeralSpec`]
6200 /// counts `0` from every arm of the count triad for EVERY
6201 /// [`ConditionKind`].
6202 #[test]
6203 fn ephemeral_count_condition_kind_triad_returns_zero_on_empty_spec() {
6204 let spec = empty_ephemeral();
6205 for kind in ConditionKind::ALL {
6206 assert_eq!(
6207 spec.count_precondition_kind(kind),
6208 0,
6209 "empty ephemeral must count 0 on precondition arm for {kind:?}",
6210 );
6211 assert_eq!(
6212 spec.count_postcondition_kind(kind),
6213 0,
6214 "empty ephemeral must count 0 on postcondition arm for {kind:?}",
6215 );
6216 assert_eq!(
6217 spec.count_condition_kind(kind),
6218 0,
6219 "empty ephemeral must count 0 on union arm for {kind:?}",
6220 );
6221 }
6222 }
6223
6224 /// SUBSTRATE-DELEGATION pin (ephemeral count-triad) — the three
6225 /// widened `count_*_kind` methods on [`EphemeralSpec`] delegate
6226 /// verbatim to [`crate::boundary::ConditionSliceExt::count_kind`]
6227 /// on the underlying [`Vec<Condition>`] slices. The
6228 /// `count_condition_kind` union SUMS preconditions and
6229 /// postconditions. Byte-for-byte peer of the point-domain
6230 /// `boundary_count_condition_kind_triad_delegates_and_sums_slice_count_kind`
6231 /// pin; a regression that (a) subtracted rather than summed, (b)
6232 /// collapsed the sum to [`std::cmp::max`], or (c) inlined a
6233 /// divergent count at either half-slice arm on the ephemeral
6234 /// surface only (breaking two-surface parity with [`Boundary`])
6235 /// surfaces HERE.
6236 #[test]
6237 fn ephemeral_count_condition_kind_triad_delegates_and_sums_slice_count_kind() {
6238 for pre_kind in ConditionKind::ALL {
6239 for post_kind in ConditionKind::ALL {
6240 let mut spec = empty_ephemeral();
6241 spec.preconditions.push(cond(pre_kind));
6242 spec.postconditions.push(cond(post_kind));
6243 for query in ConditionKind::ALL {
6244 let via_pre = spec.preconditions.count_kind(query);
6245 let via_post = spec.postconditions.count_kind(query);
6246 assert_eq!(
6247 spec.count_precondition_kind(query),
6248 via_pre,
6249 "ephemeral precondition count arm must delegate: \
6250 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6251 );
6252 assert_eq!(
6253 spec.count_postcondition_kind(query),
6254 via_post,
6255 "ephemeral postcondition count arm must delegate: \
6256 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6257 );
6258 assert_eq!(
6259 spec.count_condition_kind(query),
6260 via_pre + via_post,
6261 "ephemeral union count arm must SUM pre + post: \
6262 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6263 );
6264 }
6265 }
6266 }
6267 }
6268
6269 /// STRUCT-LEVEL DELEGATION pin (count ↔ iter on EphemeralSpec) —
6270 /// the three [`EphemeralSpec`] `count_*_kind` arms equal their
6271 /// widened peers' `.count()` projection at EVERY (pre-populated
6272 /// twice, post-populated, query) triple. Byte-for-byte peer of
6273 /// the point-domain
6274 /// `boundary_count_triad_equals_iter_triad_count_projection`
6275 /// pin. Uses two-preconditions authoring so the union arm's SUM
6276 /// composition witnesses a nontrivial cardinality (rather than
6277 /// coinciding with the presence bit).
6278 #[test]
6279 fn ephemeral_count_triad_equals_iter_triad_count_projection() {
6280 for pre_kind in ConditionKind::ALL {
6281 for post_kind in ConditionKind::ALL {
6282 let mut spec = empty_ephemeral();
6283 spec.preconditions.push(cond(pre_kind));
6284 spec.preconditions.push(cond(pre_kind));
6285 spec.postconditions.push(cond(post_kind));
6286 for query in ConditionKind::ALL {
6287 assert_eq!(
6288 spec.count_precondition_kind(query),
6289 spec.iter_precondition_kind(query).count(),
6290 "ephemeral precondition count/iter bridge drifted: \
6291 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6292 );
6293 assert_eq!(
6294 spec.count_postcondition_kind(query),
6295 spec.iter_postcondition_kind(query).count(),
6296 "ephemeral postcondition count/iter bridge drifted: \
6297 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6298 );
6299 assert_eq!(
6300 spec.count_condition_kind(query),
6301 spec.iter_condition_kind(query).count(),
6302 "ephemeral union count/iter bridge drifted: \
6303 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6304 );
6305 }
6306 }
6307 }
6308 }
6309
6310 // ── EphemeralSpec distinct-set triad — substrate-delegation pin ──
6311 //
6312 // The (precondition, postcondition, condition-union) distinct-set
6313 // triad on [`EphemeralSpec`] delegates to the slice-level substrate
6314 // primitive [`crate::boundary::ConditionSliceExt::distinct_kinds`]
6315 // on each half-slice and composes the union via
6316 // [`Self::has_condition_kind`] over [`ConditionKind::ALL`] — byte-
6317 // for-byte peer of the point-surface distinct-set triad on
6318 // [`crate::boundary::Boundary`]. The two-surface parity contract
6319 // now covers FIVE refinements on the condition axis: the four
6320 // point-probe refinements (has / find / iter / count) AND the ONE
6321 // closed-set-inversion refinement (distinct-set) on both surfaces.
6322
6323 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-kind-count
6324 /// triad) — the three `distinct_*_kind_count` methods on
6325 /// [`EphemeralSpec`] delegate to the slice-level substrate
6326 /// primitive [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
6327 /// over the two `Vec<Condition>` slots and compose the union
6328 /// scalar via `ConditionKind::ALL.filter(|k|
6329 /// has_condition_kind(*k)).count()`. Byte-for-byte peer of the
6330 /// point-surface pin
6331 /// `distinct_condition_kind_count_triad_delegates_to_slice_distinct_kind_count`
6332 /// on [`crate::boundary::Boundary`] — the two-surface parity
6333 /// contract now binds every downstream scalar-cardinality consumer
6334 /// on either surface to the SAME closed-set walk through ONE
6335 /// substrate rather than through per-surface `.distinct_*_kinds().len()`
6336 /// re-materializations that pay for a heap allocation.
6337 #[test]
6338 fn ephemeral_distinct_condition_kind_count_triad_delegates_and_matches_distinct_kinds_len() {
6339 // Empty spec — every arm returns 0.
6340 let spec = empty_ephemeral();
6341 for kind in ConditionKind::ALL {
6342 assert_eq!(
6343 spec.distinct_precondition_kind_count(),
6344 0,
6345 "empty ephemeral spec must return 0 on distinct_precondition_kind_count, kind={kind:?}",
6346 );
6347 assert_eq!(
6348 spec.distinct_postcondition_kind_count(),
6349 0,
6350 "empty ephemeral spec must return 0 on distinct_postcondition_kind_count, kind={kind:?}",
6351 );
6352 assert_eq!(
6353 spec.distinct_condition_kind_count(),
6354 0,
6355 "empty ephemeral spec must return 0 on distinct_condition_kind_count, kind={kind:?}",
6356 );
6357 }
6358
6359 for pre_kind in ConditionKind::ALL {
6360 for post_kind in ConditionKind::ALL {
6361 let mut spec = empty_ephemeral();
6362 spec.preconditions.push(cond(pre_kind));
6363 spec.postconditions.push(cond(post_kind));
6364
6365 assert_eq!(
6366 spec.distinct_precondition_kind_count(),
6367 spec.preconditions.distinct_kind_count(),
6368 "EphemeralSpec::distinct_precondition_kind_count must delegate verbatim to \
6369 preconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6370 );
6371 assert_eq!(
6372 spec.distinct_precondition_kind_count(),
6373 spec.distinct_precondition_kinds().len(),
6374 "EphemeralSpec::distinct_precondition_kind_count must equal \
6375 distinct_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6376 );
6377 assert_eq!(
6378 spec.distinct_postcondition_kind_count(),
6379 spec.postconditions.distinct_kind_count(),
6380 "EphemeralSpec::distinct_postcondition_kind_count must delegate verbatim to \
6381 postconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6382 );
6383 assert_eq!(
6384 spec.distinct_postcondition_kind_count(),
6385 spec.distinct_postcondition_kinds().len(),
6386 "EphemeralSpec::distinct_postcondition_kind_count must equal \
6387 distinct_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6388 );
6389 let expected_union_count = if pre_kind == post_kind { 1 } else { 2 };
6390 assert_eq!(
6391 spec.distinct_condition_kind_count(),
6392 expected_union_count,
6393 "EphemeralSpec::distinct_condition_kind_count must count distinct union kinds \
6394 for pre={pre_kind:?} post={post_kind:?}",
6395 );
6396 assert_eq!(
6397 spec.distinct_condition_kind_count(),
6398 spec.distinct_condition_kinds().len(),
6399 "EphemeralSpec::distinct_condition_kind_count must equal \
6400 distinct_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6401 );
6402 }
6403 }
6404 }
6405
6406 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-set triad)
6407 /// — the three `distinct_*_kinds` methods on [`EphemeralSpec`]
6408 /// delegate to the slice-level substrate primitive over the two
6409 /// `Vec<Condition>` slots and compose the union via
6410 /// `ConditionKind::ALL.filter(|k| has_condition_kind(*k))`. Byte-
6411 /// for-byte peer of the point-surface pin
6412 /// `distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds`
6413 /// on [`crate::boundary::Boundary`] — the two-surface parity
6414 /// contract binds every downstream distinct-set consumer on either
6415 /// surface to the SAME closed-set-inversion primitive through ONE
6416 /// substrate rather than through per-surface re-authored sweeps.
6417 #[test]
6418 fn ephemeral_distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds() {
6419 for pre_kind in ConditionKind::ALL {
6420 for post_kind in ConditionKind::ALL {
6421 let mut spec = empty_ephemeral();
6422 spec.preconditions.push(cond(pre_kind));
6423 spec.postconditions.push(cond(post_kind));
6424
6425 assert_eq!(
6426 spec.distinct_precondition_kinds(),
6427 spec.preconditions.distinct_kinds(),
6428 "EphemeralSpec::distinct_precondition_kinds must delegate verbatim to \
6429 preconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
6430 );
6431 assert_eq!(
6432 spec.distinct_postcondition_kinds(),
6433 spec.postconditions.distinct_kinds(),
6434 "EphemeralSpec::distinct_postcondition_kinds must delegate verbatim to \
6435 postconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
6436 );
6437 let expected_union: Vec<_> = ConditionKind::ALL
6438 .into_iter()
6439 .filter(|k| pre_kind == *k || post_kind == *k)
6440 .collect();
6441 assert_eq!(
6442 spec.distinct_condition_kinds(),
6443 expected_union,
6444 "EphemeralSpec::distinct_condition_kinds must equal ConditionKind::ALL-ordered \
6445 set-union of the two half-slice distinct-sets for pre={pre_kind:?} post={post_kind:?}",
6446 );
6447 }
6448 }
6449 }
6450
6451 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set triad) —
6452 /// the three `missing_*_kinds` methods on [`EphemeralSpec`]
6453 /// delegate to the slice-level substrate primitive
6454 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over the
6455 /// two `Vec<Condition>` slots and compose the union via
6456 /// `ConditionKind::ALL.filter(|k| !has_condition_kind(*k))`. Sweep
6457 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
6458 /// `missing_condition_kinds_triad_delegates_to_slice_missing_kinds`
6459 /// on the point-domain [`crate::boundary::Boundary`] surface —
6460 /// both peers compose against the SAME slice-level substrate
6461 /// primitive so a regression at the per-slice complement walk
6462 /// fails at that primitive's tests rather than as silent drift at
6463 /// either struct-level arm.
6464 #[test]
6465 fn ephemeral_missing_condition_kinds_triad_delegates_to_slice_missing_kinds() {
6466 // Empty ephemeral spec — every arm returns ConditionKind::ALL.
6467 let empty = empty_ephemeral();
6468 let all_kinds = ConditionKind::ALL.to_vec();
6469 assert_eq!(
6470 empty.missing_precondition_kinds(),
6471 all_kinds,
6472 "empty ephemeral spec must return ConditionKind::ALL on missing_precondition_kinds",
6473 );
6474 assert_eq!(
6475 empty.missing_postcondition_kinds(),
6476 all_kinds,
6477 "empty ephemeral spec must return ConditionKind::ALL on missing_postcondition_kinds",
6478 );
6479 assert_eq!(
6480 empty.missing_condition_kinds(),
6481 all_kinds,
6482 "empty ephemeral spec must return ConditionKind::ALL on missing_condition_kinds",
6483 );
6484
6485 for pre_kind in ConditionKind::ALL {
6486 for post_kind in ConditionKind::ALL {
6487 let mut spec = empty_ephemeral();
6488 spec.preconditions.push(cond(pre_kind));
6489 spec.postconditions.push(cond(post_kind));
6490
6491 assert_eq!(
6492 spec.missing_precondition_kinds(),
6493 spec.preconditions.missing_kinds(),
6494 "EphemeralSpec::missing_precondition_kinds must delegate verbatim to \
6495 preconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
6496 );
6497 assert_eq!(
6498 spec.missing_postcondition_kinds(),
6499 spec.postconditions.missing_kinds(),
6500 "EphemeralSpec::missing_postcondition_kinds must delegate verbatim to \
6501 postconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
6502 );
6503 // Union: a kind is missing from the union iff it is
6504 // missing from BOTH half-slices (SET-INTERSECTION).
6505 let expected_union: Vec<_> = ConditionKind::ALL
6506 .into_iter()
6507 .filter(|k| pre_kind != *k && post_kind != *k)
6508 .collect();
6509 assert_eq!(
6510 spec.missing_condition_kinds(),
6511 expected_union,
6512 "EphemeralSpec::missing_condition_kinds must equal ConditionKind::ALL-ordered \
6513 set-INTERSECTION of the two half-slice missing-sets for pre={pre_kind:?} post={post_kind:?}",
6514 );
6515 // Partition invariant (distinct ∪ missing == ALL, disjoint).
6516 let distinct = spec.distinct_condition_kinds();
6517 let missing = spec.missing_condition_kinds();
6518 for kind in ConditionKind::ALL {
6519 assert!(
6520 distinct.contains(&kind) ^ missing.contains(&kind),
6521 "EphemeralSpec (distinct, missing) partition violated on {kind:?} for pre={pre_kind:?} post={post_kind:?}",
6522 );
6523 }
6524 assert_eq!(
6525 distinct.len() + missing.len(),
6526 ConditionKind::ALL.len(),
6527 "EphemeralSpec (distinct, missing) cardinality partition drift for pre={pre_kind:?} post={post_kind:?}",
6528 );
6529 }
6530 }
6531 }
6532
6533 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-kind-count triad)
6534 /// — the three `missing_*_kind_count` methods on [`EphemeralSpec`]
6535 /// delegate to the slice-level substrate primitive
6536 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
6537 /// the two `Vec<Condition>` slots and compose the union scalar via
6538 /// `ConditionKind::ALL.iter().filter(|k|
6539 /// !has_condition_kind(**k)).count()`. Sweep
6540 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
6541 /// `missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count`
6542 /// on the point-domain [`crate::boundary::Boundary`] surface —
6543 /// both peers compose against the SAME slice-level substrate
6544 /// primitive so a regression at the per-slice negated closed-set
6545 /// walk fails at that primitive's tests rather than as silent drift
6546 /// at either struct-level scalar-cardinality arm. Also pins the
6547 /// scalar-partition invariant `distinct_kind_count +
6548 /// missing_kind_count == ConditionKind::ALL.len()` per arrangement.
6549 #[test]
6550 fn ephemeral_missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count() {
6551 // Empty ephemeral spec — every arm returns ConditionKind::ALL.len().
6552 let empty = empty_ephemeral();
6553 let total = ConditionKind::ALL.len();
6554 assert_eq!(
6555 empty.missing_precondition_kind_count(),
6556 total,
6557 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_precondition_kind_count",
6558 );
6559 assert_eq!(
6560 empty.missing_postcondition_kind_count(),
6561 total,
6562 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_postcondition_kind_count",
6563 );
6564 assert_eq!(
6565 empty.missing_condition_kind_count(),
6566 total,
6567 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_condition_kind_count",
6568 );
6569
6570 for pre_kind in ConditionKind::ALL {
6571 for post_kind in ConditionKind::ALL {
6572 let mut spec = empty_ephemeral();
6573 spec.preconditions.push(cond(pre_kind));
6574 spec.postconditions.push(cond(post_kind));
6575
6576 // Half-slice arms delegate byte-for-byte to the slice
6577 // substrate primitive.
6578 assert_eq!(
6579 spec.missing_precondition_kind_count(),
6580 spec.preconditions.missing_kind_count(),
6581 "EphemeralSpec::missing_precondition_kind_count must delegate verbatim to \
6582 preconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6583 );
6584 assert_eq!(
6585 spec.missing_precondition_kind_count(),
6586 spec.missing_precondition_kinds().len(),
6587 "EphemeralSpec::missing_precondition_kind_count must equal \
6588 missing_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6589 );
6590 assert_eq!(
6591 spec.missing_postcondition_kind_count(),
6592 spec.postconditions.missing_kind_count(),
6593 "EphemeralSpec::missing_postcondition_kind_count must delegate verbatim to \
6594 postconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6595 );
6596 assert_eq!(
6597 spec.missing_postcondition_kind_count(),
6598 spec.missing_postcondition_kinds().len(),
6599 "EphemeralSpec::missing_postcondition_kind_count must equal \
6600 missing_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6601 );
6602 // Union arm equals missing_condition_kinds().len().
6603 assert_eq!(
6604 spec.missing_condition_kind_count(),
6605 spec.missing_condition_kinds().len(),
6606 "EphemeralSpec::missing_condition_kind_count must equal \
6607 missing_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6608 );
6609 // Scalar-partition invariant: distinct + missing == ALL.
6610 assert_eq!(
6611 spec.distinct_condition_kind_count() + spec.missing_condition_kind_count(),
6612 ConditionKind::ALL.len(),
6613 "EphemeralSpec (distinct, missing) scalar partition drift for pre={pre_kind:?} post={post_kind:?}",
6614 );
6615 }
6616 }
6617 }
6618
6619 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-distinct-kind
6620 /// triad) — the three `first_distinct_*_kind` methods on
6621 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
6622 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] over
6623 /// the two `Vec<Condition>` slots and compose the union via
6624 /// `ConditionKind::ALL.iter().copied().find(|k|
6625 /// has_condition_kind(*k))`. Byte-for-byte peer of
6626 /// `first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind`
6627 /// on the point-domain [`crate::boundary::Boundary`] surface — both
6628 /// peers compose against the SAME slice-level substrate primitive
6629 /// so a regression at the per-slice short-circuit walk fails at
6630 /// that primitive's tests rather than as silent drift at either
6631 /// struct-level earliest-element arm.
6632 #[test]
6633 fn ephemeral_first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind() {
6634 // Empty ephemeral spec — every arm returns None.
6635 let empty = empty_ephemeral();
6636 assert_eq!(
6637 empty.first_distinct_precondition_kind(),
6638 None,
6639 "empty ephemeral spec must return None on first_distinct_precondition_kind",
6640 );
6641 assert_eq!(
6642 empty.first_distinct_postcondition_kind(),
6643 None,
6644 "empty ephemeral spec must return None on first_distinct_postcondition_kind",
6645 );
6646 assert_eq!(
6647 empty.first_distinct_condition_kind(),
6648 None,
6649 "empty ephemeral spec must return None on first_distinct_condition_kind",
6650 );
6651
6652 for pre_kind in ConditionKind::ALL {
6653 for post_kind in ConditionKind::ALL {
6654 let mut spec = empty_ephemeral();
6655 spec.preconditions.push(cond(pre_kind));
6656 spec.postconditions.push(cond(post_kind));
6657
6658 assert_eq!(
6659 spec.first_distinct_precondition_kind(),
6660 spec.preconditions.first_distinct_kind(),
6661 "EphemeralSpec::first_distinct_precondition_kind must delegate verbatim to \
6662 preconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6663 );
6664 assert_eq!(
6665 spec.first_distinct_precondition_kind(),
6666 spec.distinct_precondition_kinds().first().copied(),
6667 "EphemeralSpec::first_distinct_precondition_kind must equal \
6668 distinct_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6669 );
6670 assert_eq!(
6671 spec.first_distinct_postcondition_kind(),
6672 spec.postconditions.first_distinct_kind(),
6673 "EphemeralSpec::first_distinct_postcondition_kind must delegate verbatim to \
6674 postconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6675 );
6676 assert_eq!(
6677 spec.first_distinct_postcondition_kind(),
6678 spec.distinct_postcondition_kinds().first().copied(),
6679 "EphemeralSpec::first_distinct_postcondition_kind must equal \
6680 distinct_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6681 );
6682 let expected_union = ConditionKind::ALL
6683 .into_iter()
6684 .find(|k| pre_kind == *k || post_kind == *k);
6685 assert_eq!(
6686 spec.first_distinct_condition_kind(),
6687 expected_union,
6688 "EphemeralSpec::first_distinct_condition_kind must equal earliest ALL entry \
6689 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6690 );
6691 assert_eq!(
6692 spec.first_distinct_condition_kind(),
6693 spec.distinct_condition_kinds().first().copied(),
6694 "EphemeralSpec::first_distinct_condition_kind must equal \
6695 distinct_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6696 );
6697 }
6698 }
6699 }
6700
6701 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-missing-kind triad)
6702 /// — the three `first_missing_*_kind` methods on [`EphemeralSpec`]
6703 /// delegate to the slice-level substrate primitive
6704 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`] over
6705 /// the two `Vec<Condition>` slots and compose the union via
6706 /// `ConditionKind::ALL.iter().copied().find(|k|
6707 /// !has_condition_kind(*k))`. Byte-for-byte peer of
6708 /// `first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind`
6709 /// on the point-domain [`crate::boundary::Boundary`] surface.
6710 #[test]
6711 fn ephemeral_first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind() {
6712 // Empty ephemeral spec — every arm returns Some(ConditionKind::ALL[0]).
6713 let empty = empty_ephemeral();
6714 let first = Some(ConditionKind::ALL[0]);
6715 assert_eq!(
6716 empty.first_missing_precondition_kind(),
6717 first,
6718 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_precondition_kind",
6719 );
6720 assert_eq!(
6721 empty.first_missing_postcondition_kind(),
6722 first,
6723 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_postcondition_kind",
6724 );
6725 assert_eq!(
6726 empty.first_missing_condition_kind(),
6727 first,
6728 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_condition_kind",
6729 );
6730
6731 for pre_kind in ConditionKind::ALL {
6732 for post_kind in ConditionKind::ALL {
6733 let mut spec = empty_ephemeral();
6734 spec.preconditions.push(cond(pre_kind));
6735 spec.postconditions.push(cond(post_kind));
6736
6737 assert_eq!(
6738 spec.first_missing_precondition_kind(),
6739 spec.preconditions.first_missing_kind(),
6740 "EphemeralSpec::first_missing_precondition_kind must delegate verbatim to \
6741 preconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6742 );
6743 assert_eq!(
6744 spec.first_missing_precondition_kind(),
6745 spec.missing_precondition_kinds().first().copied(),
6746 "EphemeralSpec::first_missing_precondition_kind must equal \
6747 missing_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6748 );
6749 assert_eq!(
6750 spec.first_missing_postcondition_kind(),
6751 spec.postconditions.first_missing_kind(),
6752 "EphemeralSpec::first_missing_postcondition_kind must delegate verbatim to \
6753 postconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6754 );
6755 assert_eq!(
6756 spec.first_missing_postcondition_kind(),
6757 spec.missing_postcondition_kinds().first().copied(),
6758 "EphemeralSpec::first_missing_postcondition_kind must equal \
6759 missing_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6760 );
6761 let expected_union = ConditionKind::ALL
6762 .into_iter()
6763 .find(|k| pre_kind != *k && post_kind != *k);
6764 assert_eq!(
6765 spec.first_missing_condition_kind(),
6766 expected_union,
6767 "EphemeralSpec::first_missing_condition_kind must equal earliest ALL entry \
6768 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6769 );
6770 assert_eq!(
6771 spec.first_missing_condition_kind(),
6772 spec.missing_condition_kinds().first().copied(),
6773 "EphemeralSpec::first_missing_condition_kind must equal \
6774 missing_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6775 );
6776 }
6777 }
6778 }
6779
6780 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-distinct-kind
6781 /// triad) — the three `last_distinct_*_kind` methods on
6782 /// [`EphemeralSpec`] delegate to the slice-level substrate
6783 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
6784 /// over the two `Vec<Condition>` slots and compose the union via
6785 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
6786 /// has_condition_kind(*k))`. Byte-for-byte peer of
6787 /// `last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind`
6788 /// on the point-domain [`crate::boundary::Boundary`] surface —
6789 /// both peers compose against the SAME slice-level substrate
6790 /// primitive so a regression at the per-slice REVERSED short-
6791 /// circuit walk fails at that primitive's tests rather than as
6792 /// silent drift at either struct-level latest-element arm.
6793 #[test]
6794 fn ephemeral_last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind() {
6795 // Empty ephemeral spec — every arm returns None.
6796 let empty = empty_ephemeral();
6797 assert_eq!(
6798 empty.last_distinct_precondition_kind(),
6799 None,
6800 "empty ephemeral spec must return None on last_distinct_precondition_kind",
6801 );
6802 assert_eq!(
6803 empty.last_distinct_postcondition_kind(),
6804 None,
6805 "empty ephemeral spec must return None on last_distinct_postcondition_kind",
6806 );
6807 assert_eq!(
6808 empty.last_distinct_condition_kind(),
6809 None,
6810 "empty ephemeral spec must return None on last_distinct_condition_kind",
6811 );
6812
6813 for pre_kind in ConditionKind::ALL {
6814 for post_kind in ConditionKind::ALL {
6815 let mut spec = empty_ephemeral();
6816 spec.preconditions.push(cond(pre_kind));
6817 spec.postconditions.push(cond(post_kind));
6818
6819 assert_eq!(
6820 spec.last_distinct_precondition_kind(),
6821 spec.preconditions.last_distinct_kind(),
6822 "EphemeralSpec::last_distinct_precondition_kind must delegate verbatim to \
6823 preconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6824 );
6825 assert_eq!(
6826 spec.last_distinct_precondition_kind(),
6827 spec.distinct_precondition_kinds().last().copied(),
6828 "EphemeralSpec::last_distinct_precondition_kind must equal \
6829 distinct_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6830 );
6831 assert_eq!(
6832 spec.last_distinct_postcondition_kind(),
6833 spec.postconditions.last_distinct_kind(),
6834 "EphemeralSpec::last_distinct_postcondition_kind must delegate verbatim to \
6835 postconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6836 );
6837 assert_eq!(
6838 spec.last_distinct_postcondition_kind(),
6839 spec.distinct_postcondition_kinds().last().copied(),
6840 "EphemeralSpec::last_distinct_postcondition_kind must equal \
6841 distinct_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6842 );
6843 let expected_union = ConditionKind::ALL
6844 .into_iter()
6845 .rev()
6846 .find(|k| pre_kind == *k || post_kind == *k);
6847 assert_eq!(
6848 spec.last_distinct_condition_kind(),
6849 expected_union,
6850 "EphemeralSpec::last_distinct_condition_kind must equal latest ALL entry \
6851 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6852 );
6853 assert_eq!(
6854 spec.last_distinct_condition_kind(),
6855 spec.distinct_condition_kinds().last().copied(),
6856 "EphemeralSpec::last_distinct_condition_kind must equal \
6857 distinct_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6858 );
6859 }
6860 }
6861 }
6862
6863 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-missing-kind triad)
6864 /// — the three `last_missing_*_kind` methods on [`EphemeralSpec`]
6865 /// delegate to the slice-level substrate primitive
6866 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] over
6867 /// the two `Vec<Condition>` slots and compose the union via
6868 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
6869 /// !has_condition_kind(*k))`. Byte-for-byte peer of
6870 /// `last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind`
6871 /// on the point-domain [`crate::boundary::Boundary`] surface.
6872 #[test]
6873 fn ephemeral_last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind() {
6874 // Empty ephemeral spec — every arm returns Some(*ConditionKind::ALL.last().unwrap()).
6875 let empty = empty_ephemeral();
6876 let last = ConditionKind::ALL.last().copied();
6877 assert_eq!(
6878 empty.last_missing_precondition_kind(),
6879 last,
6880 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_precondition_kind",
6881 );
6882 assert_eq!(
6883 empty.last_missing_postcondition_kind(),
6884 last,
6885 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_postcondition_kind",
6886 );
6887 assert_eq!(
6888 empty.last_missing_condition_kind(),
6889 last,
6890 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_condition_kind",
6891 );
6892
6893 for pre_kind in ConditionKind::ALL {
6894 for post_kind in ConditionKind::ALL {
6895 let mut spec = empty_ephemeral();
6896 spec.preconditions.push(cond(pre_kind));
6897 spec.postconditions.push(cond(post_kind));
6898
6899 assert_eq!(
6900 spec.last_missing_precondition_kind(),
6901 spec.preconditions.last_missing_kind(),
6902 "EphemeralSpec::last_missing_precondition_kind must delegate verbatim to \
6903 preconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6904 );
6905 assert_eq!(
6906 spec.last_missing_precondition_kind(),
6907 spec.missing_precondition_kinds().last().copied(),
6908 "EphemeralSpec::last_missing_precondition_kind must equal \
6909 missing_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6910 );
6911 assert_eq!(
6912 spec.last_missing_postcondition_kind(),
6913 spec.postconditions.last_missing_kind(),
6914 "EphemeralSpec::last_missing_postcondition_kind must delegate verbatim to \
6915 postconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6916 );
6917 assert_eq!(
6918 spec.last_missing_postcondition_kind(),
6919 spec.missing_postcondition_kinds().last().copied(),
6920 "EphemeralSpec::last_missing_postcondition_kind must equal \
6921 missing_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6922 );
6923 let expected_union = ConditionKind::ALL
6924 .into_iter()
6925 .rev()
6926 .find(|k| pre_kind != *k && post_kind != *k);
6927 assert_eq!(
6928 spec.last_missing_condition_kind(),
6929 expected_union,
6930 "EphemeralSpec::last_missing_condition_kind must equal latest ALL entry \
6931 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6932 );
6933 assert_eq!(
6934 spec.last_missing_condition_kind(),
6935 spec.missing_condition_kinds().last().copied(),
6936 "EphemeralSpec::last_missing_condition_kind must equal \
6937 missing_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6938 );
6939 }
6940 }
6941 }
6942
6943 // ── assert_slice_refinement_composition_laws — mirror invocations ──
6944 //
6945 // The substrate testkit primitive
6946 // [`crate::boundary::assert_slice_refinement_composition_laws`]
6947 // pins the FOUR composition laws that bind the
6948 // [`crate::boundary::ConditionSliceExt`] refinement algebra
6949 // (find ↔ iter, count ↔ iter, has ↔ find, has ↔ count) at ONE
6950 // call site per authored arrangement, sweeping
6951 // [`ConditionKind::ALL`]. The two ephemeral-surface tests below
6952 // dispatch the primitive against the two `Vec<Condition>` slots
6953 // ([`EphemeralSpec::preconditions`] +
6954 // [`EphemeralSpec::postconditions`]) authored through the
6955 // ephemeral-surface test-fixture — byte-for-byte peer of the
6956 // point-surface `slice_refinement_composition_laws_hold_across_authored_arrangements`
6957 // + `slice_refinement_composition_laws_hold_on_interleaved_duplicates`
6958 // pins on the [`crate::boundary::Boundary`] surface. Two-surface
6959 // parity contract: the substrate primitive holds on every slice
6960 // reachable through either the point-surface `.preconditions` /
6961 // `.postconditions` fields OR the ephemeral-surface's
6962 // eponymous field pair.
6963
6964 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate
6965 /// primitive [`assert_slice_refinement_composition_laws`] holds
6966 /// on both [`EphemeralSpec::preconditions`] and
6967 /// [`EphemeralSpec::postconditions`] slices for every populated-
6968 /// pair authored through the ephemeral-surface test-fixture.
6969 /// Byte-for-byte peer of
6970 /// `slice_refinement_composition_laws_hold_across_authored_arrangements`
6971 /// on the point surface.
6972 #[test]
6973 fn ephemeral_slice_refinement_composition_laws_hold_across_authored_arrangements() {
6974 let empty = empty_ephemeral();
6975 assert_slice_refinement_composition_laws(empty.preconditions.as_slice());
6976 assert_slice_refinement_composition_laws(empty.postconditions.as_slice());
6977
6978 for pre_kind in ConditionKind::ALL {
6979 for post_kind in ConditionKind::ALL {
6980 let mut spec = empty_ephemeral();
6981 spec.preconditions.push(cond(pre_kind));
6982 spec.postconditions.push(cond(post_kind));
6983 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
6984 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
6985 }
6986 }
6987
6988 for populated in ConditionKind::ALL {
6989 let mut spec = empty_ephemeral();
6990 spec.preconditions.push(cond(populated));
6991 spec.preconditions.push(cond(populated));
6992 spec.preconditions.push(cond(populated));
6993 spec.postconditions.push(cond(populated));
6994 spec.postconditions.push(cond(populated));
6995 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
6996 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
6997 }
6998 }
6999
7000 // ── assert_surface_union_composition_laws — ephemeral surface ────
7001 //
7002 // The substrate testkit macro
7003 // [`crate::assert_surface_union_composition_laws`] pins the FOUR
7004 // union composition laws (has: OR, find: or_else, iter: chain,
7005 // count: SUM) that bind the (pre, post, union) refinement triads
7006 // on the [`EphemeralSpec`] sugar-surface at ONE call site per
7007 // authored arrangement, sweeping [`ConditionKind::ALL`]. Byte-for-
7008 // byte peer of the point-surface
7009 // `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
7010 // / `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
7011 // pins on the [`crate::boundary::Boundary`] surface — the two-
7012 // surface parity contract binds every downstream `condition-<K>`
7013 // / `precondition-<K>` / `postcondition-<K>` require-tag classifier
7014 // on either surface to the SAME four union-composition operators
7015 // through ONE substrate primitive rather than through per-surface
7016 // author-time re-authored sweeps.
7017
7018 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate macro
7019 /// [`crate::assert_surface_union_composition_laws`] passes on
7020 /// [`EphemeralSpec`] for the four canonical authored arrangements
7021 /// (empty spec, precondition-only populated, postcondition-only
7022 /// populated, dual-populated sweep over `ALL × ALL`). Byte-for-byte
7023 /// peer of the point-surface
7024 /// `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
7025 /// pin — the two-surface parity contract binds every union
7026 /// composition law on both surfaces to the SAME substrate
7027 /// primitive.
7028 #[test]
7029 fn ephemeral_surface_union_composition_laws_hold_across_authored_arrangements() {
7030 let empty = empty_ephemeral();
7031 crate::assert_surface_union_composition_laws!(empty);
7032
7033 for populated in ConditionKind::ALL {
7034 let mut pre_only = empty_ephemeral();
7035 pre_only.preconditions.push(cond(populated));
7036 crate::assert_surface_union_composition_laws!(pre_only);
7037
7038 let mut post_only = empty_ephemeral();
7039 post_only.postconditions.push(cond(populated));
7040 crate::assert_surface_union_composition_laws!(post_only);
7041 }
7042
7043 for pre_kind in ConditionKind::ALL {
7044 for post_kind in ConditionKind::ALL {
7045 let mut dual = empty_ephemeral();
7046 dual.preconditions.push(cond(pre_kind));
7047 dual.postconditions.push(cond(post_kind));
7048 crate::assert_surface_union_composition_laws!(dual);
7049 }
7050 }
7051 }
7052
7053 /// SUBSTRATE PANEL pin (ephemeral surface, params-distinguishable
7054 /// duplicates) — the substrate macro holds on an [`EphemeralSpec`]
7055 /// whose two half-slices each carry duplicates of the same kind at
7056 /// multiple positions interleaved with a distinct kind. Byte-for-
7057 /// byte peer of the point-surface
7058 /// `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
7059 /// pin — the non-degenerate composition of every union arm on the
7060 /// sugar-surface binds against the SAME four monoid operators as
7061 /// the point-surface peer. A regression on the ephemeral surface
7062 /// only that (a) collapsed `find`'s `or_else` to `and_then`, (b)
7063 /// collapsed `iter`'s `chain` to `zip`, or (c) collapsed `count`'s
7064 /// SUM to `max` surfaces HERE, breaking two-surface parity.
7065 #[test]
7066 fn ephemeral_surface_union_composition_laws_hold_on_interleaved_duplicates() {
7067 let mut spec = empty_ephemeral();
7068 spec.preconditions.push(Condition {
7069 kind: ConditionKind::ClosedLoopAuth,
7070 params: serde_json::json!({ "side": "pre-1" }),
7071 });
7072 spec.preconditions.push(Condition {
7073 kind: ConditionKind::PromQL,
7074 params: serde_json::json!({ "query": "up" }),
7075 });
7076 spec.preconditions.push(Condition {
7077 kind: ConditionKind::ClosedLoopAuth,
7078 params: serde_json::json!({ "side": "pre-2" }),
7079 });
7080 spec.postconditions.push(Condition {
7081 kind: ConditionKind::PromQL,
7082 params: serde_json::json!({ "query": "healthy" }),
7083 });
7084 spec.postconditions.push(Condition {
7085 kind: ConditionKind::ClosedLoopAuth,
7086 params: serde_json::json!({ "side": "post-1" }),
7087 });
7088 crate::assert_surface_union_composition_laws!(spec);
7089 }
7090
7091 #[test]
7092 fn from_impl_clears_other_intent_variants() {
7093 // Even if someone constructs an EphemeralSpec by hand and the
7094 // resulting ProcessSpec is later mutated, the From bridge sets
7095 // every non-Aplicacao slot to None explicitly.
7096 let e = EphemeralSpec {
7097 aplicacao: demo_overlay(),
7098 ttl: "10m".into(),
7099 teardown: TeardownPolicy::Never,
7100 max_concurrent: 0,
7101 postconditions: vec![],
7102 preconditions: vec![],
7103 verify_timeout: None,
7104 classification: None,
7105 parent: Some("seph.1".into()),
7106 exports: vec![],
7107 routing: None,
7108 };
7109 let ps: ProcessSpec = e.into();
7110 assert!(ps.intent.nix.is_none());
7111 assert!(ps.intent.flux.is_none());
7112 assert!(ps.intent.lisp.is_none());
7113 assert!(ps.intent.container.is_none());
7114 assert!(ps.intent.guest.is_none());
7115 assert!(ps.intent.aplicacao.is_some());
7116 assert_eq!(ps.identity.parent.as_deref(), Some("seph.1"));
7117 }
7118
7119 // ── EphemeralSpec::has_teardown_policy substrate pins ────────────
7120 //
7121 // Fail-before-pass-after granularity:
7122 // `EphemeralSpec::has_teardown_policy` did not exist before this
7123 // commit — the (`self.teardown == kind`) scalar-carrier probe on
7124 // the sugar-surface [`EphemeralSpec`] lived only implicitly via
7125 // hand-authored comparisons at potential future call sites, with
7126 // no analogue to the peer
7127 // [`crate::lifetime::EphemeralLifetime::has_teardown_policy`] on
7128 // the point-surface carrier. The lift adds the peer inherent
7129 // method on the [`EphemeralSpec`] sugar-surface so both surfaces'
7130 // `teardown-policy-<kind>` require-tag families in
7131 // `tatara-reconciler::bin::tatara-check` compose against the SAME
7132 // scalar `==` shape in lockstep. A regression that (a) hard-coded
7133 // the arm to a single kind, (b) inverted the closed-set match
7134 // (silently returning `true` on non-matching variants), or (c)
7135 // probed the wrong slot (a stray comparison against `ttl` /
7136 // `max_concurrent`) fails HERE at the substrate primitive rather
7137 // than as silent operator-facing drift at the ephemeral
7138 // `teardown-policy-<kind>` require-tag surface.
7139
7140 /// STORED-slot pin — an ephemeral spec that carries a given
7141 /// [`TeardownPolicy`] returns `true` for that kind, `false` for
7142 /// every other variant. Sweep the [`TeardownPolicy::ALL`] × ALL
7143 /// cross so a regression that hard-coded the arm to a single kind
7144 /// or wired the closure to a fixed unrelated field fails HERE at
7145 /// the substrate primitive. Byte-for-byte peer of
7146 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_returns_true_iff_variant_matches`]
7147 /// on the point-surface [`crate::lifetime::EphemeralLifetime`]
7148 /// carrier — the two surfaces publish identical `==` scalar
7149 /// semantics on their respective `teardown` / `teardown_policy`
7150 /// slots.
7151 #[test]
7152 fn has_teardown_policy_returns_true_iff_ephemeral_teardown_matches_per_kind() {
7153 for populated in TeardownPolicy::ALL {
7154 let mut spec = empty_ephemeral();
7155 spec.teardown = populated;
7156 for query in TeardownPolicy::ALL {
7157 let expected = query == populated;
7158 assert_eq!(
7159 spec.has_teardown_policy(query),
7160 expected,
7161 "ephemeral teardown={populated:?}: query {query:?} drifted",
7162 );
7163 }
7164 }
7165 }
7166
7167 /// DEFAULT-SLOT pin — an [`EphemeralSpec`] whose `teardown` slot
7168 /// is [`TeardownPolicy::default`] (`Always`) returns `true` for
7169 /// `Always` and `false` for every other variant. The
7170 /// (required-scalar-child) corner has no absent state — a
7171 /// hand-authored spec that omits `:teardown` from the
7172 /// `(defephemeral …)` form IS configured for `Always`, and this
7173 /// pin locks the corner's default-arm short-circuit as identical
7174 /// to the (Option-parent × defaulted-scalar-child) corner's
7175 /// reachable arm on the point surface (both return `true` on
7176 /// `Always` only). Byte-for-byte peer of
7177 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_default_probes_always_only`]
7178 /// on the point-surface carrier.
7179 #[test]
7180 fn has_teardown_policy_default_probes_always_only_on_ephemeral() {
7181 let spec = EphemeralSpec {
7182 teardown: TeardownPolicy::default(),
7183 ..empty_ephemeral()
7184 };
7185 for kind in TeardownPolicy::ALL {
7186 let expected = kind == TeardownPolicy::Always;
7187 assert_eq!(
7188 spec.has_teardown_policy(kind),
7189 expected,
7190 "default ephemeral (teardown=Always) baseline: query {kind:?} must be {expected}",
7191 );
7192 }
7193 }
7194
7195 // ── derived-bool-predicate presence probe on EphemeralSpec ×
7196 // TeardownPolicy × ProcessPhase ──
7197 //
7198 // Fail-before-pass-after granularity:
7199 // [`EphemeralSpec::has_teardown_firing_on`] did not exist before
7200 // this commit — the ephemeral sugar surface's require-tag algebra
7201 // discriminated the teardown axis only by the RAW authored variant
7202 // (via `teardown-policy-<kind>`), never by the derived
7203 // [`ProcessPhase`] transition the stored policy fires on
7204 // ([`TeardownPolicy::should_teardown_on`]). Post-lift the shape
7205 // lives at ONE inherent method that byte-for-byte parallels
7206 // [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
7207 // on the point-surface carrier, and both surfaces' require-tag
7208 // classifiers publish a symmetric `teardown-fires-on-<phase>`
7209 // family through the SAME predicate.
7210
7211 /// TRUTH-TABLE DIAGONAL — for every [`TeardownPolicy`] variant,
7212 /// an [`EphemeralSpec`] whose `teardown` slot is set to that
7213 /// variant returns `has_teardown_firing_on(phase)` in agreement
7214 /// with [`TeardownPolicy::should_teardown_on`] for every
7215 /// [`ProcessPhase`] variant. Sweep [`TeardownPolicy::ALL`] ×
7216 /// [`ProcessPhase::ALL`] full cross so a regression that hard-
7217 /// coded the arm to a single policy, wired to the wrong field, or
7218 /// inverted the predicate direction fails HERE at the substrate
7219 /// primitive on the sugar surface (byte-for-byte peer of
7220 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase`]
7221 /// on the point carrier).
7222 #[test]
7223 fn has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase_on_ephemeral() {
7224 for populated in TeardownPolicy::ALL {
7225 let spec = EphemeralSpec {
7226 teardown: populated,
7227 ..empty_ephemeral()
7228 };
7229 for phase in ProcessPhase::ALL {
7230 assert_eq!(
7231 spec.has_teardown_firing_on(phase),
7232 populated.should_teardown_on(phase),
7233 "teardown={populated:?}, phase={phase:?}: predicate drift from \
7234 should_teardown_on projection",
7235 );
7236 }
7237 }
7238 }
7239
7240 /// TWO-SURFACE PARITY PIN — for every [`TeardownPolicy`] variant
7241 /// and every [`ProcessPhase`] variant, the sugar-surface probe
7242 /// and the lowered point-surface probe agree. The `EphemeralSpec
7243 /// → ProcessSpec` lowering routes the stored `teardown` slot
7244 /// through the SAME [`TeardownPolicy::should_teardown_on`]
7245 /// projection on both sides, so the sugar caller and the lowered
7246 /// caller can never disagree — a regression that (a) drifted
7247 /// [`Self::teardown`] between sugar and lowered, (b) rewired
7248 /// either probe body to bypass the shared substrate primitive, or
7249 /// (c) skewed the (policy, phase) truth table between the two
7250 /// surfaces fails HERE at the two-surface boundary rather than at
7251 /// the operator-facing require-tag classifier.
7252 #[test]
7253 fn has_teardown_firing_on_matches_point_peer_through_lowered_teardown_policy() {
7254 for populated in TeardownPolicy::ALL {
7255 let sugar = EphemeralSpec {
7256 teardown: populated,
7257 ..empty_ephemeral()
7258 };
7259 let lowered: ProcessSpec = sugar.clone().into();
7260 let lowered_eph = lowered
7261 .lifetime
7262 .resolved_ephemeral()
7263 .expect("lowered spec must be ephemeral");
7264 for phase in ProcessPhase::ALL {
7265 assert_eq!(
7266 sugar.has_teardown_firing_on(phase),
7267 lowered_eph.has_teardown_firing_on(phase),
7268 "sugar-vs-lowered predicate drift for teardown={populated:?}, phase={phase:?}",
7269 );
7270 }
7271 }
7272 }
7273
7274 // ── EphemeralSpec::resolved_classification + has_point_type pins ─────
7275 //
7276 // Fail-before-pass-after granularity: `resolved_classification` and
7277 // `has_point_type` did not exist pre-lift on `impl EphemeralSpec` — every
7278 // caller wanting the resolved [`Classification`] on the ephemeral
7279 // sugar-surface (currently zero; future ephemeral-surface classification-
7280 // axis require-tag families in `tatara-reconciler::bin::tatara-check`,
7281 // typed audit hooks, documentation generators listing the ephemeral
7282 // surface's known require-tag vocabulary) restated the two-line
7283 // `self.classification.as_ref().unwrap_or(&default_ephemeral_class())`
7284 // resolver body at their site. Post-lift both callers of the resolver
7285 // (`Self::has_point_type` and every future classification-axis peer)
7286 // route through ONE inherent method that shares the fill-through with
7287 // the sibling `From<EphemeralSpec> for ProcessSpec` lowering
7288 // byte-for-byte. A regression that (a) inverted the arm (`Some` filled
7289 // through the default), (b) drifted the default from the sibling
7290 // primitive `Classification::gate_compute()`, or (c) shifted the
7291 // `Cow<'_, Classification>` return shape (a stray `.clone()` on the
7292 // populated arm) fails HERE at the substrate primitive rather than as
7293 // silent operator-facing drift at a future
7294 // `point-type-<kind>` ephemeral require-tag surface.
7295
7296 /// AUTHORED-slot pin — an [`EphemeralSpec`] whose
7297 /// [`EphemeralSpec::classification`] slot names a concrete
7298 /// [`Classification`] returns [`Cow::Borrowed`] pointing at that
7299 /// authored value from [`Self::resolved_classification`]. Pins the
7300 /// populated-arm zero-allocation contract: a caller reading past
7301 /// the resolver sees the SAME byte address the operator authored,
7302 /// so the resolver does not silently clone the authored slot on
7303 /// the populated arm.
7304 #[test]
7305 fn resolved_classification_borrows_authored_slot() {
7306 let mut spec = empty_ephemeral();
7307 let mut authored = Classification::gate_compute();
7308 authored.point_type = ConvergencePointType::Fork;
7309 spec.classification = Some(authored.clone());
7310 let resolved = spec.resolved_classification();
7311 assert!(matches!(resolved, Cow::Borrowed(_)));
7312 assert_eq!(&*resolved, &authored);
7313 }
7314
7315 /// ABSENT-slot pin — an [`EphemeralSpec`] whose
7316 /// [`EphemeralSpec::classification`] slot is `None` returns
7317 /// [`Cow::Owned`] with the SAME value the sibling
7318 /// [`default_ephemeral_class`] baseline produces. Pins the
7319 /// two-surface parity contract with `From<EphemeralSpec> for
7320 /// ProcessSpec`: both sites fill through the SAME baseline on
7321 /// `None`, so the ephemeral require-tag surface's future
7322 /// `point-type-<kind>` family reads identically on the authored
7323 /// spec and on the mechanically lowered `ProcessSpec`.
7324 #[test]
7325 fn resolved_classification_fills_default_on_absent_slot() {
7326 let spec = empty_ephemeral();
7327 assert!(spec.classification.is_none());
7328 let resolved = spec.resolved_classification();
7329 assert!(matches!(resolved, Cow::Owned(_)));
7330 assert_eq!(&*resolved, &default_ephemeral_class());
7331 }
7332
7333 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7334 /// [`EphemeralSpec::classification`] slot names a concrete
7335 /// [`Classification`] returns `true` from
7336 /// [`Self::has_point_type`] on the authored
7337 /// [`ConvergencePointType`] slot and `false` for every other
7338 /// variant. Sweep the [`ConvergencePointType::ALL`] × ALL cross so
7339 /// a regression that hard-coded the arm to a single kind or wired
7340 /// the closure to a fixed unrelated slot fails HERE at the
7341 /// substrate primitive. Byte-for-byte peer of
7342 /// [`crate::classification::tests`]'s point-surface
7343 /// [`Classification::has_point_type`] populated-slot sweep on the
7344 /// SAME closed-set primitive.
7345 #[test]
7346 fn has_point_type_returns_true_iff_authored_classification_matches_per_kind() {
7347 for populated in ConvergencePointType::ALL {
7348 let mut classification = Classification::gate_compute();
7349 classification.point_type = populated;
7350 let mut spec = empty_ephemeral();
7351 spec.classification = Some(classification);
7352 for query in ConvergencePointType::ALL {
7353 let expected = query == populated;
7354 assert_eq!(
7355 spec.has_point_type(query),
7356 expected,
7357 "ephemeral classification.point_type={populated:?}: query {query:?} drifted",
7358 );
7359 }
7360 }
7361 }
7362
7363 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7364 /// [`EphemeralSpec::classification`] slot is `None` returns
7365 /// `true` from [`Self::has_point_type`] on
7366 /// [`ConvergencePointType::Gate`] (the `default_ephemeral_class`
7367 /// baseline's `point_type`) and `false` on every other variant.
7368 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
7369 /// default-arm short-circuit: on the ephemeral sugar surface the
7370 /// parent Option is filled through the workspace baseline rather
7371 /// than reading `false` on every variant like the encapsulation-
7372 /// mode / encapsulation-target / routing-form Option-parent
7373 /// corners.
7374 #[test]
7375 fn has_point_type_probes_gate_only_on_absent_classification() {
7376 let spec = empty_ephemeral();
7377 assert!(spec.classification.is_none());
7378 for kind in ConvergencePointType::ALL {
7379 let expected = kind == ConvergencePointType::Gate;
7380 assert_eq!(
7381 spec.has_point_type(kind),
7382 expected,
7383 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7384 );
7385 }
7386 }
7387
7388 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7389 /// identically through [`Self::has_point_type`] AND through
7390 /// `<eph.clone().into::<ProcessSpec>>()`
7391 /// `.classification.has_point_type(kind)` on the mechanically-
7392 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7393 /// classification on every [`ConvergencePointType::ALL`] variant)
7394 /// × ALL queries so a future regression on either side of the
7395 /// resolver (a shift in the ephemeral resolver's default, a
7396 /// shift in the `From<EphemeralSpec>` lowering's fill-through)
7397 /// fails HERE at the parity boundary.
7398 #[test]
7399 fn has_point_type_matches_point_peer_through_lowered_classification() {
7400 // Absent classification: both surfaces resolve through the SAME
7401 // default and agree on every variant.
7402 let eph = empty_ephemeral();
7403 let lowered: ProcessSpec = eph.clone().into();
7404 for query in ConvergencePointType::ALL {
7405 assert_eq!(
7406 eph.has_point_type(query),
7407 lowered.classification.has_point_type(query),
7408 "None-classification parity drift on query {query:?}",
7409 );
7410 }
7411 // Authored classification: both surfaces read the same authored
7412 // value verbatim.
7413 for populated in ConvergencePointType::ALL {
7414 let mut classification = Classification::gate_compute();
7415 classification.point_type = populated;
7416 let mut eph = empty_ephemeral();
7417 eph.classification = Some(classification);
7418 let lowered: ProcessSpec = eph.clone().into();
7419 for query in ConvergencePointType::ALL {
7420 assert_eq!(
7421 eph.has_point_type(query),
7422 lowered.classification.has_point_type(query),
7423 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
7424 );
7425 }
7426 }
7427 }
7428
7429 // ── EphemeralSpec::has_substrate pins ────────────────────────────
7430 //
7431 // Fail-before-pass-after granularity: [`Self::has_substrate`] did
7432 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
7433 // through `.resolved_classification().substrate == kind` or through
7434 // the lowered `ProcessSpec`'s `spec.classification.has_substrate`.
7435 // Post-lift the SECOND classification-axis peer on the ephemeral
7436 // sugar surface routes through the SAME
7437 // [`Self::resolved_classification`] resolver + the sibling closed-
7438 // set primitive [`Classification::has_substrate`], so a regression
7439 // that dropped the resolver hop, inverted the `Some`/`None`
7440 // fill-through, or wired the closure to a fixed unrelated slot
7441 // fails HERE.
7442
7443 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7444 /// [`EphemeralSpec::classification`] slot names a concrete
7445 /// [`Classification`] returns `true` from
7446 /// [`Self::has_substrate`] on the authored [`SubstrateType`] slot
7447 /// and `false` for every other variant. Sweep the
7448 /// [`SubstrateType::ALL`] × ALL cross so a regression that
7449 /// hard-coded the arm to a single kind or wired the closure to a
7450 /// fixed unrelated slot fails HERE at the substrate primitive.
7451 /// Byte-for-byte peer of the point-surface
7452 /// [`Classification::has_substrate`] populated-slot sweep on the
7453 /// SAME closed-set primitive.
7454 #[test]
7455 fn has_substrate_returns_true_iff_authored_classification_matches_per_kind() {
7456 for populated in SubstrateType::ALL {
7457 let mut classification = Classification::gate_compute();
7458 classification.substrate = populated;
7459 let mut spec = empty_ephemeral();
7460 spec.classification = Some(classification);
7461 for query in SubstrateType::ALL {
7462 let expected = query == populated;
7463 assert_eq!(
7464 spec.has_substrate(query),
7465 expected,
7466 "ephemeral classification.substrate={populated:?}: query {query:?} drifted",
7467 );
7468 }
7469 }
7470 }
7471
7472 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7473 /// [`EphemeralSpec::classification`] slot is `None` returns
7474 /// `true` from [`Self::has_substrate`] on
7475 /// [`SubstrateType::Compute`] (the `default_ephemeral_class`
7476 /// baseline's `substrate`) and `false` on every other variant.
7477 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
7478 /// default-arm short-circuit on the SECOND classification-axis
7479 /// peer: on the ephemeral sugar surface the parent Option is
7480 /// filled through the workspace baseline rather than reading
7481 /// `false` on every variant like the Option-parent encapsulates /
7482 /// routing corners.
7483 #[test]
7484 fn has_substrate_probes_compute_only_on_absent_classification() {
7485 let spec = empty_ephemeral();
7486 assert!(spec.classification.is_none());
7487 for kind in SubstrateType::ALL {
7488 let expected = kind == SubstrateType::Compute;
7489 assert_eq!(
7490 spec.has_substrate(kind),
7491 expected,
7492 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7493 );
7494 }
7495 }
7496
7497 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7498 /// identically through [`Self::has_substrate`] AND through
7499 /// `<eph.clone().into::<ProcessSpec>>()`
7500 /// `.classification.has_substrate(kind)` on the mechanically-
7501 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7502 /// classification on every [`SubstrateType::ALL`] variant) × ALL
7503 /// queries so a future regression on either side of the resolver
7504 /// (a shift in the ephemeral resolver's default, a shift in the
7505 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7506 /// the parity boundary. Byte-for-byte peer of the sibling
7507 /// [`Self::has_point_type`] two-surface parity pin on the SAME
7508 /// `Cow`-resolver carrier — the SECOND classification-axis
7509 /// two-surface parity contract on the ephemeral surface.
7510 #[test]
7511 fn has_substrate_matches_point_peer_through_lowered_classification() {
7512 // Absent classification: both surfaces resolve through the SAME
7513 // default and agree on every variant.
7514 let eph = empty_ephemeral();
7515 let lowered: ProcessSpec = eph.clone().into();
7516 for query in SubstrateType::ALL {
7517 assert_eq!(
7518 eph.has_substrate(query),
7519 lowered.classification.has_substrate(query),
7520 "None-classification parity drift on query {query:?}",
7521 );
7522 }
7523 // Authored classification: both surfaces read the same authored
7524 // value verbatim.
7525 for populated in SubstrateType::ALL {
7526 let mut classification = Classification::gate_compute();
7527 classification.substrate = populated;
7528 let mut eph = empty_ephemeral();
7529 eph.classification = Some(classification);
7530 let lowered: ProcessSpec = eph.clone().into();
7531 for query in SubstrateType::ALL {
7532 assert_eq!(
7533 eph.has_substrate(query),
7534 lowered.classification.has_substrate(query),
7535 "authored classification.substrate={populated:?}: parity drift on query {query:?}",
7536 );
7537 }
7538 }
7539 }
7540
7541 // ── EphemeralSpec::has_calm pins ─────────────────────────────────
7542 //
7543 // Fail-before-pass-after granularity: [`Self::has_calm`] did not
7544 // exist pre-lift on `impl EphemeralSpec` — every callsite went
7545 // through `.resolved_classification().calm == kind` or through the
7546 // lowered `ProcessSpec`'s `spec.classification.has_calm`. Post-
7547 // lift the THIRD classification-axis peer on the ephemeral sugar
7548 // surface routes through the SAME
7549 // [`Self::resolved_classification`] resolver + the sibling closed-
7550 // set primitive [`Classification::has_calm`], so a regression that
7551 // dropped the resolver hop, inverted the `Some`/`None` fill-
7552 // through, or wired the closure to a fixed unrelated slot fails
7553 // HERE. Distinct from the FIRST + SECOND peers on the (Option-
7554 // parent × NON-DEFAULT-scalar-child) corner: the (Option-parent ×
7555 // DEFAULTED-scalar-child) corner this peer opens has BOTH the
7556 // parent fill-through baseline (`default_ephemeral_class`) AND the
7557 // child's own `#[default]` land on the SAME variant
7558 // ([`CalmClassification::Monotone`]), a two-defaults composition
7559 // property the three pins below all exercise.
7560
7561 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7562 /// [`EphemeralSpec::classification`] slot names a concrete
7563 /// [`Classification`] returns `true` from [`Self::has_calm`] on
7564 /// the authored [`CalmClassification`] slot and `false` for every
7565 /// other variant. Sweep the [`CalmClassification::ALL`] × ALL
7566 /// cross so a regression that hard-coded the arm to a single
7567 /// kind or wired the closure to a fixed unrelated slot fails HERE
7568 /// at the substrate primitive. Byte-for-byte peer of the point-
7569 /// surface [`Classification::has_calm`] populated-slot sweep on
7570 /// the SAME closed-set primitive.
7571 #[test]
7572 fn has_calm_returns_true_iff_authored_classification_matches_per_kind() {
7573 for populated in CalmClassification::ALL {
7574 let mut classification = Classification::gate_compute();
7575 classification.calm = populated;
7576 let mut spec = empty_ephemeral();
7577 spec.classification = Some(classification);
7578 for query in CalmClassification::ALL {
7579 let expected = query == populated;
7580 assert_eq!(
7581 spec.has_calm(query),
7582 expected,
7583 "ephemeral classification.calm={populated:?}: query {query:?} drifted",
7584 );
7585 }
7586 }
7587 }
7588
7589 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7590 /// [`EphemeralSpec::classification`] slot is `None` returns
7591 /// `true` from [`Self::has_calm`] on
7592 /// [`CalmClassification::Monotone`] (the `default_ephemeral_class`
7593 /// baseline's `calm` axis AND the [`CalmClassification`] child's
7594 /// own `#[default]` variant) and `false` on every other variant.
7595 /// Pins the (Option-parent × DEFAULTED-scalar-child ×
7596 /// operator-resolvable-baseline) corner's default-arm short-
7597 /// circuit on the THIRD classification-axis peer — distinct from
7598 /// the FIRST + SECOND peers on the (Option-parent × NON-DEFAULT-
7599 /// scalar-child) corner which default through a specific chosen
7600 /// baseline ([`ConvergencePointType::Gate`],
7601 /// [`SubstrateType::Compute`]) rather than through the child's
7602 /// own `#[default]`. Two-defaults composition property: both the
7603 /// parent fill-through and the child's `#[default]` land on the
7604 /// SAME variant, so the ephemeral sugar surface's `calm-Monotone`
7605 /// require-tag reads `true` on every operator-authored spec that
7606 /// omits both the `:classification` slot AND the `:calm` sub-slot,
7607 /// pinning the workspace's monotone-by-default posture.
7608 #[test]
7609 fn has_calm_probes_monotone_only_on_absent_classification() {
7610 let spec = empty_ephemeral();
7611 assert!(spec.classification.is_none());
7612 for kind in CalmClassification::ALL {
7613 let expected = kind == CalmClassification::Monotone;
7614 assert_eq!(
7615 spec.has_calm(kind),
7616 expected,
7617 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7618 );
7619 }
7620 }
7621
7622 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7623 /// identically through [`Self::has_calm`] AND through
7624 /// `<eph.clone().into::<ProcessSpec>>()`
7625 /// `.classification.has_calm(kind)` on the mechanically-
7626 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7627 /// classification on every [`CalmClassification::ALL`] variant) ×
7628 /// ALL queries so a future regression on either side of the
7629 /// resolver (a shift in the ephemeral resolver's default, a shift
7630 /// in the `From<EphemeralSpec>` lowering's fill-through) fails
7631 /// HERE at the parity boundary. Byte-for-byte peer of the sibling
7632 /// [`Self::has_point_type`] + [`Self::has_substrate`] two-surface
7633 /// parity pins on the SAME `Cow`-resolver carrier — the THIRD
7634 /// classification-axis two-surface parity contract on the
7635 /// ephemeral surface, and the FIRST on the (Option-parent ×
7636 /// DEFAULTED-scalar-child) corner.
7637 #[test]
7638 fn has_calm_matches_point_peer_through_lowered_classification() {
7639 // Absent classification: both surfaces resolve through the SAME
7640 // default and agree on every variant.
7641 let eph = empty_ephemeral();
7642 let lowered: ProcessSpec = eph.clone().into();
7643 for query in CalmClassification::ALL {
7644 assert_eq!(
7645 eph.has_calm(query),
7646 lowered.classification.has_calm(query),
7647 "None-classification parity drift on query {query:?}",
7648 );
7649 }
7650 // Authored classification: both surfaces read the same authored
7651 // value verbatim.
7652 for populated in CalmClassification::ALL {
7653 let mut classification = Classification::gate_compute();
7654 classification.calm = populated;
7655 let mut eph = empty_ephemeral();
7656 eph.classification = Some(classification);
7657 let lowered: ProcessSpec = eph.clone().into();
7658 for query in CalmClassification::ALL {
7659 assert_eq!(
7660 eph.has_calm(query),
7661 lowered.classification.has_calm(query),
7662 "authored classification.calm={populated:?}: parity drift on query {query:?}",
7663 );
7664 }
7665 }
7666 }
7667
7668 // ── EphemeralSpec::has_data_classification pins ──────────────────
7669 //
7670 // Fail-before-pass-after granularity: [`Self::has_data_classification`]
7671 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
7672 // went through `.resolved_classification().data_classification ==
7673 // kind` or through the lowered `ProcessSpec`'s
7674 // `spec.classification.has_data_classification`. Post-lift the
7675 // FOURTH classification-axis peer on the ephemeral sugar surface
7676 // routes through the SAME [`Self::resolved_classification`]
7677 // resolver + the sibling closed-set primitive
7678 // [`crate::classification::Classification::has_data_classification`],
7679 // so a regression that dropped the resolver hop, inverted the
7680 // `Some`/`None` fill-through, or wired the closure to a fixed
7681 // unrelated slot fails HERE. SECOND occupant on the (Option-parent
7682 // × DEFAULTED-scalar-child × operator-resolvable-baseline) corner
7683 // alongside [`Self::has_calm`]: both the parent fill-through
7684 // baseline (`default_ephemeral_class`) AND the child's own
7685 // `#[default]` land on the SAME variant
7686 // ([`DataClassification::Internal`]), a two-defaults composition
7687 // property the three pins below all exercise.
7688
7689 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7690 /// [`EphemeralSpec::classification`] slot names a concrete
7691 /// [`Classification`] returns `true` from
7692 /// [`Self::has_data_classification`] on the authored
7693 /// [`DataClassification`] slot and `false` for every other
7694 /// variant. Sweep the [`DataClassification::ALL`] × ALL cross so
7695 /// a regression that hard-coded the arm to a single kind or
7696 /// wired the closure to a fixed unrelated slot fails HERE at the
7697 /// substrate primitive. Byte-for-byte peer of the point-surface
7698 /// [`Classification::has_data_classification`] populated-slot
7699 /// sweep on the SAME closed-set primitive.
7700 #[test]
7701 fn has_data_classification_returns_true_iff_authored_classification_matches_per_kind() {
7702 for populated in DataClassification::ALL {
7703 let mut classification = Classification::gate_compute();
7704 classification.data_classification = populated;
7705 let mut spec = empty_ephemeral();
7706 spec.classification = Some(classification);
7707 for query in DataClassification::ALL {
7708 let expected = query == populated;
7709 assert_eq!(
7710 spec.has_data_classification(query),
7711 expected,
7712 "ephemeral classification.data_classification={populated:?}: query {query:?} drifted",
7713 );
7714 }
7715 }
7716 }
7717
7718 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7719 /// [`EphemeralSpec::classification`] slot is `None` returns
7720 /// `true` from [`Self::has_data_classification`] on
7721 /// [`DataClassification::Internal`] (the `default_ephemeral_class`
7722 /// baseline's `data_classification` axis AND the
7723 /// [`DataClassification`] child's own `#[default]` variant) and
7724 /// `false` on every other variant. Pins the (Option-parent ×
7725 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner's
7726 /// default-arm short-circuit on the FOURTH classification-axis
7727 /// peer — SECOND occupant on that corner after [`Self::has_calm`]
7728 /// opened it. Two-defaults composition property: both the parent
7729 /// fill-through and the child's `#[default]` land on the SAME
7730 /// variant, so the ephemeral sugar surface's
7731 /// `data-classification-Internal` require-tag reads `true` on
7732 /// every operator-authored spec that omits both the
7733 /// `:classification` slot AND the `:data-classification` sub-slot,
7734 /// pinning the workspace's internal-by-default sensitivity posture.
7735 #[test]
7736 fn has_data_classification_probes_internal_only_on_absent_classification() {
7737 let spec = empty_ephemeral();
7738 assert!(spec.classification.is_none());
7739 for kind in DataClassification::ALL {
7740 let expected = kind == DataClassification::Internal;
7741 assert_eq!(
7742 spec.has_data_classification(kind),
7743 expected,
7744 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7745 );
7746 }
7747 }
7748
7749 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7750 /// identically through [`Self::has_data_classification`] AND
7751 /// through `<eph.clone().into::<ProcessSpec>>()`
7752 /// `.classification.has_data_classification(kind)` on the
7753 /// mechanically-lowered `ProcessSpec`. Sweeps (`None`
7754 /// classification, `Some(_)` classification on every
7755 /// [`DataClassification::ALL`] variant) × ALL queries so a
7756 /// future regression on either side of the resolver (a shift in
7757 /// the ephemeral resolver's default, a shift in the
7758 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7759 /// the parity boundary. Byte-for-byte peer of the sibling
7760 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
7761 /// [`Self::has_calm`] two-surface parity pins on the SAME
7762 /// `Cow`-resolver carrier — the FOURTH classification-axis
7763 /// two-surface parity contract on the ephemeral surface, and the
7764 /// SECOND on the (Option-parent × DEFAULTED-scalar-child) corner.
7765 #[test]
7766 fn has_data_classification_matches_point_peer_through_lowered_classification() {
7767 // Absent classification: both surfaces resolve through the SAME
7768 // default and agree on every variant.
7769 let eph = empty_ephemeral();
7770 let lowered: ProcessSpec = eph.clone().into();
7771 for query in DataClassification::ALL {
7772 assert_eq!(
7773 eph.has_data_classification(query),
7774 lowered.classification.has_data_classification(query),
7775 "None-classification parity drift on query {query:?}",
7776 );
7777 }
7778 // Authored classification: both surfaces read the same authored
7779 // value verbatim.
7780 for populated in DataClassification::ALL {
7781 let mut classification = Classification::gate_compute();
7782 classification.data_classification = populated;
7783 let mut eph = empty_ephemeral();
7784 eph.classification = Some(classification);
7785 let lowered: ProcessSpec = eph.clone().into();
7786 for query in DataClassification::ALL {
7787 assert_eq!(
7788 eph.has_data_classification(query),
7789 lowered.classification.has_data_classification(query),
7790 "authored classification.data_classification={populated:?}: parity drift on query {query:?}",
7791 );
7792 }
7793 }
7794 }
7795
7796 // ── EphemeralSpec::has_horizon_kind pins ─────────────────────────
7797 //
7798 // Fail-before-pass-after granularity: [`Self::has_horizon_kind`]
7799 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
7800 // went through `.resolved_classification().horizon.kind == kind`
7801 // or through the lowered `ProcessSpec`'s
7802 // `spec.classification.has_horizon_kind`. Post-lift the FIFTH
7803 // classification-axis peer on the ephemeral sugar surface routes
7804 // through the SAME [`Self::resolved_classification`] resolver +
7805 // the sibling closed-set primitive
7806 // [`crate::classification::Classification::has_horizon_kind`], so
7807 // a regression that dropped the resolver hop, inverted the
7808 // `Some`/`None` fill-through, or wired the closure to a fixed
7809 // unrelated slot fails HERE. OPENS a fresh (Option-parent ×
7810 // NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
7811 // corner on the ephemeral surface — distinct from the four prior
7812 // scalar-carrier peers on the (Option-parent × NON-DEFAULT-scalar-
7813 // child) and (Option-parent × DEFAULTED-scalar-child) corners, all
7814 // of which reach a discriminator DIRECTLY off a scalar
7815 // [`Classification`] slot. Both the parent Option's fill-through
7816 // baseline (`default_ephemeral_class`, which fills
7817 // `horizon: Horizon::default()`) AND the child's own `#[default]`
7818 // land on the SAME variant ([`HorizonKind::Bounded`]) — a two-
7819 // defaults composition property the three pins below all
7820 // exercise.
7821
7822 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7823 /// [`EphemeralSpec::classification`] slot names a concrete
7824 /// [`Classification`] returns `true` from
7825 /// [`Self::has_horizon_kind`] on the authored [`HorizonKind`] slot
7826 /// and `false` for every other variant. Sweep the
7827 /// [`HorizonKind::ALL`] × ALL cross so a regression that hard-
7828 /// coded the arm to a single kind or wired the closure to a
7829 /// fixed unrelated slot (e.g. reading `self.classification` as if
7830 /// it were a scalar rather than routing through
7831 /// `resolved_classification().horizon.kind`) fails HERE at the
7832 /// substrate primitive. Byte-for-byte peer of the point-surface
7833 /// [`Classification::has_horizon_kind`] populated-slot sweep on
7834 /// the SAME closed-set primitive.
7835 #[test]
7836 fn has_horizon_kind_returns_true_iff_authored_classification_matches_per_kind() {
7837 for populated in HorizonKind::ALL {
7838 let classification = Classification::gate_compute_with_axis(populated);
7839 let mut spec = empty_ephemeral();
7840 spec.classification = Some(classification);
7841 for query in HorizonKind::ALL {
7842 let expected = query == populated;
7843 assert_eq!(
7844 spec.has_horizon_kind(query),
7845 expected,
7846 "ephemeral classification.horizon.kind={populated:?}: query {query:?} drifted",
7847 );
7848 }
7849 }
7850 }
7851
7852 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7853 /// [`EphemeralSpec::classification`] slot is `None` returns
7854 /// `true` from [`Self::has_horizon_kind`] on
7855 /// [`HorizonKind::Bounded`] (the `default_ephemeral_class`
7856 /// baseline's `horizon.kind` axis AND the [`HorizonKind`] child's
7857 /// own `#[default]` variant) and `false` on every other variant.
7858 /// Pins the fresh (Option-parent × NESTED-STRUCT-scalar-child ×
7859 /// operator-resolvable-baseline) corner's default-arm short-
7860 /// circuit on the FIFTH classification-axis peer. Two-defaults
7861 /// composition property through a NESTED-STRUCT hop: both the
7862 /// parent Option's fill-through baseline
7863 /// (`default_ephemeral_class` fills `horizon: Horizon::default()`)
7864 /// AND the child's own `#[default]` (`HorizonKind::Bounded` via
7865 /// `#[default]` on the closed set) land on the SAME variant, so
7866 /// the ephemeral sugar surface's `horizon-Bounded` require-tag
7867 /// reads `true` on every operator-authored spec that omits both
7868 /// the `:classification` slot AND the `:horizon` sub-slot,
7869 /// pinning the workspace's bounded-by-default lifetime posture.
7870 #[test]
7871 fn has_horizon_kind_probes_bounded_only_on_absent_classification() {
7872 let spec = empty_ephemeral();
7873 assert!(spec.classification.is_none());
7874 for kind in HorizonKind::ALL {
7875 let expected = kind == HorizonKind::Bounded;
7876 assert_eq!(
7877 spec.has_horizon_kind(kind),
7878 expected,
7879 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7880 );
7881 }
7882 }
7883
7884 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7885 /// identically through [`Self::has_horizon_kind`] AND through
7886 /// `<eph.clone().into::<ProcessSpec>>()`
7887 /// `.classification.has_horizon_kind(kind)` on the mechanically-
7888 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7889 /// classification on every [`HorizonKind::ALL`] variant) × ALL
7890 /// queries so a future regression on either side of the resolver
7891 /// (a shift in the ephemeral resolver's default, a shift in the
7892 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7893 /// the parity boundary. Byte-for-byte peer of the sibling
7894 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
7895 /// [`Self::has_calm`] + [`Self::has_data_classification`] two-
7896 /// surface parity pins on the SAME `Cow`-resolver carrier — the
7897 /// FIFTH classification-axis two-surface parity contract on the
7898 /// ephemeral surface, and the FIRST on the (Option-parent ×
7899 /// NESTED-STRUCT-scalar-child) corner.
7900 #[test]
7901 fn has_horizon_kind_matches_point_peer_through_lowered_classification() {
7902 // Absent classification: both surfaces resolve through the SAME
7903 // default and agree on every variant.
7904 let eph = empty_ephemeral();
7905 let lowered: ProcessSpec = eph.clone().into();
7906 for query in HorizonKind::ALL {
7907 assert_eq!(
7908 eph.has_horizon_kind(query),
7909 lowered.classification.has_horizon_kind(query),
7910 "None-classification parity drift on query {query:?}",
7911 );
7912 }
7913 // Authored classification: both surfaces read the same authored
7914 // value verbatim.
7915 for populated in HorizonKind::ALL {
7916 let classification = Classification::gate_compute_with_axis(populated);
7917 let mut eph = empty_ephemeral();
7918 eph.classification = Some(classification);
7919 let lowered: ProcessSpec = eph.clone().into();
7920 for query in HorizonKind::ALL {
7921 assert_eq!(
7922 eph.has_horizon_kind(query),
7923 lowered.classification.has_horizon_kind(query),
7924 "authored classification.horizon.kind={populated:?}: parity drift on query {query:?}",
7925 );
7926 }
7927 }
7928 }
7929
7930 // ── EphemeralSpec::has_optimization_direction pins ───────────────
7931 //
7932 // Fail-before-pass-after granularity:
7933 // [`Self::has_optimization_direction`] did not exist pre-lift on
7934 // `impl EphemeralSpec` — every callsite went through
7935 // `.resolved_classification().horizon.direction.unwrap_or_default() == kind`
7936 // or through the lowered `ProcessSpec`'s
7937 // `spec.classification.has_optimization_direction`. Post-lift the
7938 // SIXTH classification-axis peer on the ephemeral sugar surface
7939 // routes through the SAME [`Self::resolved_classification`]
7940 // resolver + the sibling closed-set primitive
7941 // [`crate::classification::Classification::has_optimization_direction`],
7942 // so a regression that dropped the resolver hop, inverted the
7943 // `Some`/`None` fill-through, wired the closure to a fixed
7944 // unrelated slot, or flipped [`OptimizationDirection`]'s
7945 // `#[default]` off `Minimize` fails HERE. SECOND occupant on the
7946 // (Option-parent × NESTED-STRUCT-scalar-child × operator-
7947 // resolvable-baseline) corner alongside
7948 // [`Self::has_horizon_kind`] — pinning the corner as a proven-
7949 // repeatable primitive shape on the ephemeral surface with a
7950 // second nested-struct-child probe, and DEMONSTRATING that the
7951 // corner admits both direct-scalar and Option-scalar traversals
7952 // through the SAME nested [`Horizon`] intermediary via the closed
7953 // set's `Default` on the inner `Option<OptimizationDirection>`
7954 // slot.
7955
7956 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7957 /// [`EphemeralSpec::classification`] slot names a concrete
7958 /// [`Classification`] whose [`crate::classification::Horizon::direction`]
7959 /// slot carries `Some(<direction>)` returns `true` from
7960 /// [`Self::has_optimization_direction`] on the authored
7961 /// [`OptimizationDirection`] variant and `false` for every other
7962 /// variant. Sweep the [`OptimizationDirection::ALL`] × ALL cross
7963 /// so a regression that hard-coded the arm to a single kind, or
7964 /// dropped the `Option::unwrap_or_default` collapse, or wired the
7965 /// closure to a fixed unrelated slot (e.g. reading `self.horizon.kind`)
7966 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
7967 /// point-surface
7968 /// [`Classification::has_optimization_direction`] populated-slot
7969 /// sweep on the SAME closed-set primitive.
7970 #[test]
7971 fn has_optimization_direction_returns_true_iff_authored_direction_matches_per_kind() {
7972 for populated in OptimizationDirection::ALL {
7973 let classification = Classification::gate_compute_with_axis(populated);
7974 let mut spec = empty_ephemeral();
7975 spec.classification = Some(classification);
7976 for query in OptimizationDirection::ALL {
7977 let expected = query == populated;
7978 assert_eq!(
7979 spec.has_optimization_direction(query),
7980 expected,
7981 "ephemeral classification.horizon.direction=Some({populated:?}): query {query:?} drifted",
7982 );
7983 }
7984 }
7985 }
7986
7987 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7988 /// [`EphemeralSpec::classification`] slot is `None` returns
7989 /// `true` from [`Self::has_optimization_direction`] on
7990 /// [`OptimizationDirection::Minimize`] (the `default_ephemeral_class`
7991 /// baseline fills `horizon: Horizon::default()`, which in turn
7992 /// leaves `direction: None`, and the substrate's
7993 /// `Option::unwrap_or_default` collapse then reads
7994 /// [`OptimizationDirection::Minimize`] via the closed set's
7995 /// `#[default]`) and `false` on every other variant. Pins the
7996 /// (Option-parent × NESTED-STRUCT-scalar-child × operator-
7997 /// resolvable-baseline) corner's default-arm short-circuit on the
7998 /// SIXTH classification-axis peer through TWO Option-hops: parent
7999 /// `EphemeralSpec::classification` and inner `Horizon::direction`
8000 /// both `None`, both collapsing to the closed set's `#[default]`
8001 /// [`OptimizationDirection::Minimize`]. A regression that promoted
8002 /// [`OptimizationDirection::Maximize`] to `#[default]` (silently
8003 /// inverting every unadorned Process's rate-window evaluator
8004 /// polarity), dropped `Option::unwrap_or_default`, or wired the arm
8005 /// to a fixed variant answer fails HERE.
8006 #[test]
8007 fn has_optimization_direction_probes_minimize_only_on_absent_classification() {
8008 let spec = empty_ephemeral();
8009 assert!(spec.classification.is_none());
8010 for kind in OptimizationDirection::ALL {
8011 let expected = kind == OptimizationDirection::Minimize;
8012 assert_eq!(
8013 spec.has_optimization_direction(kind),
8014 expected,
8015 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8016 );
8017 }
8018 }
8019
8020 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8021 /// identically through [`Self::has_optimization_direction`] AND
8022 /// through
8023 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
8024 /// on the mechanically-lowered `ProcessSpec`. Sweeps three arms —
8025 /// (`None` classification), (`Some(_)` classification with
8026 /// `direction: None`), and (`Some(_)` classification on every
8027 /// [`OptimizationDirection::ALL`] variant) — × ALL queries so a
8028 /// future regression on either side of the resolver (an ephemeral-
8029 /// side fill-through drift, a lowering-side `From<EphemeralSpec>`
8030 /// `unwrap_or_else(default_ephemeral_class)` drift, an inner
8031 /// `Option::unwrap_or_default` collapse drift on either side)
8032 /// fails HERE at the parity boundary. Byte-for-byte peer of the
8033 /// sibling [`Self::has_point_type`] + [`Self::has_substrate`] +
8034 /// [`Self::has_calm`] + [`Self::has_data_classification`] +
8035 /// [`Self::has_horizon_kind`] two-surface parity pins on the SAME
8036 /// `Cow`-resolver carrier — the SIXTH classification-axis two-
8037 /// surface parity contract on the ephemeral surface, and the
8038 /// SECOND on the (Option-parent × NESTED-STRUCT-scalar-child)
8039 /// corner.
8040 #[test]
8041 fn has_optimization_direction_matches_point_peer_through_lowered_classification() {
8042 // Absent classification: both surfaces resolve through the SAME
8043 // default and agree on every variant.
8044 let eph = empty_ephemeral();
8045 let lowered: ProcessSpec = eph.clone().into();
8046 for query in OptimizationDirection::ALL {
8047 assert_eq!(
8048 eph.has_optimization_direction(query),
8049 lowered.classification.has_optimization_direction(query),
8050 "None-classification parity drift on query {query:?}",
8051 );
8052 }
8053 // Authored classification with `direction: None` — the inner
8054 // Option collapses through `unwrap_or_default` on both sides,
8055 // reading `Minimize`.
8056 let mut classification = Classification::gate_compute();
8057 classification.horizon = Horizon::default();
8058 let mut eph = empty_ephemeral();
8059 eph.classification = Some(classification);
8060 let lowered: ProcessSpec = eph.clone().into();
8061 for query in OptimizationDirection::ALL {
8062 assert_eq!(
8063 eph.has_optimization_direction(query),
8064 lowered.classification.has_optimization_direction(query),
8065 "authored classification with horizon.direction=None: parity drift on query {query:?}",
8066 );
8067 }
8068 // Authored classification with `direction: Some(_)` — both
8069 // surfaces read the same authored value verbatim.
8070 for populated in OptimizationDirection::ALL {
8071 let classification = Classification::gate_compute_with_axis(populated);
8072 let mut eph = empty_ephemeral();
8073 eph.classification = Some(classification);
8074 let lowered: ProcessSpec = eph.clone().into();
8075 for query in OptimizationDirection::ALL {
8076 assert_eq!(
8077 eph.has_optimization_direction(query),
8078 lowered.classification.has_optimization_direction(query),
8079 "authored classification.horizon.direction=Some({populated:?}): parity drift on query {query:?}",
8080 );
8081 }
8082 }
8083 }
8084
8085 // ── EphemeralSpec::has_input_arity pins ──────────────────────────
8086 //
8087 // Fail-before-pass-after granularity: [`Self::has_input_arity`] did
8088 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8089 // through `.resolved_classification().point_type.input_arity() ==
8090 // kind` or through the lowered `ProcessSpec`'s
8091 // `spec.classification.has_input_arity`. Post-lift the SEVENTH
8092 // classification-axis peer on the ephemeral sugar surface routes
8093 // through the SAME [`Self::resolved_classification`] resolver + the
8094 // sibling closed-set primitive
8095 // [`crate::classification::Classification::has_input_arity`], so a
8096 // regression that dropped the resolver hop, dropped the
8097 // `.input_arity()` projection call, inverted the projection (`One
8098 // ↔ Many`), or crossed the wires with the sibling
8099 // [`ConvergencePointType::output_arity`] projection fails HERE.
8100 // OPENS the (Option-parent × NESTED-STRUCT-scalar-child ×
8101 // derived-typed-projection) corner on the ephemeral surface —
8102 // distinct from the two prior nested-scalar peers on the corner
8103 // (`has_horizon_kind` reads `horizon.kind` directly;
8104 // `has_optimization_direction` reads `horizon.direction` through an
8105 // Option collapse), both of which reach a discriminator DIRECTLY off
8106 // a scalar. This peer instead threads through a many-to-one closed-
8107 // set typed projection so the child's closed set is REACHED THROUGH
8108 // a projection layer, pinning the corner as admitting three
8109 // ephemeral-surface traversal shapes (direct-scalar, Option-scalar-
8110 // with-default, derived-typed-projection) through the SAME resolver
8111 // walk.
8112
8113 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
8114 /// [`EphemeralSpec::classification`] slot names a concrete
8115 /// [`Classification`] with an authored [`ConvergencePointType`]
8116 /// returns `true` from [`Self::has_input_arity`] on the [`Arity`]
8117 /// value the projection [`ConvergencePointType::input_arity`] maps
8118 /// the authored point-type to and `false` for every other variant.
8119 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
8120 /// a regression that (a) dropped the projection call, (b) inverted
8121 /// the projection, (c) probed [`ConvergencePointType`] directly, or
8122 /// (d) crossed wires with [`ConvergencePointType::output_arity`]
8123 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
8124 /// point-surface [`Classification::has_input_arity`] populated-slot
8125 /// sweep on the SAME closed-set primitive routed through the SAME
8126 /// projection.
8127 #[test]
8128 fn has_input_arity_returns_true_iff_authored_point_type_projects_per_kind() {
8129 for populated in ConvergencePointType::ALL {
8130 let mut classification = Classification::gate_compute();
8131 classification.point_type = populated;
8132 let mut spec = empty_ephemeral();
8133 spec.classification = Some(classification);
8134 let projected = populated.input_arity();
8135 for query in Arity::ALL {
8136 let expected = query == projected;
8137 assert_eq!(
8138 spec.has_input_arity(query),
8139 expected,
8140 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
8141 );
8142 }
8143 }
8144 }
8145
8146 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
8147 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
8148 /// from [`Self::has_input_arity`] on [`Arity::Many`] (the
8149 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
8150 /// and [`ConvergencePointType::input_arity`] projects
8151 /// `Gate → Arity::Many`) and `false` on [`Arity::One`]. Pins the
8152 /// (Option-parent × NESTED-STRUCT-scalar-child × derived-typed-
8153 /// projection) corner's baseline projection on the SEVENTH
8154 /// classification-axis peer through a chain of TWO fill-throughs
8155 /// composed with ONE projection: the parent Option's
8156 /// `unwrap_or_else(default_ephemeral_class)` picks the substrate
8157 /// baseline, and the projection then collapses the baseline's
8158 /// point-type through the closed-set-driven many-to-one bucket
8159 /// walk. [`Arity`] carries no `#[default]`, so there is NO default-
8160 /// arm short-circuit shortcut here — the answer flows entirely
8161 /// through the projection's bucket-membership decision. A
8162 /// regression that promoted the baseline's `point_type` off `Gate`
8163 /// (silently flipping every unadorned Process's convergent-by-
8164 /// default input-side posture to endomorphic or diffusive), dropped
8165 /// the projection call, inverted the projection, or crossed wires
8166 /// with [`ConvergencePointType::output_arity`] (which would flip
8167 /// the baseline answer from `Many` to `One` for `Gate`) fails HERE.
8168 #[test]
8169 fn has_input_arity_probes_many_only_on_absent_classification() {
8170 let spec = empty_ephemeral();
8171 assert!(spec.classification.is_none());
8172 for kind in Arity::ALL {
8173 let expected = kind == Arity::Many;
8174 assert_eq!(
8175 spec.has_input_arity(kind),
8176 expected,
8177 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many): query {kind:?} must be {expected}",
8178 );
8179 }
8180 }
8181
8182 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8183 /// identically through [`Self::has_input_arity`] AND through
8184 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
8185 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8186 /// classification, `Some(_)` classification on every
8187 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
8188 /// so a future regression on either side of the resolver (a shift
8189 /// in the ephemeral resolver's default, a shift in the
8190 /// `From<EphemeralSpec>` lowering's fill-through, a projection
8191 /// drift on either side) fails HERE at the parity boundary. Byte-
8192 /// for-byte peer of the sibling [`Self::has_point_type`] +
8193 /// [`Self::has_substrate`] + [`Self::has_calm`] +
8194 /// [`Self::has_data_classification`] + [`Self::has_horizon_kind`] +
8195 /// [`Self::has_optimization_direction`] two-surface parity pins on
8196 /// the SAME `Cow`-resolver carrier — the SEVENTH classification-
8197 /// axis two-surface parity contract on the ephemeral surface, and
8198 /// the FIRST on the (Option-parent × NESTED-STRUCT-scalar-child ×
8199 /// derived-typed-projection) corner.
8200 #[test]
8201 fn has_input_arity_matches_point_peer_through_lowered_classification() {
8202 // Absent classification: both surfaces resolve through the SAME
8203 // default and agree on every variant.
8204 let eph = empty_ephemeral();
8205 let lowered: ProcessSpec = eph.clone().into();
8206 for query in Arity::ALL {
8207 assert_eq!(
8208 eph.has_input_arity(query),
8209 lowered.classification.has_input_arity(query),
8210 "None-classification parity drift on query {query:?}",
8211 );
8212 }
8213 // Authored classification: both surfaces read the same authored
8214 // point_type and route through the same projection.
8215 for populated in ConvergencePointType::ALL {
8216 let mut classification = Classification::gate_compute();
8217 classification.point_type = populated;
8218 let mut eph = empty_ephemeral();
8219 eph.classification = Some(classification);
8220 let lowered: ProcessSpec = eph.clone().into();
8221 for query in Arity::ALL {
8222 assert_eq!(
8223 eph.has_input_arity(query),
8224 lowered.classification.has_input_arity(query),
8225 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8226 );
8227 }
8228 }
8229 }
8230
8231 // ── EphemeralSpec::has_output_arity pins ─────────────────────────
8232 //
8233 // Fail-before-pass-after granularity: [`Self::has_output_arity`] did
8234 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8235 // through `.resolved_classification().point_type.output_arity() ==
8236 // kind` or through the lowered `ProcessSpec`'s
8237 // `spec.classification.has_output_arity`. Post-lift the EIGHTH
8238 // classification-axis peer on the ephemeral sugar surface routes
8239 // through the SAME [`Self::resolved_classification`] resolver + the
8240 // sibling closed-set primitive
8241 // [`crate::classification::Classification::has_output_arity`], so a
8242 // regression that dropped the resolver hop, dropped the
8243 // `.output_arity()` projection call, inverted the projection (`One
8244 // ↔ Many`), or crossed the wires with the sibling
8245 // [`ConvergencePointType::input_arity`] projection fails HERE.
8246 // CLOSES the (Option-parent × NESTED-STRUCT-scalar-child ×
8247 // derived-typed-projection) corner on the ephemeral surface as the
8248 // SECOND occupant — co-tenant with [`Self::has_input_arity`] on the
8249 // SAME `point_type` scalar carrier through the SAME [`Arity`] closed
8250 // set but through the sibling many-to-one projection, closing the
8251 // DAG-composition arity pair on the ephemeral side.
8252
8253 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
8254 /// [`EphemeralSpec::classification`] slot names a concrete
8255 /// [`Classification`] with an authored [`ConvergencePointType`]
8256 /// returns `true` from [`Self::has_output_arity`] on the [`Arity`]
8257 /// value the projection [`ConvergencePointType::output_arity`] maps
8258 /// the authored point-type to and `false` for every other variant.
8259 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
8260 /// a regression that (a) dropped the projection call, (b) inverted
8261 /// the projection, (c) probed [`ConvergencePointType`] directly, or
8262 /// (d) crossed wires with [`ConvergencePointType::input_arity`]
8263 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
8264 /// point-surface [`Classification::has_output_arity`] populated-slot
8265 /// sweep on the SAME closed-set primitive routed through the SAME
8266 /// projection.
8267 #[test]
8268 fn has_output_arity_returns_true_iff_authored_point_type_projects_per_kind() {
8269 for populated in ConvergencePointType::ALL {
8270 let mut classification = Classification::gate_compute();
8271 classification.point_type = populated;
8272 let mut spec = empty_ephemeral();
8273 spec.classification = Some(classification);
8274 let projected = populated.output_arity();
8275 for query in Arity::ALL {
8276 let expected = query == projected;
8277 assert_eq!(
8278 spec.has_output_arity(query),
8279 expected,
8280 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
8281 );
8282 }
8283 }
8284 }
8285
8286 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
8287 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
8288 /// from [`Self::has_output_arity`] on [`Arity::One`] (the
8289 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
8290 /// and [`ConvergencePointType::output_arity`] projects
8291 /// `Gate → Arity::One`) and `false` on [`Arity::Many`]. MIRROR of
8292 /// the [`Self::has_input_arity`] baseline (`Gate → input_arity =
8293 /// Many`) — the DAG-composition arity pair projects the same `Gate`
8294 /// baseline through the two projections to opposite [`Arity`] arms,
8295 /// so this pin locks the output-side half of that pair against a
8296 /// regression that (a) promoted the baseline's `point_type` off
8297 /// `Gate` (silently flipping every unadorned Process's convergent-
8298 /// by-default output-side posture to diffusive), (b) dropped the
8299 /// projection call, (c) inverted the projection, or (d) crossed
8300 /// wires with [`ConvergencePointType::input_arity`] (which would
8301 /// flip the baseline answer from `One` to `Many` for `Gate`).
8302 #[test]
8303 fn has_output_arity_probes_one_only_on_absent_classification() {
8304 let spec = empty_ephemeral();
8305 assert!(spec.classification.is_none());
8306 for kind in Arity::ALL {
8307 let expected = kind == Arity::One;
8308 assert_eq!(
8309 spec.has_output_arity(kind),
8310 expected,
8311 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One): query {kind:?} must be {expected}",
8312 );
8313 }
8314 }
8315
8316 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8317 /// identically through [`Self::has_output_arity`] AND through
8318 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
8319 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8320 /// classification, `Some(_)` classification on every
8321 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
8322 /// so a future regression on either side of the resolver fails HERE
8323 /// at the parity boundary. Byte-for-byte peer of the seven sibling
8324 /// two-surface parity pins on the SAME `Cow`-resolver carrier — the
8325 /// EIGHTH classification-axis two-surface parity contract on the
8326 /// ephemeral surface, closing the SECOND occupant of the (Option-
8327 /// parent × NESTED-STRUCT-scalar-child × derived-typed-projection)
8328 /// corner.
8329 #[test]
8330 fn has_output_arity_matches_point_peer_through_lowered_classification() {
8331 // Absent classification: both surfaces resolve through the SAME
8332 // default and agree on every variant.
8333 let eph = empty_ephemeral();
8334 let lowered: ProcessSpec = eph.clone().into();
8335 for query in Arity::ALL {
8336 assert_eq!(
8337 eph.has_output_arity(query),
8338 lowered.classification.has_output_arity(query),
8339 "None-classification parity drift on query {query:?}",
8340 );
8341 }
8342 // Authored classification: both surfaces read the same authored
8343 // point_type and route through the same projection.
8344 for populated in ConvergencePointType::ALL {
8345 let mut classification = Classification::gate_compute();
8346 classification.point_type = populated;
8347 let mut eph = empty_ephemeral();
8348 eph.classification = Some(classification);
8349 let lowered: ProcessSpec = eph.clone().into();
8350 for query in Arity::ALL {
8351 assert_eq!(
8352 eph.has_output_arity(query),
8353 lowered.classification.has_output_arity(query),
8354 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8355 );
8356 }
8357 }
8358 }
8359
8360 /// DAG-COMPOSITION ARITY-PAIR pin — the SEVENTH
8361 /// ([`Self::has_input_arity`]) and EIGHTH
8362 /// ([`Self::has_output_arity`]) classification-axis peers on the
8363 /// ephemeral surface walk the SAME `point_type` scalar carrier
8364 /// (routed through the SAME [`Self::resolved_classification`]
8365 /// resolver) through the SAME [`Arity`] closed set but through
8366 /// DIFFERENT typed projections
8367 /// ([`ConvergencePointType::input_arity`] vs.
8368 /// [`ConvergencePointType::output_arity`]). An [`EphemeralSpec`]
8369 /// with `classification.point_type = Fork` (the diffusive `(One,
8370 /// Many)` cell) MUST simultaneously answer `has_input_arity(One)`
8371 /// true AND `has_output_arity(Many)` true AND
8372 /// `has_input_arity(Many)` false AND `has_output_arity(One)` false.
8373 /// An [`EphemeralSpec`] with `point_type = Transform` (endomorphic
8374 /// `(One, One)`) MUST answer BOTH `has_input_arity(One)` and
8375 /// `has_output_arity(One)` true — the two projections AGREE in the
8376 /// endomorphic bucket. The absent-classification baseline (Gate,
8377 /// convergent `(Many, One)`) MUST answer
8378 /// `has_input_arity(Many)` true AND `has_output_arity(One)` true —
8379 /// the mirror of the Fork case. A regression that (a) collapsed
8380 /// `has_output_arity` onto `has_input_arity`, (b) swapped the
8381 /// projection direction, or (c) drifted the topology-bucket
8382 /// contract fails HERE at ONE narrow ephemeral-surface site,
8383 /// symmetric with the point-surface DAG-composition arity-pair pin.
8384 #[test]
8385 fn has_input_arity_and_has_output_arity_pin_dag_composition_pair() {
8386 // Diffusive cell: Fork carries (input, output) = (One, Many)
8387 let mut classification = Classification::gate_compute();
8388 classification.point_type = ConvergencePointType::Fork;
8389 let mut fork = empty_ephemeral();
8390 fork.classification = Some(classification);
8391 assert!(fork.has_input_arity(Arity::One));
8392 assert!(fork.has_output_arity(Arity::Many));
8393 assert!(!fork.has_input_arity(Arity::Many));
8394 assert!(!fork.has_output_arity(Arity::One));
8395
8396 // Endomorphic cell: Transform carries (input, output) = (One, One)
8397 let mut classification = Classification::gate_compute();
8398 classification.point_type = ConvergencePointType::Transform;
8399 let mut transform = empty_ephemeral();
8400 transform.classification = Some(classification);
8401 assert!(transform.has_input_arity(Arity::One));
8402 assert!(transform.has_output_arity(Arity::One));
8403 assert!(!transform.has_input_arity(Arity::Many));
8404 assert!(!transform.has_output_arity(Arity::Many));
8405
8406 // Convergent cell: absent classification defaults to Gate,
8407 // which carries (input, output) = (Many, One).
8408 let gate = empty_ephemeral();
8409 assert!(gate.classification.is_none());
8410 assert!(gate.has_input_arity(Arity::Many));
8411 assert!(gate.has_output_arity(Arity::One));
8412 assert!(!gate.has_input_arity(Arity::One));
8413 assert!(!gate.has_output_arity(Arity::Many));
8414 }
8415
8416 // ── EphemeralSpec::horizon_terminates pins ───────────────────────
8417 //
8418 // Fail-before-pass-after granularity: `horizon_terminates` did not
8419 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8420 // the "does this ephemeral spec's horizon terminate?" question
8421 // went through `.resolved_classification().horizon.kind.terminates()`
8422 // or through the lowered `ProcessSpec`'s
8423 // `spec.classification.horizon.kind.terminates()`. Post-lift the
8424 // NINTH classification-axis peer on the ephemeral surface routes
8425 // through the SAME [`Self::resolved_classification`] resolver +
8426 // the sibling substrate primitive
8427 // [`crate::classification::Classification::horizon_terminates`],
8428 // so the two-surface parity contract holds by construction — a
8429 // regression on either side of the resolver fails at these pins
8430 // before landing at the operator-facing `terminating-horizon`
8431 // fixed tag in `tatara-check`.
8432
8433 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8434 /// [`Classification`] carries a specific [`HorizonKind`] variant
8435 /// answers [`Self::horizon_terminates`] matching the closed
8436 /// set's own [`HorizonKind::terminates`] truth table. Sweep
8437 /// [`HorizonKind::ALL`] so a regression that (a) hard-coded the
8438 /// body to a fixed answer, (b) inverted the projection, or (c)
8439 /// crossed the wires with the antisymmetric partner
8440 /// [`HorizonKind::requires_metric_axes`] fails HERE at the
8441 /// substrate primitive before drifting through the
8442 /// `terminating-horizon` fixed tag or the peer point surface.
8443 #[test]
8444 fn horizon_terminates_returns_horizon_kind_projection_per_kind() {
8445 for populated in HorizonKind::ALL {
8446 let classification = Classification::gate_compute_with_axis(populated);
8447 let mut spec = empty_ephemeral();
8448 spec.classification = Some(classification);
8449 assert_eq!(
8450 spec.horizon_terminates(),
8451 populated.terminates(),
8452 "authored horizon.kind={populated:?}: horizon_terminates() drift",
8453 );
8454 }
8455 }
8456
8457 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8458 /// with `classification: None` routes through the
8459 /// [`Self::resolved_classification`] resolver's substrate default
8460 /// [`Classification::gate_compute`], which uses
8461 /// [`crate::classification::Horizon::default`] whose `kind`
8462 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
8463 /// [`HorizonKind::Bounded::terminates`] projects `true`, so
8464 /// [`Self::horizon_terminates`] returns `true`. Pins the default-
8465 /// arm short-circuit through THREE layers of `Default`
8466 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
8467 /// [`HorizonKind::default`]) reaching this derived-nullary
8468 /// predicate — a regression that dropped the resolver hop
8469 /// (silently answering `false` on an absent classification, as
8470 /// if the operator's absence meant "no horizon at all") fails
8471 /// HERE at ONE narrow ephemeral-surface site.
8472 #[test]
8473 fn horizon_terminates_probes_true_on_absent_classification() {
8474 let spec = empty_ephemeral();
8475 assert!(spec.classification.is_none());
8476 assert!(
8477 spec.horizon_terminates(),
8478 "absent classification (defaults to gate_compute, horizon.kind=Bounded → terminates=true)",
8479 );
8480 }
8481
8482 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8483 /// identically through [`Self::horizon_terminates`] AND through
8484 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_terminates()`
8485 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8486 /// classification, `Some(_)` classification on every
8487 /// [`HorizonKind::ALL`] variant) so a future regression on
8488 /// either side of the resolver fails HERE at the parity
8489 /// boundary. Byte-for-byte peer of the eight sibling two-surface
8490 /// parity pins on the SAME `Cow`-resolver carrier — the NINTH
8491 /// classification-axis two-surface parity contract on the
8492 /// ephemeral surface, and the FIRST via a derived-nullary-
8493 /// boolean predicate rather than a variant-equality probe.
8494 #[test]
8495 fn horizon_terminates_matches_point_peer_through_lowered_classification() {
8496 // Absent classification: both surfaces resolve through the SAME
8497 // default and agree.
8498 let eph = empty_ephemeral();
8499 let lowered: ProcessSpec = eph.clone().into();
8500 assert_eq!(
8501 eph.horizon_terminates(),
8502 lowered.classification.horizon_terminates(),
8503 "None-classification parity drift",
8504 );
8505 // Authored classification: both surfaces read the same authored
8506 // horizon.kind and route through the same projection.
8507 for populated in HorizonKind::ALL {
8508 let classification = Classification::gate_compute_with_axis(populated);
8509 let mut eph = empty_ephemeral();
8510 eph.classification = Some(classification);
8511 let lowered: ProcessSpec = eph.clone().into();
8512 assert_eq!(
8513 eph.horizon_terminates(),
8514 lowered.classification.horizon_terminates(),
8515 "authored horizon.kind={populated:?}: parity drift",
8516 );
8517 }
8518 }
8519
8520 // ── EphemeralSpec::horizon_requires_metric_axes pins ─────────────
8521 //
8522 // Fail-before-pass-after granularity: `horizon_requires_metric_axes`
8523 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
8524 // walking the "does this ephemeral spec's horizon require metric
8525 // axes?" question went through
8526 // `.resolved_classification().horizon.kind.requires_metric_axes()`
8527 // or through the lowered `ProcessSpec`'s
8528 // `spec.classification.horizon.kind.requires_metric_axes()`. Post-
8529 // lift the antisymmetric peer of `horizon_terminates` routes
8530 // through the SAME [`Self::resolved_classification`] resolver +
8531 // the sibling substrate primitive
8532 // [`crate::classification::Classification::horizon_requires_metric_axes`],
8533 // so the two-surface parity contract holds by construction — a
8534 // regression on either side of the resolver fails at these pins
8535 // before landing at the operator-facing `metric-axes-required`
8536 // fixed tag in `tatara-check`.
8537
8538 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8539 /// [`Classification`] carries a specific [`HorizonKind`] variant
8540 /// answers [`Self::horizon_requires_metric_axes`] matching the
8541 /// closed set's own [`HorizonKind::requires_metric_axes`] truth
8542 /// table. Sweep [`HorizonKind::ALL`] so a regression that (a)
8543 /// hard-coded the body to a fixed answer, (b) inverted the
8544 /// projection, or (c) crossed the wires with the antisymmetric
8545 /// partner [`HorizonKind::terminates`] fails HERE at the
8546 /// substrate primitive before drifting through the
8547 /// `metric-axes-required` fixed tag or the peer point surface.
8548 #[test]
8549 fn horizon_requires_metric_axes_returns_horizon_kind_projection_per_kind() {
8550 for populated in HorizonKind::ALL {
8551 let classification = Classification::gate_compute_with_axis(populated);
8552 let mut spec = empty_ephemeral();
8553 spec.classification = Some(classification);
8554 assert_eq!(
8555 spec.horizon_requires_metric_axes(),
8556 populated.requires_metric_axes(),
8557 "authored horizon.kind={populated:?}: horizon_requires_metric_axes() drift",
8558 );
8559 }
8560 }
8561
8562 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8563 /// with `classification: None` routes through the
8564 /// [`Self::resolved_classification`] resolver's substrate default
8565 /// [`Classification::gate_compute`], which uses
8566 /// [`crate::classification::Horizon::default`] whose `kind`
8567 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
8568 /// [`HorizonKind::Bounded::requires_metric_axes`] projects
8569 /// `false`, so [`Self::horizon_requires_metric_axes`] returns
8570 /// `false`. Pins the default-arm short-circuit through THREE
8571 /// layers of `Default` ([`Classification::gate_compute`] →
8572 /// [`Horizon::default`] → [`HorizonKind::default`]) reaching this
8573 /// derived-nullary predicate — mirror image of
8574 /// `horizon_terminates_probes_true_on_absent_classification`.
8575 #[test]
8576 fn horizon_requires_metric_axes_probes_false_on_absent_classification() {
8577 let spec = empty_ephemeral();
8578 assert!(spec.classification.is_none());
8579 assert!(
8580 !spec.horizon_requires_metric_axes(),
8581 "absent classification (defaults to gate_compute, horizon.kind=Bounded → requires_metric_axes=false)",
8582 );
8583 }
8584
8585 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8586 /// identically through [`Self::horizon_requires_metric_axes`]
8587 /// AND through
8588 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_requires_metric_axes()`
8589 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8590 /// classification, `Some(_)` classification on every
8591 /// [`HorizonKind::ALL`] variant) so a future regression on
8592 /// either side of the resolver fails HERE at the parity
8593 /// boundary. Byte-for-byte peer of the sibling
8594 /// `horizon_terminates_matches_point_peer_through_lowered_classification`.
8595 #[test]
8596 fn horizon_requires_metric_axes_matches_point_peer_through_lowered_classification() {
8597 // Absent classification.
8598 let eph = empty_ephemeral();
8599 let lowered: ProcessSpec = eph.clone().into();
8600 assert_eq!(
8601 eph.horizon_requires_metric_axes(),
8602 lowered.classification.horizon_requires_metric_axes(),
8603 "None-classification parity drift",
8604 );
8605 // Authored classification.
8606 for populated in HorizonKind::ALL {
8607 let classification = Classification::gate_compute_with_axis(populated);
8608 let mut eph = empty_ephemeral();
8609 eph.classification = Some(classification);
8610 let lowered: ProcessSpec = eph.clone().into();
8611 assert_eq!(
8612 eph.horizon_requires_metric_axes(),
8613 lowered.classification.horizon_requires_metric_axes(),
8614 "authored horizon.kind={populated:?}: parity drift",
8615 );
8616 }
8617 }
8618
8619 // ── EphemeralSpec::calm_requires_coordination pins ───────────────
8620 //
8621 // Fail-before-pass-after granularity: `calm_requires_coordination`
8622 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
8623 // walking the "does this ephemeral spec require coordination?"
8624 // question went through
8625 // `.resolved_classification().calm.requires_coordination()` or
8626 // through the lowered `ProcessSpec`'s
8627 // `spec.classification.calm.requires_coordination()`. Post-lift the
8628 // THIRD derived-nullary-boolean peer on the ephemeral surface
8629 // (first on the calm axis, after the two horizon-axis peers)
8630 // routes through the SAME [`Self::resolved_classification`]
8631 // resolver + the sibling substrate primitive
8632 // [`crate::classification::Classification::calm_requires_coordination`],
8633 // so the two-surface parity contract holds by construction — a
8634 // regression on either side of the resolver fails at these pins
8635 // before landing at the operator-facing `coordination-required`
8636 // fixed tag in `tatara-check`.
8637
8638 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8639 /// [`Classification`] carries a specific [`CalmClassification`]
8640 /// variant answers [`Self::calm_requires_coordination`] matching
8641 /// the closed set's own
8642 /// [`CalmClassification::requires_coordination`] truth table.
8643 /// Sweep [`CalmClassification::ALL`] so a regression that (a)
8644 /// hard-coded the body to a fixed answer, (b) inverted the
8645 /// projection, or (c) crossed the wires with a sibling
8646 /// classification-axis probe fails HERE at the substrate primitive
8647 /// before drifting through the `coordination-required` fixed tag
8648 /// or the peer point surface.
8649 #[test]
8650 fn calm_requires_coordination_returns_calm_projection_per_kind() {
8651 for populated in CalmClassification::ALL {
8652 let mut classification = Classification::gate_compute();
8653 classification.calm = populated;
8654 let mut spec = empty_ephemeral();
8655 spec.classification = Some(classification);
8656 assert_eq!(
8657 spec.calm_requires_coordination(),
8658 populated.requires_coordination(),
8659 "authored calm={populated:?}: calm_requires_coordination() drift",
8660 );
8661 }
8662 }
8663
8664 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8665 /// with `classification: None` routes through the
8666 /// [`Self::resolved_classification`] resolver's substrate default
8667 /// [`Classification::gate_compute`], which carries
8668 /// [`CalmClassification::default = Monotone`], and
8669 /// [`CalmClassification::Monotone::requires_coordination`] projects
8670 /// `false`, so [`Self::calm_requires_coordination`] returns
8671 /// `false`. Pins the default-arm short-circuit through TWO layers
8672 /// of `Default` ([`Classification::gate_compute`] →
8673 /// [`CalmClassification::default`]) reaching this derived-nullary
8674 /// predicate — distinct from the sibling `horizon_*` absent-
8675 /// classification pins by ONE structural degree (those walk THREE
8676 /// layers of `Default` because horizon has a nested-struct wrapper;
8677 /// this walks TWO because `calm` is a direct scalar). A regression
8678 /// that dropped the resolver hop (silently answering `true` on an
8679 /// absent classification, as if the operator's absence meant
8680 /// "requires coordination") fails HERE at ONE narrow ephemeral-
8681 /// surface site.
8682 #[test]
8683 fn calm_requires_coordination_probes_false_on_absent_classification() {
8684 let spec = empty_ephemeral();
8685 assert!(spec.classification.is_none());
8686 assert!(
8687 !spec.calm_requires_coordination(),
8688 "absent classification (defaults to gate_compute, calm=Monotone → requires_coordination=false)",
8689 );
8690 }
8691
8692 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8693 /// identically through [`Self::calm_requires_coordination`] AND
8694 /// through
8695 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_requires_coordination()`
8696 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8697 /// classification, `Some(_)` classification on every
8698 /// [`CalmClassification::ALL`] variant) so a future regression on
8699 /// either side of the resolver fails HERE at the parity boundary.
8700 /// Byte-for-byte peer of the sibling
8701 /// `horizon_terminates_matches_point_peer_through_lowered_classification`
8702 /// on the calm axis.
8703 #[test]
8704 fn calm_requires_coordination_matches_point_peer_through_lowered_classification() {
8705 // Absent classification.
8706 let eph = empty_ephemeral();
8707 let lowered: ProcessSpec = eph.clone().into();
8708 assert_eq!(
8709 eph.calm_requires_coordination(),
8710 lowered.classification.calm_requires_coordination(),
8711 "None-classification parity drift",
8712 );
8713 // Authored classification.
8714 for populated in CalmClassification::ALL {
8715 let mut classification = Classification::gate_compute();
8716 classification.calm = populated;
8717 let mut eph = empty_ephemeral();
8718 eph.classification = Some(classification);
8719 let lowered: ProcessSpec = eph.clone().into();
8720 assert_eq!(
8721 eph.calm_requires_coordination(),
8722 lowered.classification.calm_requires_coordination(),
8723 "authored calm={populated:?}: parity drift",
8724 );
8725 }
8726 }
8727
8728 // ── EphemeralSpec::data_is_regulated pins ────────────────────────
8729 //
8730 // Fail-before-pass-after granularity: `data_is_regulated` did not
8731 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8732 // the "does this ephemeral spec carry regulated data?" question
8733 // went through
8734 // `.resolved_classification().data_classification.is_regulated()`
8735 // or through the lowered `ProcessSpec`'s
8736 // `spec.classification.data_classification.is_regulated()`. Post-
8737 // lift the FOURTH derived-nullary-boolean peer on the ephemeral
8738 // surface (first on the data axis, after two horizon-axis peers
8739 // and one calm-axis peer) routes through the SAME
8740 // [`Self::resolved_classification`] resolver + the sibling
8741 // substrate primitive
8742 // [`crate::classification::Classification::data_is_regulated`],
8743 // so the two-surface parity contract holds by construction — a
8744 // regression on either side of the resolver fails at these pins
8745 // before landing at the operator-facing `data-regulated` fixed
8746 // tag in `tatara-check`.
8747
8748 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8749 /// [`Classification`] carries a specific [`DataClassification`]
8750 /// variant answers [`Self::data_is_regulated`] matching the
8751 /// closed set's own [`DataClassification::is_regulated`] truth
8752 /// table. Sweep [`DataClassification::ALL`] so a regression that
8753 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8754 /// projection, or (c) crossed the wires with a sibling
8755 /// classification-axis probe fails HERE at the substrate
8756 /// primitive before drifting through the `data-regulated` fixed
8757 /// tag or the peer point surface.
8758 #[test]
8759 fn data_is_regulated_returns_data_classification_projection_per_kind() {
8760 for populated in DataClassification::ALL {
8761 let mut classification = Classification::gate_compute();
8762 classification.data_classification = populated;
8763 let mut spec = empty_ephemeral();
8764 spec.classification = Some(classification);
8765 assert_eq!(
8766 spec.data_is_regulated(),
8767 populated.is_regulated(),
8768 "authored data_classification={populated:?}: data_is_regulated() drift",
8769 );
8770 }
8771 }
8772
8773 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8774 /// with `classification: None` routes through the
8775 /// [`Self::resolved_classification`] resolver's substrate default
8776 /// [`Classification::gate_compute`], which carries
8777 /// [`DataClassification::default = Internal`], and
8778 /// [`DataClassification::Internal::is_regulated`] projects
8779 /// `false`, so [`Self::data_is_regulated`] returns `false`. Pins
8780 /// the default-arm short-circuit through TWO layers of `Default`
8781 /// ([`Classification::gate_compute`] →
8782 /// [`DataClassification::default`]) reaching this derived-nullary
8783 /// predicate — byte-for-byte structural peer of the sibling
8784 /// `calm_requires_coordination_probes_false_on_absent_classification`
8785 /// on the classification-data axis, distinct from the two
8786 /// `horizon_*` absent-classification pins by ONE structural
8787 /// degree (those walk THREE layers because horizon has a nested-
8788 /// struct wrapper; this walks TWO because `data_classification`
8789 /// is a direct scalar). A regression that dropped the resolver
8790 /// hop (silently answering `true` on an absent classification,
8791 /// as if the operator's absence meant "regulated data") fails
8792 /// HERE at ONE narrow ephemeral-surface site.
8793 #[test]
8794 fn data_is_regulated_probes_false_on_absent_classification() {
8795 let spec = empty_ephemeral();
8796 assert!(spec.classification.is_none());
8797 assert!(
8798 !spec.data_is_regulated(),
8799 "absent classification (defaults to gate_compute, data_classification=Internal → is_regulated=false)",
8800 );
8801 }
8802
8803 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8804 /// identically through [`Self::data_is_regulated`] AND through
8805 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_regulated()`
8806 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8807 /// classification, `Some(_)` classification on every
8808 /// [`DataClassification::ALL`] variant) so a future regression on
8809 /// either side of the resolver fails HERE at the parity boundary.
8810 /// Byte-for-byte peer of the sibling
8811 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
8812 /// on the data axis.
8813 #[test]
8814 fn data_is_regulated_matches_point_peer_through_lowered_classification() {
8815 // Absent classification.
8816 let eph = empty_ephemeral();
8817 let lowered: ProcessSpec = eph.clone().into();
8818 assert_eq!(
8819 eph.data_is_regulated(),
8820 lowered.classification.data_is_regulated(),
8821 "None-classification parity drift",
8822 );
8823 // Authored classification.
8824 for populated in DataClassification::ALL {
8825 let mut classification = Classification::gate_compute();
8826 classification.data_classification = populated;
8827 let mut eph = empty_ephemeral();
8828 eph.classification = Some(classification);
8829 let lowered: ProcessSpec = eph.clone().into();
8830 assert_eq!(
8831 eph.data_is_regulated(),
8832 lowered.classification.data_is_regulated(),
8833 "authored data_classification={populated:?}: parity drift",
8834 );
8835 }
8836 }
8837
8838 // ── EphemeralSpec::data_is_restricted pins ───────────────────────
8839 //
8840 // Fail-before-pass-after granularity: `data_is_restricted` did not
8841 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8842 // the "does this ephemeral spec require access controls?" question
8843 // went through
8844 // `.resolved_classification().data_classification.is_restricted()`
8845 // or through the lowered `ProcessSpec`'s
8846 // `spec.classification.data_classification.is_restricted()`. Post-
8847 // lift the FIFTH derived-nullary-boolean peer on the ephemeral
8848 // surface (second on the data axis, after
8849 // [`Self::data_is_regulated`] opened the axis) routes through the
8850 // SAME [`Self::resolved_classification`] resolver + the sibling
8851 // substrate primitive
8852 // [`crate::classification::Classification::data_is_restricted`],
8853 // so the two-surface parity contract holds by construction — a
8854 // regression on either side of the resolver fails at these pins
8855 // before landing at the operator-facing `data-restricted` fixed
8856 // tag in `tatara-check`. FIRST direct-scalar ephemeral-surface
8857 // peer whose absent-classification baseline projects to `true`
8858 // rather than `false`.
8859
8860 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8861 /// [`Classification`] carries a specific [`DataClassification`]
8862 /// variant answers [`Self::data_is_restricted`] matching the
8863 /// closed set's own [`DataClassification::is_restricted`] truth
8864 /// table. Sweep [`DataClassification::ALL`] so a regression that
8865 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8866 /// projection, or (c) crossed the wires with the sibling
8867 /// [`DataClassification::is_regulated`] projection fails HERE at
8868 /// the substrate primitive before drifting through the
8869 /// `data-restricted` fixed tag or the peer point surface.
8870 #[test]
8871 fn data_is_restricted_returns_data_classification_projection_per_kind() {
8872 for populated in DataClassification::ALL {
8873 let mut classification = Classification::gate_compute();
8874 classification.data_classification = populated;
8875 let mut spec = empty_ephemeral();
8876 spec.classification = Some(classification);
8877 assert_eq!(
8878 spec.data_is_restricted(),
8879 populated.is_restricted(),
8880 "authored data_classification={populated:?}: data_is_restricted() drift",
8881 );
8882 }
8883 }
8884
8885 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8886 /// with `classification: None` routes through the
8887 /// [`Self::resolved_classification`] resolver's substrate default
8888 /// [`Classification::gate_compute`], which carries
8889 /// [`DataClassification::default = Internal`], and
8890 /// [`DataClassification::Internal::is_restricted`] projects
8891 /// `true`, so [`Self::data_is_restricted`] returns `true`. Pins
8892 /// the default-arm short-circuit through TWO layers of `Default`
8893 /// ([`Classification::gate_compute`] →
8894 /// [`DataClassification::default`]) reaching this derived-nullary
8895 /// predicate. FIRST direct-scalar ephemeral-surface peer whose
8896 /// absent-classification baseline answers `true`, not `false`
8897 /// (the four earlier direct-scalar peers on this surface —
8898 /// `data_is_regulated`, `calm_requires_coordination`, plus the
8899 /// nested-struct `horizon_requires_metric_axes` — all project
8900 /// `false` on the same absent classification, and only the
8901 /// sibling nested-struct `horizon_terminates` projects `true`).
8902 /// A regression that dropped the resolver hop (silently answering
8903 /// `false` on an absent classification, as if the operator's
8904 /// absence meant "freely distributable"), or that inverted the
8905 /// projection while the closed-set primitive stayed intact,
8906 /// fails HERE at ONE narrow ephemeral-surface site.
8907 #[test]
8908 fn data_is_restricted_probes_true_on_absent_classification() {
8909 let spec = empty_ephemeral();
8910 assert!(spec.classification.is_none());
8911 assert!(
8912 spec.data_is_restricted(),
8913 "absent classification (defaults to gate_compute, data_classification=Internal → is_restricted=true)",
8914 );
8915 }
8916
8917 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8918 /// identically through [`Self::data_is_restricted`] AND through
8919 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_restricted()`
8920 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8921 /// classification, `Some(_)` classification on every
8922 /// [`DataClassification::ALL`] variant) so a future regression on
8923 /// either side of the resolver fails HERE at the parity boundary.
8924 /// Byte-for-byte peer of the sibling
8925 /// `data_is_regulated_matches_point_peer_through_lowered_classification`
8926 /// on the same classification-data axis, published a second time
8927 /// through the antisymmetric closed-set projection.
8928 #[test]
8929 fn data_is_restricted_matches_point_peer_through_lowered_classification() {
8930 // Absent classification.
8931 let eph = empty_ephemeral();
8932 let lowered: ProcessSpec = eph.clone().into();
8933 assert_eq!(
8934 eph.data_is_restricted(),
8935 lowered.classification.data_is_restricted(),
8936 "None-classification parity drift",
8937 );
8938 // Authored classification.
8939 for populated in DataClassification::ALL {
8940 let mut classification = Classification::gate_compute();
8941 classification.data_classification = populated;
8942 let mut eph = empty_ephemeral();
8943 eph.classification = Some(classification);
8944 let lowered: ProcessSpec = eph.clone().into();
8945 assert_eq!(
8946 eph.data_is_restricted(),
8947 lowered.classification.data_is_restricted(),
8948 "authored data_classification={populated:?}: parity drift",
8949 );
8950 }
8951 }
8952
8953 /// COMPOSED IMPLICATION pin — the ephemeral-surface counterpart of
8954 /// the closed-set-internal
8955 /// `data_classification_regulated_implies_restricted` and its
8956 /// parent-composed peer
8957 /// `classification_data_is_regulated_implies_data_is_restricted_over_all`:
8958 /// for every ([`EphemeralSpec`] with authored classification
8959 /// carrying every [`DataClassification`] variant, plus the
8960 /// absent-classification case), the resolver-hop probe pair
8961 /// satisfies `data_is_regulated() ⇒ data_is_restricted()`. Pins
8962 /// the implication contract at the ephemeral-surface site so a
8963 /// regression that (a) inverted the ephemeral
8964 /// [`Self::data_is_regulated`] resolver hop, (b) inverted the
8965 /// ephemeral [`Self::data_is_restricted`] resolver hop, or (c)
8966 /// crossed their wires while the underlying substrate primitives
8967 /// stayed intact fails HERE. FIRST ephemeral-surface corner-peer
8968 /// pair whose two projections carry a non-trivial closed-set-
8969 /// internal implication relationship.
8970 #[test]
8971 fn ephemeral_data_is_regulated_implies_data_is_restricted_over_all() {
8972 // Absent classification.
8973 let eph = empty_ephemeral();
8974 assert!(
8975 !eph.data_is_regulated() || eph.data_is_restricted(),
8976 "None-classification: data_is_regulated ⇒ data_is_restricted violated",
8977 );
8978 // Authored classification.
8979 for populated in DataClassification::ALL {
8980 let mut classification = Classification::gate_compute();
8981 classification.data_classification = populated;
8982 let mut eph = empty_ephemeral();
8983 eph.classification = Some(classification);
8984 assert!(
8985 !eph.data_is_regulated() || eph.data_is_restricted(),
8986 "authored data_classification={populated:?}: data_is_regulated ⇒ data_is_restricted violated",
8987 );
8988 }
8989 }
8990
8991 // ── EphemeralSpec::point_is_endomorphic pins ─────────────────────
8992 //
8993 // Fail-before-pass-after granularity: `point_is_endomorphic` did
8994 // not exist pre-lift on `impl EphemeralSpec` — every consumer
8995 // walking the "does this ephemeral spec's point-type project to
8996 // the 1→1 endomorphic bucket?" question went through
8997 // `.resolved_classification().point_type.is_endomorphic()` or the
8998 // lowered `ProcessSpec`'s
8999 // `spec.classification.point_type.is_endomorphic()`. Post-lift the
9000 // SIXTH derived-nullary-boolean peer on the ephemeral surface
9001 // (first on the `point_type` axis) routes through the SAME
9002 // [`Self::resolved_classification`] resolver + the sibling
9003 // substrate primitive
9004 // [`crate::classification::Classification::point_is_endomorphic`],
9005 // so the two-surface parity contract holds by construction — a
9006 // regression on either side of the resolver fails at these pins
9007 // before landing at the operator-facing `endomorphic-point` fixed
9008 // tag in `tatara-check`.
9009
9010 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9011 /// [`Classification`] carries a specific [`ConvergencePointType`]
9012 /// variant answers [`Self::point_is_endomorphic`] matching the
9013 /// closed set's own [`ConvergencePointType::is_endomorphic`] truth
9014 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9015 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9016 /// projection, or (c) crossed the wires with the sibling
9017 /// [`ConvergencePointType::is_diffusive`] /
9018 /// [`ConvergencePointType::is_convergent`] projections fails
9019 /// HERE at the substrate primitive before drifting through the
9020 /// `endomorphic-point` fixed tag or the peer point surface.
9021 #[test]
9022 fn point_is_endomorphic_returns_point_type_projection_per_kind() {
9023 for populated in ConvergencePointType::ALL {
9024 let mut classification = Classification::gate_compute();
9025 classification.point_type = populated;
9026 let mut spec = empty_ephemeral();
9027 spec.classification = Some(classification);
9028 assert_eq!(
9029 spec.point_is_endomorphic(),
9030 populated.is_endomorphic(),
9031 "authored point_type={populated:?}: point_is_endomorphic() drift",
9032 );
9033 }
9034 }
9035
9036 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9037 /// with `classification: None` routes through the
9038 /// [`Self::resolved_classification`] resolver's substrate default
9039 /// [`Classification::gate_compute`], which carries
9040 /// [`ConvergencePointType::Gate`] (a convergent barrier, not an
9041 /// endomorphism), and
9042 /// [`ConvergencePointType::Gate::is_endomorphic`] projects `false`,
9043 /// so [`Self::point_is_endomorphic`] returns `false`. Pins the
9044 /// resolver's chosen-field baseline at ONE narrow site — a
9045 /// regression that dropped the resolver hop, or that promoted
9046 /// [`ConvergencePointType::Transform`] to the gate-compute
9047 /// baseline (silently retargeting every unadorned ephemeral
9048 /// spec's topology bucket), fails HERE at ONE narrow ephemeral-
9049 /// surface site. FIRST direct-scalar ephemeral-surface peer whose
9050 /// absent-classification baseline is a chosen-field answer on the
9051 /// resolver's [`Classification::gate_compute`] default rather
9052 /// than a substrate-`#[default]` short-circuit on the closed-set
9053 /// side ([`ConvergencePointType`] has no `impl Default`).
9054 #[test]
9055 fn point_is_endomorphic_probes_false_on_absent_classification() {
9056 let spec = empty_ephemeral();
9057 assert!(spec.classification.is_none());
9058 assert!(
9059 !spec.point_is_endomorphic(),
9060 "absent classification (defaults to gate_compute, point_type=Gate → is_endomorphic=false)",
9061 );
9062 }
9063
9064 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9065 /// identically through [`Self::point_is_endomorphic`] AND through
9066 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_endomorphic()`
9067 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9068 /// classification, `Some(_)` classification on every
9069 /// [`ConvergencePointType::ALL`] variant) so a future regression
9070 /// on either side of the resolver fails HERE at the parity
9071 /// boundary. Byte-for-byte peer of the sibling
9072 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
9073 /// on a DIFFERENT closed-set axis, published a first time through
9074 /// the `point_type` closed-set projection.
9075 #[test]
9076 fn point_is_endomorphic_matches_point_peer_through_lowered_classification() {
9077 // Absent classification.
9078 let eph = empty_ephemeral();
9079 let lowered: ProcessSpec = eph.clone().into();
9080 assert_eq!(
9081 eph.point_is_endomorphic(),
9082 lowered.classification.point_is_endomorphic(),
9083 "None-classification parity drift",
9084 );
9085 // Authored classification.
9086 for populated in ConvergencePointType::ALL {
9087 let mut classification = Classification::gate_compute();
9088 classification.point_type = populated;
9089 let mut eph = empty_ephemeral();
9090 eph.classification = Some(classification);
9091 let lowered: ProcessSpec = eph.clone().into();
9092 assert_eq!(
9093 eph.point_is_endomorphic(),
9094 lowered.classification.point_is_endomorphic(),
9095 "authored point_type={populated:?}: parity drift",
9096 );
9097 }
9098 }
9099
9100 // ── EphemeralSpec::point_is_diffusive pins ───────────────────────
9101 //
9102 // Fail-before-pass-after granularity: `point_is_diffusive` did not
9103 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9104 // the "does this ephemeral spec's point-type project to the 1→N
9105 // diffusive fan-out bucket?" question went through
9106 // `.resolved_classification().point_type.is_diffusive()` or the
9107 // lowered `ProcessSpec`'s
9108 // `spec.classification.point_type.is_diffusive()`. Post-lift the
9109 // SEVENTH derived-nullary-boolean peer on the ephemeral surface
9110 // (SECOND on the `point_type` axis) routes through the SAME
9111 // [`Self::resolved_classification`] resolver + the sibling
9112 // substrate primitive
9113 // [`crate::classification::Classification::point_is_diffusive`],
9114 // so the two-surface parity contract holds by construction.
9115
9116 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9117 /// [`Classification`] carries a specific [`ConvergencePointType`]
9118 /// variant answers [`Self::point_is_diffusive`] matching the
9119 /// closed set's own [`ConvergencePointType::is_diffusive`] truth
9120 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9121 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9122 /// projection, or (c) crossed the wires with the sibling
9123 /// [`ConvergencePointType::is_endomorphic`] /
9124 /// [`ConvergencePointType::is_convergent`] projections fails HERE
9125 /// at the substrate primitive before drifting through the
9126 /// `diffusive-point` fixed tag or the peer point surface.
9127 #[test]
9128 fn point_is_diffusive_returns_point_type_projection_per_kind() {
9129 for populated in ConvergencePointType::ALL {
9130 let mut classification = Classification::gate_compute();
9131 classification.point_type = populated;
9132 let mut spec = empty_ephemeral();
9133 spec.classification = Some(classification);
9134 assert_eq!(
9135 spec.point_is_diffusive(),
9136 populated.is_diffusive(),
9137 "authored point_type={populated:?}: point_is_diffusive() drift",
9138 );
9139 }
9140 }
9141
9142 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9143 /// with `classification: None` routes through the
9144 /// [`Self::resolved_classification`] resolver's substrate default
9145 /// [`Classification::gate_compute`], which carries
9146 /// [`ConvergencePointType::Gate`] (a convergent barrier, not a
9147 /// diffusive fan-out), and
9148 /// [`ConvergencePointType::Gate::is_diffusive`] projects `false`,
9149 /// so [`Self::point_is_diffusive`] returns `false`. Pins the
9150 /// resolver's chosen-field baseline at ONE narrow site.
9151 #[test]
9152 fn point_is_diffusive_probes_false_on_absent_classification() {
9153 let spec = empty_ephemeral();
9154 assert!(spec.classification.is_none());
9155 assert!(
9156 !spec.point_is_diffusive(),
9157 "absent classification (defaults to gate_compute, point_type=Gate → is_diffusive=false)",
9158 );
9159 }
9160
9161 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9162 /// identically through [`Self::point_is_diffusive`] AND through
9163 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_diffusive()`
9164 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9165 /// classification, `Some(_)` classification on every
9166 /// [`ConvergencePointType::ALL`] variant) so a future regression
9167 /// on either side of the resolver fails HERE at the parity
9168 /// boundary. Byte-for-byte peer of
9169 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
9170 /// on the SAME closed-set axis via a sibling projection.
9171 #[test]
9172 fn point_is_diffusive_matches_point_peer_through_lowered_classification() {
9173 // Absent classification.
9174 let eph = empty_ephemeral();
9175 let lowered: ProcessSpec = eph.clone().into();
9176 assert_eq!(
9177 eph.point_is_diffusive(),
9178 lowered.classification.point_is_diffusive(),
9179 "None-classification parity drift",
9180 );
9181 // Authored classification.
9182 for populated in ConvergencePointType::ALL {
9183 let mut classification = Classification::gate_compute();
9184 classification.point_type = populated;
9185 let mut eph = empty_ephemeral();
9186 eph.classification = Some(classification);
9187 let lowered: ProcessSpec = eph.clone().into();
9188 assert_eq!(
9189 eph.point_is_diffusive(),
9190 lowered.classification.point_is_diffusive(),
9191 "authored point_type={populated:?}: parity drift",
9192 );
9193 }
9194 }
9195
9196 /// MUTEX pin — [`Self::point_is_endomorphic`] AND
9197 /// [`Self::point_is_diffusive`] are NEVER simultaneously true for
9198 /// ANY [`EphemeralSpec`] (authored or defaulted), since the
9199 /// underlying [`ConvergencePointType`] closed set carves its
9200 /// eight variants into THREE disjoint buckets. Sweep the absent-
9201 /// classification case + every [`ConvergencePointType::ALL`]
9202 /// variant so a regression that crossed the wires between the
9203 /// two ephemeral-surface corner peers (one probe silently
9204 /// composing the wrong closed-set arm at the resolver-hop layer)
9205 /// fails HERE rather than at every downstream consumer that
9206 /// trusts the two probes partition the resolver's output into
9207 /// disjoint buckets. FIRST ephemeral-surface corner-peer pair on
9208 /// the `point_type` axis whose two projections carry a non-
9209 /// trivial closed-set-internal MUTEX relationship (distinct from
9210 /// the sibling `data`-axis pair whose two projections carry a
9211 /// non-trivial IMPLICATION relationship, sealed by
9212 /// `ephemeral_data_is_regulated_implies_data_is_restricted_over_all`).
9213 #[test]
9214 fn ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all() {
9215 // Absent classification.
9216 let eph = empty_ephemeral();
9217 assert!(
9218 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
9219 "None-classification: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
9220 );
9221 // Authored classification.
9222 for populated in ConvergencePointType::ALL {
9223 let mut classification = Classification::gate_compute();
9224 classification.point_type = populated;
9225 let mut eph = empty_ephemeral();
9226 eph.classification = Some(classification);
9227 assert!(
9228 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
9229 "authored point_type={populated:?}: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
9230 );
9231 }
9232 }
9233
9234 // ── EphemeralSpec::point_is_convergent pins ──────────────────────
9235 //
9236 // Fail-before-pass-after granularity: `point_is_convergent` did
9237 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9238 // walking the "does this ephemeral spec's point-type project to
9239 // the N→1 convergent fan-in bucket?" question went through
9240 // `.resolved_classification().point_type.is_convergent()` or the
9241 // lowered `ProcessSpec`'s
9242 // `spec.classification.point_type.is_convergent()`. Post-lift the
9243 // EIGHTH derived-nullary-boolean peer on the ephemeral surface
9244 // (THIRD on the `point_type` axis) routes through the SAME
9245 // [`Self::resolved_classification`] resolver + the sibling
9246 // substrate primitive
9247 // [`crate::classification::Classification::point_is_convergent`],
9248 // so the two-surface parity contract holds by construction, AND
9249 // the THREE `point_type`-axis peers on this surface close into
9250 // the FULL three-way XOR partition contract.
9251
9252 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9253 /// [`Classification`] carries a specific [`ConvergencePointType`]
9254 /// variant answers [`Self::point_is_convergent`] matching the
9255 /// closed set's own [`ConvergencePointType::is_convergent`] truth
9256 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9257 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9258 /// projection, or (c) crossed the wires with the sibling
9259 /// [`ConvergencePointType::is_endomorphic`] /
9260 /// [`ConvergencePointType::is_diffusive`] projections fails HERE
9261 /// at the substrate primitive before drifting through the
9262 /// `convergent-point` fixed tag or the peer point surface.
9263 #[test]
9264 fn point_is_convergent_returns_point_type_projection_per_kind() {
9265 for populated in ConvergencePointType::ALL {
9266 let mut classification = Classification::gate_compute();
9267 classification.point_type = populated;
9268 let mut spec = empty_ephemeral();
9269 spec.classification = Some(classification);
9270 assert_eq!(
9271 spec.point_is_convergent(),
9272 populated.is_convergent(),
9273 "authored point_type={populated:?}: point_is_convergent() drift",
9274 );
9275 }
9276 }
9277
9278 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9279 /// with `classification: None` routes through the
9280 /// [`Self::resolved_classification`] resolver's substrate default
9281 /// [`Classification::gate_compute`], which carries
9282 /// [`ConvergencePointType::Gate`] (the canonical convergent
9283 /// barrier), and [`ConvergencePointType::Gate::is_convergent`]
9284 /// projects `true`, so [`Self::point_is_convergent`] returns
9285 /// `true`. Pins the resolver's chosen-field baseline at ONE
9286 /// narrow site — FIRST direct-scalar ephemeral-surface peer whose
9287 /// absent-classification baseline projects `true` through the
9288 /// resolver's chosen-field answer, mirror-inverted from the two
9289 /// sibling `point_is_endomorphic` / `point_is_diffusive`
9290 /// ephemeral-surface baselines which both project `false`.
9291 #[test]
9292 fn point_is_convergent_probes_true_on_absent_classification() {
9293 let spec = empty_ephemeral();
9294 assert!(spec.classification.is_none());
9295 assert!(
9296 spec.point_is_convergent(),
9297 "absent classification (defaults to gate_compute, point_type=Gate → is_convergent=true)",
9298 );
9299 }
9300
9301 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9302 /// identically through [`Self::point_is_convergent`] AND through
9303 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_convergent()`
9304 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9305 /// classification, `Some(_)` classification on every
9306 /// [`ConvergencePointType::ALL`] variant) so a future regression
9307 /// on either side of the resolver fails HERE at the parity
9308 /// boundary. Byte-for-byte peer of
9309 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
9310 /// and
9311 /// `point_is_diffusive_matches_point_peer_through_lowered_classification`
9312 /// on the SAME closed-set axis via a sibling projection.
9313 #[test]
9314 fn point_is_convergent_matches_point_peer_through_lowered_classification() {
9315 // Absent classification.
9316 let eph = empty_ephemeral();
9317 let lowered: ProcessSpec = eph.clone().into();
9318 assert_eq!(
9319 eph.point_is_convergent(),
9320 lowered.classification.point_is_convergent(),
9321 "None-classification parity drift",
9322 );
9323 // Authored classification.
9324 for populated in ConvergencePointType::ALL {
9325 let mut classification = Classification::gate_compute();
9326 classification.point_type = populated;
9327 let mut eph = empty_ephemeral();
9328 eph.classification = Some(classification);
9329 let lowered: ProcessSpec = eph.clone().into();
9330 assert_eq!(
9331 eph.point_is_convergent(),
9332 lowered.classification.point_is_convergent(),
9333 "authored point_type={populated:?}: parity drift",
9334 );
9335 }
9336 }
9337
9338 /// THREE-WAY XOR PARTITION pin — for the absent-classification
9339 /// baseline AND every [`ConvergencePointType::ALL`] variant,
9340 /// EXACTLY ONE of [`Self::point_is_endomorphic`],
9341 /// [`Self::point_is_diffusive`], and [`Self::point_is_convergent`]
9342 /// returns `true`. Closes the mutex pair
9343 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`
9344 /// into the FULL ternary XOR partition contract on the ephemeral
9345 /// surface — the resolver-hop peer of the parent-composed
9346 /// `classification_point_type_probes_form_three_way_xor_partition_over_all`
9347 /// test. Guarantees the absent-classification case lands in the
9348 /// convergent bucket (`gate_compute` → Gate → is_convergent =
9349 /// true), so every unadorned `(defephemeral …)` audits under a
9350 /// definite non-empty topology bucket.
9351 #[test]
9352 fn ephemeral_point_type_probes_form_three_way_xor_partition_over_all() {
9353 // Absent classification.
9354 let eph = empty_ephemeral();
9355 let buckets = [
9356 eph.point_is_endomorphic(),
9357 eph.point_is_diffusive(),
9358 eph.point_is_convergent(),
9359 ];
9360 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9361 assert_eq!(
9362 hits, 1,
9363 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9364 );
9365 // Authored classification.
9366 for populated in ConvergencePointType::ALL {
9367 let mut classification = Classification::gate_compute();
9368 classification.point_type = populated;
9369 let mut eph = empty_ephemeral();
9370 eph.classification = Some(classification);
9371 let buckets = [
9372 eph.point_is_endomorphic(),
9373 eph.point_is_diffusive(),
9374 eph.point_is_convergent(),
9375 ];
9376 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9377 assert_eq!(
9378 hits, 1,
9379 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9380 );
9381 }
9382 }
9383
9384 // ── EphemeralSpec::substrate_is_resource pins ────────────────────
9385 //
9386 // Fail-before-pass-after granularity: `substrate_is_resource` did
9387 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9388 // walking the "does this ephemeral spec's substrate project to
9389 // the resource plane?" question went through
9390 // `.resolved_classification().substrate.is_resource()` or the
9391 // lowered `ProcessSpec`'s
9392 // `spec.classification.substrate.is_resource()`. Post-lift the
9393 // NINTH derived-nullary-boolean peer on the ephemeral surface
9394 // (FIRST on the `substrate` axis) routes through the SAME
9395 // [`Self::resolved_classification`] resolver + the sibling
9396 // substrate primitive
9397 // [`crate::classification::Classification::substrate_is_resource`],
9398 // so the two-surface parity contract holds by construction.
9399
9400 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9401 /// [`Classification`] carries a specific
9402 /// [`crate::classification::SubstrateType`] variant answers
9403 /// [`Self::substrate_is_resource`] matching the closed set's own
9404 /// [`crate::classification::SubstrateType::is_resource`] truth
9405 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
9406 /// so a regression that (a) hard-coded the body to a fixed
9407 /// answer, (b) inverted the projection, or (c) crossed the wires
9408 /// with the sibling
9409 /// [`crate::classification::SubstrateType::is_policy`] /
9410 /// [`crate::classification::SubstrateType::is_telemetry`]
9411 /// projections fails HERE at the substrate primitive before
9412 /// drifting through the `resource-substrate` fixed tag or the
9413 /// peer point surface.
9414 #[test]
9415 fn substrate_is_resource_returns_substrate_projection_per_kind() {
9416 for populated in SubstrateType::ALL {
9417 let mut classification = Classification::gate_compute();
9418 classification.substrate = populated;
9419 let mut spec = empty_ephemeral();
9420 spec.classification = Some(classification);
9421 assert_eq!(
9422 spec.substrate_is_resource(),
9423 populated.is_resource(),
9424 "authored substrate={populated:?}: substrate_is_resource() drift",
9425 );
9426 }
9427 }
9428
9429 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9430 /// with `classification: None` routes through the
9431 /// [`Self::resolved_classification`] resolver's substrate default
9432 /// [`Classification::gate_compute`], which carries
9433 /// [`crate::classification::SubstrateType::Compute`] (the
9434 /// canonical resource-plane substrate), and
9435 /// [`crate::classification::SubstrateType::Compute::is_resource`]
9436 /// projects `true`, so [`Self::substrate_is_resource`] returns
9437 /// `true`. Pins the resolver's chosen-field baseline at ONE
9438 /// narrow site — mirror-aligned with the sibling
9439 /// `point_is_convergent_probes_true_on_absent_classification`
9440 /// baseline (both projections on `gate_compute` chosen fields
9441 /// answer `true`).
9442 #[test]
9443 fn substrate_is_resource_probes_true_on_absent_classification() {
9444 let spec = empty_ephemeral();
9445 assert!(spec.classification.is_none());
9446 assert!(
9447 spec.substrate_is_resource(),
9448 "absent classification (defaults to gate_compute, substrate=Compute → is_resource=true)",
9449 );
9450 }
9451
9452 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9453 /// identically through [`Self::substrate_is_resource`] AND through
9454 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_resource()`
9455 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9456 /// classification, `Some(_)` classification on every
9457 /// [`crate::classification::SubstrateType::ALL`] variant) so a
9458 /// future regression on either side of the resolver fails HERE
9459 /// at the parity boundary. Byte-for-byte peer of
9460 /// `point_is_convergent_matches_point_peer_through_lowered_classification`
9461 /// on a sibling classification axis.
9462 #[test]
9463 fn substrate_is_resource_matches_point_peer_through_lowered_classification() {
9464 // Absent classification.
9465 let eph = empty_ephemeral();
9466 let lowered: ProcessSpec = eph.clone().into();
9467 assert_eq!(
9468 eph.substrate_is_resource(),
9469 lowered.classification.substrate_is_resource(),
9470 "None-classification parity drift",
9471 );
9472 // Authored classification.
9473 for populated in SubstrateType::ALL {
9474 let mut classification = Classification::gate_compute();
9475 classification.substrate = populated;
9476 let mut eph = empty_ephemeral();
9477 eph.classification = Some(classification);
9478 let lowered: ProcessSpec = eph.clone().into();
9479 assert_eq!(
9480 eph.substrate_is_resource(),
9481 lowered.classification.substrate_is_resource(),
9482 "authored substrate={populated:?}: parity drift",
9483 );
9484 }
9485 }
9486
9487 // ── EphemeralSpec::substrate_is_policy pins ──────────────────────
9488 //
9489 // Fail-before-pass-after granularity: `substrate_is_policy` did
9490 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9491 // walking the "does this ephemeral spec's substrate project to
9492 // the policy plane?" question went through
9493 // `.resolved_classification().substrate.is_policy()` or the
9494 // lowered `ProcessSpec`'s
9495 // `spec.classification.substrate.is_policy()`. Post-lift the
9496 // TENTH derived-nullary-boolean peer on the ephemeral surface
9497 // (SECOND on the `substrate` axis) routes through the SAME
9498 // [`Self::resolved_classification`] resolver + the sibling
9499 // substrate primitive
9500 // [`crate::classification::Classification::substrate_is_policy`],
9501 // so the two-surface parity contract holds by construction, AND
9502 // the two `substrate`-axis peers on this surface open the
9503 // MUTEX pair on the axis via
9504 // `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`.
9505
9506 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9507 /// [`Classification`] carries a specific
9508 /// [`crate::classification::SubstrateType`] variant answers
9509 /// [`Self::substrate_is_policy`] matching the closed set's own
9510 /// [`crate::classification::SubstrateType::is_policy`] truth
9511 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
9512 /// so a regression that (a) hard-coded the body to a fixed
9513 /// answer, (b) inverted the projection, or (c) crossed the wires
9514 /// with the sibling
9515 /// [`crate::classification::SubstrateType::is_resource`] /
9516 /// [`crate::classification::SubstrateType::is_telemetry`]
9517 /// projections fails HERE at the substrate primitive before
9518 /// drifting through the `policy-substrate` fixed tag or the
9519 /// peer point surface.
9520 #[test]
9521 fn substrate_is_policy_returns_substrate_projection_per_kind() {
9522 for populated in SubstrateType::ALL {
9523 let mut classification = Classification::gate_compute();
9524 classification.substrate = populated;
9525 let mut spec = empty_ephemeral();
9526 spec.classification = Some(classification);
9527 assert_eq!(
9528 spec.substrate_is_policy(),
9529 populated.is_policy(),
9530 "authored substrate={populated:?}: substrate_is_policy() drift",
9531 );
9532 }
9533 }
9534
9535 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9536 /// with `classification: None` routes through the
9537 /// [`Self::resolved_classification`] resolver's substrate default
9538 /// [`Classification::gate_compute`], which carries
9539 /// [`crate::classification::SubstrateType::Compute`] (the
9540 /// canonical resource-plane substrate, NOT a policy plane), and
9541 /// [`crate::classification::SubstrateType::Compute::is_policy`]
9542 /// projects `false`, so [`Self::substrate_is_policy`] returns
9543 /// `false`. Pins the resolver's chosen-field baseline at ONE
9544 /// narrow site — mirror-inverted from the sibling
9545 /// `substrate_is_resource_probes_true_on_absent_classification`
9546 /// (both projections on `gate_compute`'s chosen `substrate`
9547 /// field, but the sibling answers `true` where this one
9548 /// answers `false` — the closed set's disjoint plane partition
9549 /// forbids both being true).
9550 #[test]
9551 fn substrate_is_policy_probes_false_on_absent_classification() {
9552 let spec = empty_ephemeral();
9553 assert!(spec.classification.is_none());
9554 assert!(
9555 !spec.substrate_is_policy(),
9556 "absent classification (defaults to gate_compute, substrate=Compute → is_policy=false)",
9557 );
9558 }
9559
9560 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9561 /// identically through [`Self::substrate_is_policy`] AND through
9562 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_policy()`
9563 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9564 /// classification, `Some(_)` classification on every
9565 /// [`crate::classification::SubstrateType::ALL`] variant) so a
9566 /// future regression on either side of the resolver fails HERE
9567 /// at the parity boundary. Byte-for-byte peer of
9568 /// `substrate_is_resource_matches_point_peer_through_lowered_classification`
9569 /// on the SAME closed-set axis via a sibling projection.
9570 #[test]
9571 fn substrate_is_policy_matches_point_peer_through_lowered_classification() {
9572 // Absent classification.
9573 let eph = empty_ephemeral();
9574 let lowered: ProcessSpec = eph.clone().into();
9575 assert_eq!(
9576 eph.substrate_is_policy(),
9577 lowered.classification.substrate_is_policy(),
9578 "None-classification parity drift",
9579 );
9580 // Authored classification.
9581 for populated in SubstrateType::ALL {
9582 let mut classification = Classification::gate_compute();
9583 classification.substrate = populated;
9584 let mut eph = empty_ephemeral();
9585 eph.classification = Some(classification);
9586 let lowered: ProcessSpec = eph.clone().into();
9587 assert_eq!(
9588 eph.substrate_is_policy(),
9589 lowered.classification.substrate_is_policy(),
9590 "authored substrate={populated:?}: parity drift",
9591 );
9592 }
9593 }
9594
9595 /// MUTEX pin — [`Self::substrate_is_resource`] AND
9596 /// [`Self::substrate_is_policy`] are NEVER simultaneously true
9597 /// for ANY [`EphemeralSpec`] (authored or defaulted), since the
9598 /// underlying [`crate::classification::SubstrateType`] closed set
9599 /// carves its eight variants into THREE disjoint buckets. Sweep
9600 /// the absent-classification case + every
9601 /// [`crate::classification::SubstrateType::ALL`] variant so a
9602 /// regression that crossed the wires between the two ephemeral-
9603 /// surface corner peers (one probe silently composing the wrong
9604 /// closed-set arm at the resolver-hop layer) fails HERE rather
9605 /// than at every downstream consumer that trusts the two probes
9606 /// partition the resolver's output into disjoint buckets.
9607 /// FIRST ephemeral-surface `substrate`-axis corner-peer pair
9608 /// carrying a non-trivial MUTEX relationship — structural twin
9609 /// of the sibling `point_type`-axis MUTEX pair sealed on this
9610 /// surface by
9611 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
9612 #[test]
9613 fn ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all() {
9614 // Absent classification.
9615 let eph = empty_ephemeral();
9616 assert!(
9617 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
9618 "None-classification: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
9619 );
9620 // Authored classification.
9621 for populated in SubstrateType::ALL {
9622 let mut classification = Classification::gate_compute();
9623 classification.substrate = populated;
9624 let mut eph = empty_ephemeral();
9625 eph.classification = Some(classification);
9626 assert!(
9627 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
9628 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
9629 );
9630 }
9631 }
9632
9633 // ── EphemeralSpec::substrate_is_telemetry pins ───────────────────
9634 //
9635 // Fail-before-pass-after granularity: `substrate_is_telemetry`
9636 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9637 // walking the "does this ephemeral spec's substrate project to
9638 // the telemetry plane?" question went through
9639 // `.resolved_classification().substrate.is_telemetry()` or the
9640 // lowered `ProcessSpec`'s
9641 // `spec.classification.substrate.is_telemetry()`. Post-lift the
9642 // ELEVENTH derived-nullary-boolean peer on the ephemeral surface
9643 // (THIRD on the `substrate` axis) routes through the SAME
9644 // [`Self::resolved_classification`] resolver + the sibling
9645 // substrate primitive
9646 // [`crate::classification::Classification::substrate_is_telemetry`],
9647 // so the two-surface parity contract holds by construction, AND
9648 // the three `substrate`-axis peers on this surface CLOSE the
9649 // axis into the FULL three-way XOR partition contract via
9650 // `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
9651
9652 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9653 /// [`Classification`] carries a specific
9654 /// [`crate::classification::SubstrateType`] variant answers
9655 /// [`Self::substrate_is_telemetry`] matching the closed set's own
9656 /// [`crate::classification::SubstrateType::is_telemetry`] truth
9657 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
9658 /// so a regression that (a) hard-coded the body to a fixed
9659 /// answer, (b) inverted the projection, or (c) crossed the wires
9660 /// with the sibling
9661 /// [`crate::classification::SubstrateType::is_resource`] /
9662 /// [`crate::classification::SubstrateType::is_policy`]
9663 /// projections fails HERE at the substrate primitive before
9664 /// drifting through the `telemetry-substrate` fixed tag or the
9665 /// peer point surface.
9666 #[test]
9667 fn substrate_is_telemetry_returns_substrate_projection_per_kind() {
9668 for populated in SubstrateType::ALL {
9669 let mut classification = Classification::gate_compute();
9670 classification.substrate = populated;
9671 let mut spec = empty_ephemeral();
9672 spec.classification = Some(classification);
9673 assert_eq!(
9674 spec.substrate_is_telemetry(),
9675 populated.is_telemetry(),
9676 "authored substrate={populated:?}: substrate_is_telemetry() drift",
9677 );
9678 }
9679 }
9680
9681 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9682 /// with `classification: None` routes through the
9683 /// [`Self::resolved_classification`] resolver's substrate default
9684 /// [`Classification::gate_compute`], which carries
9685 /// [`crate::classification::SubstrateType::Compute`] (the
9686 /// canonical resource-plane substrate, NOT a telemetry plane),
9687 /// and
9688 /// [`crate::classification::SubstrateType::Compute::is_telemetry`]
9689 /// projects `false`, so [`Self::substrate_is_telemetry`] returns
9690 /// `false`. Pins the resolver's chosen-field baseline at ONE
9691 /// narrow site — aligned with the sibling
9692 /// `substrate_is_policy_probes_false_on_absent_classification`
9693 /// (both projections on `gate_compute`'s chosen `substrate`
9694 /// field project `false` since `Compute` lives in the resource
9695 /// plane), mirror-inverted from
9696 /// `substrate_is_resource_probes_true_on_absent_classification`.
9697 #[test]
9698 fn substrate_is_telemetry_probes_false_on_absent_classification() {
9699 let spec = empty_ephemeral();
9700 assert!(spec.classification.is_none());
9701 assert!(
9702 !spec.substrate_is_telemetry(),
9703 "absent classification (defaults to gate_compute, substrate=Compute → is_telemetry=false)",
9704 );
9705 }
9706
9707 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9708 /// identically through [`Self::substrate_is_telemetry`] AND
9709 /// through
9710 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_telemetry()`
9711 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9712 /// classification, `Some(_)` classification on every
9713 /// [`crate::classification::SubstrateType::ALL`] variant) so a
9714 /// future regression on either side of the resolver fails HERE
9715 /// at the parity boundary. Byte-for-byte peer of
9716 /// `substrate_is_policy_matches_point_peer_through_lowered_classification`
9717 /// on the SAME closed-set axis via a sibling projection.
9718 #[test]
9719 fn substrate_is_telemetry_matches_point_peer_through_lowered_classification() {
9720 // Absent classification.
9721 let eph = empty_ephemeral();
9722 let lowered: ProcessSpec = eph.clone().into();
9723 assert_eq!(
9724 eph.substrate_is_telemetry(),
9725 lowered.classification.substrate_is_telemetry(),
9726 "None-classification parity drift",
9727 );
9728 // Authored classification.
9729 for populated in SubstrateType::ALL {
9730 let mut classification = Classification::gate_compute();
9731 classification.substrate = populated;
9732 let mut eph = empty_ephemeral();
9733 eph.classification = Some(classification);
9734 let lowered: ProcessSpec = eph.clone().into();
9735 assert_eq!(
9736 eph.substrate_is_telemetry(),
9737 lowered.classification.substrate_is_telemetry(),
9738 "authored substrate={populated:?}: parity drift",
9739 );
9740 }
9741 }
9742
9743 /// MUTEX pin — [`Self::substrate_is_resource`] AND
9744 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
9745 /// for ANY [`EphemeralSpec`] (authored or defaulted). Second
9746 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
9747 /// peer of
9748 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9749 /// on a sibling closed-set projection.
9750 #[test]
9751 fn ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all() {
9752 // Absent classification.
9753 let eph = empty_ephemeral();
9754 assert!(
9755 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
9756 "None-classification: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
9757 );
9758 // Authored classification.
9759 for populated in SubstrateType::ALL {
9760 let mut classification = Classification::gate_compute();
9761 classification.substrate = populated;
9762 let mut eph = empty_ephemeral();
9763 eph.classification = Some(classification);
9764 assert!(
9765 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
9766 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
9767 );
9768 }
9769 }
9770
9771 /// MUTEX pin — [`Self::substrate_is_policy`] AND
9772 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
9773 /// for ANY [`EphemeralSpec`] (authored or defaulted). Third
9774 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
9775 /// completes the three pairwise MUTEX relations alongside
9776 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9777 /// and
9778 /// `ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all`.
9779 #[test]
9780 fn ephemeral_substrate_is_policy_and_substrate_is_telemetry_are_mutex_over_all() {
9781 // Absent classification.
9782 let eph = empty_ephemeral();
9783 assert!(
9784 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
9785 "None-classification: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
9786 );
9787 // Authored classification.
9788 for populated in SubstrateType::ALL {
9789 let mut classification = Classification::gate_compute();
9790 classification.substrate = populated;
9791 let mut eph = empty_ephemeral();
9792 eph.classification = Some(classification);
9793 assert!(
9794 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
9795 "authored substrate={populated:?}: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
9796 );
9797 }
9798 }
9799
9800 /// THREE-WAY XOR PARTITION pin — for the absent-classification
9801 /// baseline AND every [`crate::classification::SubstrateType::ALL`]
9802 /// variant, EXACTLY ONE of [`Self::substrate_is_resource`],
9803 /// [`Self::substrate_is_policy`], and
9804 /// [`Self::substrate_is_telemetry`] returns `true`. CLOSES the
9805 /// three pairwise MUTEX pins on the substrate axis
9806 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`,
9807 /// `substrate_is_resource ⇒ ¬substrate_is_telemetry`,
9808 /// `substrate_is_policy ⇒ ¬substrate_is_telemetry`) into the
9809 /// FULL ternary XOR partition contract on the ephemeral surface
9810 /// — the resolver-hop peer of the parent-composed
9811 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`
9812 /// test. Structural twin of the sibling `point_type`-axis
9813 /// ternary lift sealed on this surface by
9814 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
9815 /// Guarantees the absent-classification case lands in the
9816 /// resource bucket (`gate_compute` → Compute → is_resource =
9817 /// true), so every unadorned `(defephemeral …)` audits under a
9818 /// definite non-empty plane bucket.
9819 #[test]
9820 fn ephemeral_substrate_probes_form_three_way_xor_partition_over_all() {
9821 // Absent classification.
9822 let eph = empty_ephemeral();
9823 let buckets = [
9824 eph.substrate_is_resource(),
9825 eph.substrate_is_policy(),
9826 eph.substrate_is_telemetry(),
9827 ];
9828 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9829 assert_eq!(
9830 hits, 1,
9831 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9832 );
9833 // Authored classification.
9834 for populated in SubstrateType::ALL {
9835 let mut classification = Classification::gate_compute();
9836 classification.substrate = populated;
9837 let mut eph = empty_ephemeral();
9838 eph.classification = Some(classification);
9839 let buckets = [
9840 eph.substrate_is_resource(),
9841 eph.substrate_is_policy(),
9842 eph.substrate_is_telemetry(),
9843 ];
9844 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9845 assert_eq!(
9846 hits, 1,
9847 "authored substrate={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9848 );
9849 }
9850 }
9851
9852 // ── EphemeralSpec::calm_is_monotone pins ─────────────────────────
9853 //
9854 // Fail-before-pass-after granularity: `calm_is_monotone` did not
9855 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9856 // the "can this ephemeral spec participate in gossip-only writes?"
9857 // question went through the antisymmetric
9858 // `!self.calm_requires_coordination()` or through
9859 // `.resolved_classification().calm.is_monotone()`. Post-lift the
9860 // TWELFTH derived-nullary-boolean peer on the ephemeral surface
9861 // (SECOND on the calm axis, closing that axis into a binary XOR
9862 // partition on this surface) routes through the SAME
9863 // [`Self::resolved_classification`] resolver + the sibling
9864 // substrate primitive
9865 // [`crate::classification::Classification::calm_is_monotone`], so
9866 // the two-surface parity contract holds by construction, AND the
9867 // two calm-axis peers on this surface CLOSE the axis into the
9868 // FULL binary XOR partition contract via
9869 // `ephemeral_calm_probes_form_binary_xor_partition_over_all`.
9870
9871 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9872 /// [`Classification`] carries a specific
9873 /// [`crate::classification::CalmClassification`] variant answers
9874 /// [`Self::calm_is_monotone`] matching the closed set's own
9875 /// [`crate::classification::CalmClassification::is_monotone`]
9876 /// truth table. Sweep
9877 /// [`crate::classification::CalmClassification::ALL`] so a
9878 /// regression that (a) hard-coded the body to a fixed answer,
9879 /// (b) inverted the projection, or (c) crossed the wires with
9880 /// the sibling
9881 /// [`crate::classification::CalmClassification::requires_coordination`]
9882 /// projection fails HERE at the substrate primitive before
9883 /// drifting through the `monotone-calm` fixed tag or the peer
9884 /// point surface.
9885 #[test]
9886 fn calm_is_monotone_returns_calm_projection_per_kind() {
9887 for populated in CalmClassification::ALL {
9888 let mut classification = Classification::gate_compute();
9889 classification.calm = populated;
9890 let mut spec = empty_ephemeral();
9891 spec.classification = Some(classification);
9892 assert_eq!(
9893 spec.calm_is_monotone(),
9894 populated.is_monotone(),
9895 "authored calm={populated:?}: calm_is_monotone() drift",
9896 );
9897 }
9898 }
9899
9900 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9901 /// with `classification: None` routes through the
9902 /// [`Self::resolved_classification`] resolver's substrate default
9903 /// [`Classification::gate_compute`], which carries
9904 /// [`crate::classification::CalmClassification::default = Monotone`]
9905 /// via `#[default]`, and
9906 /// [`crate::classification::CalmClassification::Monotone::is_monotone`]
9907 /// projects `true`, so [`Self::calm_is_monotone`] returns
9908 /// `true`. Pins the resolver's default-arm short-circuit through
9909 /// TWO layers of `Default` ([`Classification::gate_compute`] →
9910 /// [`crate::classification::CalmClassification::default`])
9911 /// reaching this derived-nullary predicate. Mirror-inverted from
9912 /// the sibling
9913 /// `calm_requires_coordination_probes_false_on_absent_classification`
9914 /// (both walk the SAME defaulted `calm` field, so
9915 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
9916 /// closed set's disjoint XOR partition). Guarantees every
9917 /// unadorned `(defephemeral …)` reads as gossip-eligible under
9918 /// the positive CALM framing.
9919 #[test]
9920 fn calm_is_monotone_probes_true_on_absent_classification() {
9921 let spec = empty_ephemeral();
9922 assert!(spec.classification.is_none());
9923 assert!(
9924 spec.calm_is_monotone(),
9925 "absent classification (defaults to gate_compute, calm=Monotone → is_monotone=true)",
9926 );
9927 }
9928
9929 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9930 /// identically through [`Self::calm_is_monotone`] AND through
9931 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_is_monotone()`
9932 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9933 /// classification, `Some(_)` classification on every
9934 /// [`crate::classification::CalmClassification::ALL`] variant) so
9935 /// a future regression on either side of the resolver fails HERE
9936 /// at the parity boundary. Byte-for-byte peer of
9937 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
9938 /// on the SAME closed-set axis via the antisymmetric projection.
9939 #[test]
9940 fn calm_is_monotone_matches_point_peer_through_lowered_classification() {
9941 // Absent classification.
9942 let eph = empty_ephemeral();
9943 let lowered: ProcessSpec = eph.clone().into();
9944 assert_eq!(
9945 eph.calm_is_monotone(),
9946 lowered.classification.calm_is_monotone(),
9947 "None-classification parity drift",
9948 );
9949 // Authored classification.
9950 for populated in CalmClassification::ALL {
9951 let mut classification = Classification::gate_compute();
9952 classification.calm = populated;
9953 let mut eph = empty_ephemeral();
9954 eph.classification = Some(classification);
9955 let lowered: ProcessSpec = eph.clone().into();
9956 assert_eq!(
9957 eph.calm_is_monotone(),
9958 lowered.classification.calm_is_monotone(),
9959 "authored calm={populated:?}: parity drift",
9960 );
9961 }
9962 }
9963
9964 /// MUTEX pin — [`Self::calm_requires_coordination`] AND
9965 /// [`Self::calm_is_monotone`] are NEVER simultaneously true for
9966 /// ANY [`EphemeralSpec`] (authored or defaulted). FIRST
9967 /// ephemeral-surface `calm`-axis corner-peer MUTEX pin — the
9968 /// calm axis's counterpart to the sibling substrate-axis
9969 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9970 /// on a binary (rather than ternary) closed set.
9971 #[test]
9972 fn ephemeral_calm_requires_coordination_and_calm_is_monotone_are_mutex_over_all() {
9973 // Absent classification.
9974 let eph = empty_ephemeral();
9975 assert!(
9976 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
9977 "None-classification: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
9978 );
9979 // Authored classification.
9980 for populated in CalmClassification::ALL {
9981 let mut classification = Classification::gate_compute();
9982 classification.calm = populated;
9983 let mut eph = empty_ephemeral();
9984 eph.classification = Some(classification);
9985 assert!(
9986 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
9987 "authored calm={populated:?}: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
9988 );
9989 }
9990 }
9991
9992 /// BINARY XOR PARTITION pin — for the absent-classification
9993 /// baseline AND every
9994 /// [`crate::classification::CalmClassification::ALL`] variant,
9995 /// EXACTLY ONE of [`Self::calm_is_monotone`] and
9996 /// [`Self::calm_requires_coordination`] returns `true`. CLOSES
9997 /// the calm-axis MUTEX pin
9998 /// (`calm_requires_coordination ⇒ ¬calm_is_monotone`) into the
9999 /// FULL binary XOR partition contract on the ephemeral surface
10000 /// — the resolver-hop peer of the parent-composed
10001 /// `classification_calm_probes_form_binary_xor_partition_over_all`
10002 /// test. Binary counterpart of the ternary XOR partitions sealed
10003 /// on the sibling `point_type` and `substrate` axes by
10004 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10005 /// and
10006 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
10007 /// Guarantees the absent-classification case lands in the
10008 /// monotone bucket (`gate_compute` → CalmClassification::Monotone
10009 /// → is_monotone = true), so every unadorned `(defephemeral …)`
10010 /// audits under a definite non-empty CALM bucket.
10011 #[test]
10012 fn ephemeral_calm_probes_form_binary_xor_partition_over_all() {
10013 // Absent classification.
10014 let eph = empty_ephemeral();
10015 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
10016 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10017 assert_eq!(
10018 hits, 1,
10019 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10020 );
10021 // Authored classification.
10022 for populated in CalmClassification::ALL {
10023 let mut classification = Classification::gate_compute();
10024 classification.calm = populated;
10025 let mut eph = empty_ephemeral();
10026 eph.classification = Some(classification);
10027 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
10028 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10029 assert_eq!(
10030 hits, 1,
10031 "authored calm={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10032 );
10033 }
10034 }
10035
10036 // ── EphemeralSpec::data_is_public pins ───────────────────────────
10037 //
10038 // Fail-before-pass-after granularity: `data_is_public` did not
10039 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10040 // the "is this ephemeral spec's dataset publicly distributable?"
10041 // question went through the antisymmetric
10042 // `!self.data_is_restricted()` or through
10043 // `.resolved_classification().data_classification.is_public()`.
10044 // Post-lift the THIRTEENTH derived-nullary-boolean peer on the
10045 // ephemeral surface (THIRD on the data axis, closing that axis
10046 // into a binary XOR partition on this surface) routes through the
10047 // SAME [`Self::resolved_classification`] resolver + the sibling
10048 // substrate primitive
10049 // [`crate::classification::Classification::data_is_public`], so
10050 // the two-surface parity contract holds by construction, AND the
10051 // two-way public/restricted split on this surface CLOSES the
10052 // data axis into the FULL binary XOR partition contract via
10053 // `ephemeral_data_probes_form_binary_xor_partition_over_all`.
10054
10055 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10056 /// [`Classification`] carries a specific
10057 /// [`crate::classification::DataClassification`] variant answers
10058 /// [`Self::data_is_public`] matching the closed set's own
10059 /// [`crate::classification::DataClassification::is_public`] truth
10060 /// table. Sweep
10061 /// [`crate::classification::DataClassification::ALL`] so a
10062 /// regression that (a) hard-coded the body to a fixed answer,
10063 /// (b) inverted the projection, or (c) crossed the wires with
10064 /// the sibling
10065 /// [`crate::classification::DataClassification::is_restricted`]
10066 /// projection fails HERE at the substrate primitive before
10067 /// drifting through the `public-data` fixed tag or the peer
10068 /// point surface.
10069 #[test]
10070 fn data_is_public_returns_data_projection_per_kind() {
10071 for populated in DataClassification::ALL {
10072 let mut classification = Classification::gate_compute();
10073 classification.data_classification = populated;
10074 let mut spec = empty_ephemeral();
10075 spec.classification = Some(classification);
10076 assert_eq!(
10077 spec.data_is_public(),
10078 populated.is_public(),
10079 "authored data_classification={populated:?}: data_is_public() drift",
10080 );
10081 }
10082 }
10083
10084 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10085 /// with `classification: None` routes through the
10086 /// [`Self::resolved_classification`] resolver's substrate default
10087 /// [`Classification::gate_compute`], which carries
10088 /// [`crate::classification::DataClassification::default = Internal`]
10089 /// via `#[default]`, and
10090 /// [`crate::classification::DataClassification::Internal::is_public`]
10091 /// projects `false`, so [`Self::data_is_public`] returns `false`.
10092 /// Pins the resolver's default-arm short-circuit through TWO
10093 /// layers of `Default` ([`Classification::gate_compute`] →
10094 /// [`crate::classification::DataClassification::default`])
10095 /// reaching this derived-nullary predicate. Mirror-inverted from
10096 /// the sibling
10097 /// `data_is_restricted_probes_true_on_absent_classification`
10098 /// (both walk the SAME defaulted `data_classification` field, so
10099 /// `is_restricted = true` ⇒ `is_public = false` on the closed
10100 /// set's disjoint XOR partition). Guarantees every unadorned
10101 /// `(defephemeral …)` audits under the access-controlled default
10102 /// rather than silently promoting an unadorned dataset onto the
10103 /// freely-distributable path.
10104 #[test]
10105 fn data_is_public_probes_false_on_absent_classification() {
10106 let spec = empty_ephemeral();
10107 assert!(spec.classification.is_none());
10108 assert!(
10109 !spec.data_is_public(),
10110 "absent classification (defaults to gate_compute, data_classification=Internal → is_public=false)",
10111 );
10112 }
10113
10114 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10115 /// identically through [`Self::data_is_public`] AND through
10116 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_public()`
10117 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10118 /// classification, `Some(_)` classification on every
10119 /// [`crate::classification::DataClassification::ALL`] variant) so
10120 /// a future regression on either side of the resolver fails HERE
10121 /// at the parity boundary. Byte-for-byte peer of
10122 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
10123 /// on the SAME closed-set axis via the antisymmetric projection.
10124 #[test]
10125 fn data_is_public_matches_point_peer_through_lowered_classification() {
10126 // Absent classification.
10127 let eph = empty_ephemeral();
10128 let lowered: ProcessSpec = eph.clone().into();
10129 assert_eq!(
10130 eph.data_is_public(),
10131 lowered.classification.data_is_public(),
10132 "None-classification parity drift",
10133 );
10134 // Authored classification.
10135 for populated in DataClassification::ALL {
10136 let mut classification = Classification::gate_compute();
10137 classification.data_classification = populated;
10138 let mut eph = empty_ephemeral();
10139 eph.classification = Some(classification);
10140 let lowered: ProcessSpec = eph.clone().into();
10141 assert_eq!(
10142 eph.data_is_public(),
10143 lowered.classification.data_is_public(),
10144 "authored data_classification={populated:?}: parity drift",
10145 );
10146 }
10147 }
10148
10149 /// MUTEX pin — [`Self::data_is_regulated`] AND
10150 /// [`Self::data_is_public`] are NEVER simultaneously true for ANY
10151 /// [`EphemeralSpec`] (authored or defaulted). FIRST ephemeral-
10152 /// surface data-axis antisymmetric MUTEX pin against the
10153 /// positive-distribution framing: sealed on the closed set by
10154 /// `data_classification_regulated_implies_not_public` and lifted
10155 /// through the resolver hop as a substrate-wide contract on this
10156 /// surface.
10157 #[test]
10158 fn ephemeral_data_is_regulated_and_data_is_public_are_mutex_over_all() {
10159 // Absent classification.
10160 let eph = empty_ephemeral();
10161 assert!(
10162 !(eph.data_is_regulated() && eph.data_is_public()),
10163 "None-classification: data_is_regulated AND data_is_public both true (mutex violated)",
10164 );
10165 // Authored classification.
10166 for populated in DataClassification::ALL {
10167 let mut classification = Classification::gate_compute();
10168 classification.data_classification = populated;
10169 let mut eph = empty_ephemeral();
10170 eph.classification = Some(classification);
10171 assert!(
10172 !(eph.data_is_regulated() && eph.data_is_public()),
10173 "authored data_classification={populated:?}: data_is_regulated AND data_is_public both true (mutex violated)",
10174 );
10175 }
10176 }
10177
10178 /// BINARY XOR PARTITION pin — for the absent-classification
10179 /// baseline AND every
10180 /// [`crate::classification::DataClassification::ALL`] variant,
10181 /// EXACTLY ONE of [`Self::data_is_public`] and
10182 /// [`Self::data_is_restricted`] returns `true`. CLOSES the data-
10183 /// axis MUTEX pin (`data_is_regulated ⇒ ¬data_is_public`) into
10184 /// the FULL binary XOR partition contract on the ephemeral
10185 /// surface — the resolver-hop peer of the parent-composed
10186 /// `classification_data_probes_form_binary_xor_partition_over_all`
10187 /// test. Binary counterpart of the ternary XOR partitions sealed
10188 /// on the sibling `point_type` and `substrate` axes by
10189 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10190 /// and
10191 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
10192 /// Guarantees the absent-classification case lands in the
10193 /// access-controlled bucket (`gate_compute` →
10194 /// DataClassification::Internal → is_public = false,
10195 /// is_restricted = true), so every unadorned `(defephemeral …)`
10196 /// audits under a definite non-empty distribution bucket.
10197 #[test]
10198 fn ephemeral_data_probes_form_binary_xor_partition_over_all() {
10199 // Absent classification.
10200 let eph = empty_ephemeral();
10201 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
10202 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10203 assert_eq!(
10204 hits, 1,
10205 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10206 );
10207 // Authored classification.
10208 for populated in DataClassification::ALL {
10209 let mut classification = Classification::gate_compute();
10210 classification.data_classification = populated;
10211 let mut eph = empty_ephemeral();
10212 eph.classification = Some(classification);
10213 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
10214 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10215 assert_eq!(
10216 hits, 1,
10217 "authored data_classification={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10218 );
10219 }
10220 }
10221
10222 // ── EphemeralSpec::direction_prefers_lower pins ─────────────────
10223 //
10224 // Fail-before-pass-after granularity: `direction_prefers_lower`
10225 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10226 // walking the "does this ephemeral spec's rate-window evaluator
10227 // treat decreasing values as improvement?" question went through
10228 // `.resolved_classification().horizon.direction.unwrap_or_default().prefers_lower()`.
10229 // Post-lift the FOURTEENTH derived-nullary-boolean peer on the
10230 // ephemeral surface (FIRST on the optimization-direction axis,
10231 // opening the SIXTH classification axis into the fixed-tag algebra)
10232 // routes through the SAME [`Self::resolved_classification`] resolver
10233 // + the sibling substrate primitive
10234 // [`crate::classification::Classification::direction_prefers_lower`],
10235 // so the two-surface parity contract holds by construction.
10236
10237 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10238 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
10239 /// answers [`Self::direction_prefers_lower`] matching the closed
10240 /// set's own
10241 /// [`crate::classification::OptimizationDirection::prefers_lower`]
10242 /// truth table. Sweep
10243 /// [`crate::classification::OptimizationDirection::ALL`] so a
10244 /// regression that (a) hard-coded the body to a fixed answer,
10245 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
10246 /// hop, or (d) crossed the wires with a sibling classification-axis
10247 /// probe fails HERE at the substrate primitive before drifting
10248 /// through the `prefers-lower-direction` fixed tag or the peer
10249 /// point surface.
10250 #[test]
10251 fn direction_prefers_lower_returns_direction_projection_per_kind() {
10252 for populated in OptimizationDirection::ALL {
10253 let mut classification = Classification::gate_compute();
10254 classification.horizon.direction = Some(populated);
10255 let mut spec = empty_ephemeral();
10256 spec.classification = Some(classification);
10257 assert_eq!(
10258 spec.direction_prefers_lower(),
10259 populated.prefers_lower(),
10260 "authored horizon.direction={populated:?}: direction_prefers_lower() drift",
10261 );
10262 }
10263 }
10264
10265 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10266 /// with `classification: None` routes through the
10267 /// [`Self::resolved_classification`] resolver's substrate default
10268 /// [`Classification::gate_compute`], which carries
10269 /// `horizon: Horizon::default()` whose `direction` field is `None`,
10270 /// so `unwrap_or_default()` defaults to
10271 /// [`crate::classification::OptimizationDirection::Minimize`] via
10272 /// `#[default]`, and `Minimize.prefers_lower()` projects `true`,
10273 /// so [`Self::direction_prefers_lower`] returns `true`. Pins the
10274 /// resolver's default-arm short-circuit through THREE layers of
10275 /// `Default` ([`Classification::gate_compute`] →
10276 /// [`crate::classification::Horizon::default`] with `direction: None`
10277 /// → [`crate::classification::OptimizationDirection::default =
10278 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
10279 /// every unadorned `(defephemeral …)` reads under the lower-is-
10280 /// better polarity default (safe under the asymptotic-health
10281 /// rate-window evaluator convention: an operator must deliberately
10282 /// opt into Maximize polarity).
10283 #[test]
10284 fn direction_prefers_lower_probes_true_on_absent_classification() {
10285 let spec = empty_ephemeral();
10286 assert!(spec.classification.is_none());
10287 assert!(
10288 spec.direction_prefers_lower(),
10289 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_lower=true)",
10290 );
10291 }
10292
10293 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10294 /// identically through [`Self::direction_prefers_lower`] AND through
10295 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_lower()`
10296 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10297 /// classification, `Some(_)` classification on every
10298 /// [`crate::classification::OptimizationDirection::ALL`] variant) so
10299 /// a future regression on either side of the resolver fails HERE
10300 /// at the parity boundary. Byte-for-byte peer of
10301 /// `calm_is_monotone_matches_point_peer_through_lowered_classification`
10302 /// on the analog closed-set axis via the same resolver-hop shape.
10303 #[test]
10304 fn direction_prefers_lower_matches_point_peer_through_lowered_classification() {
10305 // Absent classification.
10306 let eph = empty_ephemeral();
10307 let lowered: ProcessSpec = eph.clone().into();
10308 assert_eq!(
10309 eph.direction_prefers_lower(),
10310 lowered.classification.direction_prefers_lower(),
10311 "None-classification parity drift",
10312 );
10313 // Authored classification.
10314 for populated in OptimizationDirection::ALL {
10315 let mut classification = Classification::gate_compute();
10316 classification.horizon.direction = Some(populated);
10317 let mut eph = empty_ephemeral();
10318 eph.classification = Some(classification);
10319 let lowered: ProcessSpec = eph.clone().into();
10320 assert_eq!(
10321 eph.direction_prefers_lower(),
10322 lowered.classification.direction_prefers_lower(),
10323 "authored horizon.direction={populated:?}: parity drift",
10324 );
10325 }
10326 }
10327
10328 // ── EphemeralSpec::direction_prefers_higher pins ────────────────
10329 //
10330 // Fail-before-pass-after granularity: `direction_prefers_higher`
10331 // did not exist pre-lift on `impl EphemeralSpec` — the positive
10332 // higher-is-better framing peer of
10333 // [`Self::direction_prefers_lower`] had no ephemeral-surface
10334 // substrate owner. Post-lift the FIFTEENTH derived-nullary-boolean
10335 // peer on the ephemeral surface (SECOND on the optimization-
10336 // direction axis, CLOSING the SIXTH classification axis into a
10337 // binary XOR partition on this surface) routes through the SAME
10338 // [`Self::resolved_classification`] resolver + the sibling
10339 // substrate primitive
10340 // [`crate::classification::Classification::direction_prefers_higher`],
10341 // so the two-surface parity contract holds by construction, AND
10342 // the two-way lower/higher split on this surface CLOSES the
10343 // optimization-direction axis into the FULL binary XOR partition
10344 // contract via
10345 // `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
10346
10347 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10348 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
10349 /// answers [`Self::direction_prefers_higher`] matching the closed
10350 /// set's own
10351 /// [`crate::classification::OptimizationDirection::prefers_higher`]
10352 /// truth table. Sweep
10353 /// [`crate::classification::OptimizationDirection::ALL`] so a
10354 /// regression that (a) hard-coded the body to a fixed answer,
10355 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
10356 /// hop, or (d) crossed the wires with a sibling classification-
10357 /// axis probe fails HERE at the substrate primitive before
10358 /// drifting through the `prefers-higher-direction` fixed tag or
10359 /// the peer point surface.
10360 #[test]
10361 fn direction_prefers_higher_returns_direction_projection_per_kind() {
10362 for populated in OptimizationDirection::ALL {
10363 let mut classification = Classification::gate_compute();
10364 classification.horizon.direction = Some(populated);
10365 let mut spec = empty_ephemeral();
10366 spec.classification = Some(classification);
10367 assert_eq!(
10368 spec.direction_prefers_higher(),
10369 populated.prefers_higher(),
10370 "authored horizon.direction={populated:?}: direction_prefers_higher() drift",
10371 );
10372 }
10373 }
10374
10375 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10376 /// with `classification: None` routes through the
10377 /// [`Self::resolved_classification`] resolver's substrate default
10378 /// [`Classification::gate_compute`], which carries
10379 /// `horizon: Horizon::default()` whose `direction` field is `None`,
10380 /// so `unwrap_or_default()` defaults to
10381 /// [`crate::classification::OptimizationDirection::Minimize`] via
10382 /// `#[default]`, and `Minimize.prefers_higher()` projects `false`,
10383 /// so [`Self::direction_prefers_higher`] returns `false`. Pins
10384 /// the resolver's default-arm short-circuit through THREE layers
10385 /// of `Default` ([`Classification::gate_compute`] →
10386 /// [`crate::classification::Horizon::default`] with `direction:
10387 /// None` → [`crate::classification::OptimizationDirection::default =
10388 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
10389 /// every unadorned `(defephemeral …)` reads UNDER the lower-is-
10390 /// better polarity default (safe under the asymptotic-health
10391 /// rate-window evaluator convention: an operator must
10392 /// deliberately opt into Maximize polarity). Mirror-inverted from
10393 /// the sibling `direction_prefers_lower_probes_true_on_absent_classification`
10394 /// baseline on the same resolver walk.
10395 #[test]
10396 fn direction_prefers_higher_probes_false_on_absent_classification() {
10397 let spec = empty_ephemeral();
10398 assert!(spec.classification.is_none());
10399 assert!(
10400 !spec.direction_prefers_higher(),
10401 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_higher=false)",
10402 );
10403 }
10404
10405 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10406 /// identically through [`Self::direction_prefers_higher`] AND
10407 /// through
10408 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_higher()`
10409 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10410 /// classification, `Some(_)` classification on every
10411 /// [`crate::classification::OptimizationDirection::ALL`] variant)
10412 /// so a future regression on either side of the resolver fails
10413 /// HERE at the parity boundary. Byte-for-byte peer of
10414 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
10415 /// on the antisymmetric closed-set arm via the same resolver-hop
10416 /// shape.
10417 #[test]
10418 fn direction_prefers_higher_matches_point_peer_through_lowered_classification() {
10419 // Absent classification.
10420 let eph = empty_ephemeral();
10421 let lowered: ProcessSpec = eph.clone().into();
10422 assert_eq!(
10423 eph.direction_prefers_higher(),
10424 lowered.classification.direction_prefers_higher(),
10425 "None-classification parity drift",
10426 );
10427 // Authored classification.
10428 for populated in OptimizationDirection::ALL {
10429 let mut classification = Classification::gate_compute();
10430 classification.horizon.direction = Some(populated);
10431 let mut eph = empty_ephemeral();
10432 eph.classification = Some(classification);
10433 let lowered: ProcessSpec = eph.clone().into();
10434 assert_eq!(
10435 eph.direction_prefers_higher(),
10436 lowered.classification.direction_prefers_higher(),
10437 "authored horizon.direction={populated:?}: parity drift",
10438 );
10439 }
10440 }
10441
10442 /// BINARY XOR PARTITION pin — for the absent-classification
10443 /// baseline AND every
10444 /// [`crate::classification::OptimizationDirection::ALL`] variant,
10445 /// EXACTLY ONE of [`Self::direction_prefers_lower`] and
10446 /// [`Self::direction_prefers_higher`] returns `true`. CLOSES the
10447 /// optimization-direction axis into the FULL binary XOR partition
10448 /// contract on the ephemeral surface — the resolver-hop peer of
10449 /// the parent-composed
10450 /// `classification_direction_probes_form_binary_xor_partition_over_all`
10451 /// test. Binary counterpart of the ternary XOR partitions sealed
10452 /// on the sibling `point_type` and `substrate` axes by
10453 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10454 /// and
10455 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10456 /// structural twin of the calm/data binary partitions
10457 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all` and
10458 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
10459 /// This pin is the SIXTH (and final) classification axis to reach
10460 /// the closed XOR partition landmark on the ephemeral resolver-
10461 /// hop surface — ALL SIX classification axes (horizon, calm,
10462 /// data, point, substrate, optimization-direction) now have
10463 /// their partitions closed on the ephemeral surface at this
10464 /// corner. Guarantees the absent-classification case lands in
10465 /// the definite lower-is-better bucket (`gate_compute` →
10466 /// Horizon::default → direction: None →
10467 /// OptimizationDirection::default = Minimize → prefers_lower =
10468 /// true, prefers_higher = false), so every unadorned
10469 /// `(defephemeral …)` audits under a definite non-empty polarity
10470 /// bucket.
10471 #[test]
10472 fn ephemeral_direction_probes_form_binary_xor_partition_over_all() {
10473 // Absent classification.
10474 let eph = empty_ephemeral();
10475 let buckets = [
10476 eph.direction_prefers_lower(),
10477 eph.direction_prefers_higher(),
10478 ];
10479 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10480 assert_eq!(
10481 hits, 1,
10482 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10483 );
10484 // Authored classification.
10485 for populated in OptimizationDirection::ALL {
10486 let mut classification = Classification::gate_compute();
10487 classification.horizon.direction = Some(populated);
10488 let mut eph = empty_ephemeral();
10489 eph.classification = Some(classification);
10490 let buckets = [
10491 eph.direction_prefers_lower(),
10492 eph.direction_prefers_higher(),
10493 ];
10494 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10495 assert_eq!(
10496 hits, 1,
10497 "authored horizon.direction={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10498 );
10499 }
10500 }
10501
10502 // ── EphemeralSpec::input_arity_is_one pins ──────────────────────
10503 //
10504 // Fail-before-pass-after granularity: `input_arity_is_one` did not
10505 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10506 // the "does this ephemeral spec's DAG-composition input port
10507 // accept a single upstream edge?" question went through
10508 // `.resolved_classification().point_type.input_arity().is_one()`.
10509 // Post-lift the SIXTEENTH derived-nullary-boolean peer on the
10510 // ephemeral surface (FIRST on the input-arity axis, opening the
10511 // SEVENTH classification axis into the fixed-tag algebra + the
10512 // derived-typed-projection stratum on this surface for the first
10513 // time) routes through the SAME [`Self::resolved_classification`]
10514 // resolver + the sibling substrate primitive
10515 // [`crate::classification::Classification::input_arity_is_one`],
10516 // so the two-surface parity contract holds by construction.
10517
10518 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10519 /// [`Classification`] carries `point_type: kind` answers
10520 /// [`Self::input_arity_is_one`] matching the closed set's own
10521 /// [`crate::classification::ConvergencePointType::input_arity`]
10522 /// truth table projected through [`Arity::is_one`]. Sweep
10523 /// [`crate::classification::ConvergencePointType::ALL`] so a
10524 /// regression that (a) hard-coded the body to a fixed answer,
10525 /// (b) inverted the projection, (c) dropped the resolver hop, or
10526 /// (d) crossed the wires with the sibling `output_arity`
10527 /// projection (which disagrees on six of eight variants) fails
10528 /// HERE at the substrate primitive before drifting through the
10529 /// future `single-input-arity` fixed tag or the peer point
10530 /// surface.
10531 #[test]
10532 fn input_arity_is_one_returns_input_arity_projection_per_kind() {
10533 for populated in ConvergencePointType::ALL {
10534 let mut classification = Classification::gate_compute();
10535 classification.point_type = populated;
10536 let mut spec = empty_ephemeral();
10537 spec.classification = Some(classification);
10538 assert_eq!(
10539 spec.input_arity_is_one(),
10540 populated.input_arity().is_one(),
10541 "authored point_type={populated:?}: input_arity_is_one() drift",
10542 );
10543 }
10544 }
10545
10546 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10547 /// with `classification: None` routes through the
10548 /// [`Self::resolved_classification`] resolver's substrate default
10549 /// [`Classification::gate_compute`], which carries `point_type:
10550 /// Gate` and `Gate.input_arity() = Many`, so
10551 /// [`Self::input_arity_is_one`] returns `false`. Pins the
10552 /// resolver's default-arm short-circuit reaching this derived-
10553 /// nullary predicate — every unadorned `(defephemeral …)` lands
10554 /// in the multi-input bucket under the substrate default. Mirror-
10555 /// inverted from the sibling `input_arity_is_many` baseline on
10556 /// the same resolver walk (the XOR partition forces exactly one
10557 /// bucket per baseline).
10558 #[test]
10559 fn input_arity_is_one_probes_false_on_absent_classification() {
10560 let spec = empty_ephemeral();
10561 assert!(spec.classification.is_none());
10562 assert!(
10563 !spec.input_arity_is_one(),
10564 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_one=false)",
10565 );
10566 }
10567
10568 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10569 /// identically through [`Self::input_arity_is_one`] AND through
10570 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_one()`
10571 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10572 /// classification, `Some(_)` classification on every
10573 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10574 /// so a future regression on either side of the resolver fails
10575 /// HERE at the parity boundary. Byte-for-byte peer of
10576 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
10577 /// on the same resolver-hop shape.
10578 #[test]
10579 fn input_arity_is_one_matches_point_peer_through_lowered_classification() {
10580 // Absent classification.
10581 let eph = empty_ephemeral();
10582 let lowered: ProcessSpec = eph.clone().into();
10583 assert_eq!(
10584 eph.input_arity_is_one(),
10585 lowered.classification.input_arity_is_one(),
10586 "None-classification parity drift",
10587 );
10588 // Authored classification.
10589 for populated in ConvergencePointType::ALL {
10590 let mut classification = Classification::gate_compute();
10591 classification.point_type = populated;
10592 let mut eph = empty_ephemeral();
10593 eph.classification = Some(classification);
10594 let lowered: ProcessSpec = eph.clone().into();
10595 assert_eq!(
10596 eph.input_arity_is_one(),
10597 lowered.classification.input_arity_is_one(),
10598 "authored point_type={populated:?}: parity drift",
10599 );
10600 }
10601 }
10602
10603 // ── EphemeralSpec::input_arity_is_many pins ─────────────────────
10604 //
10605 // Fail-before-pass-after granularity: `input_arity_is_many` did
10606 // not exist pre-lift on `impl EphemeralSpec` — the multi-input
10607 // framing peer of [`Self::input_arity_is_one`] had no ephemeral-
10608 // surface substrate owner. Post-lift the SEVENTEENTH derived-
10609 // nullary-boolean peer on the ephemeral surface (SECOND on the
10610 // input-arity axis, CLOSING the SEVENTH classification axis into
10611 // a binary XOR partition on this surface) routes through the SAME
10612 // [`Self::resolved_classification`] resolver + the sibling
10613 // substrate primitive
10614 // [`crate::classification::Classification::input_arity_is_many`],
10615 // so the two-surface parity contract holds by construction, AND
10616 // the two-way single/many split on this surface CLOSES the
10617 // input-arity axis into the FULL binary XOR partition contract
10618 // via `ephemeral_input_arity_probes_form_binary_xor_partition_over_all`.
10619
10620 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10621 /// [`Classification`] carries `point_type: kind` answers
10622 /// [`Self::input_arity_is_many`] matching the closed set's own
10623 /// [`crate::classification::ConvergencePointType::input_arity`]
10624 /// truth table projected through [`Arity::is_many`]. Sweep
10625 /// [`crate::classification::ConvergencePointType::ALL`] so a
10626 /// regression that (a) hard-coded the body to a fixed answer,
10627 /// (b) inverted the projection, (c) dropped the resolver hop, or
10628 /// (d) crossed the wires with the sibling `output_arity`
10629 /// projection fails HERE at the substrate primitive before
10630 /// drifting through the future `multi-input-arity` fixed tag or
10631 /// the peer point surface.
10632 #[test]
10633 fn input_arity_is_many_returns_input_arity_projection_per_kind() {
10634 for populated in ConvergencePointType::ALL {
10635 let mut classification = Classification::gate_compute();
10636 classification.point_type = populated;
10637 let mut spec = empty_ephemeral();
10638 spec.classification = Some(classification);
10639 assert_eq!(
10640 spec.input_arity_is_many(),
10641 populated.input_arity().is_many(),
10642 "authored point_type={populated:?}: input_arity_is_many() drift",
10643 );
10644 }
10645 }
10646
10647 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10648 /// with `classification: None` routes through the
10649 /// [`Self::resolved_classification`] resolver's substrate default
10650 /// [`Classification::gate_compute`], which carries `point_type:
10651 /// Gate` and `Gate.input_arity() = Many`, so
10652 /// [`Self::input_arity_is_many`] returns `true`. Pins the
10653 /// resolver's default-arm short-circuit reaching this derived-
10654 /// nullary predicate — every unadorned `(defephemeral …)` lands
10655 /// in the multi-input bucket under the substrate default. Mirror-
10656 /// inverted from the sibling `input_arity_is_one` baseline on
10657 /// the same resolver walk (the XOR partition forces exactly one
10658 /// bucket per baseline).
10659 #[test]
10660 fn input_arity_is_many_probes_true_on_absent_classification() {
10661 let spec = empty_ephemeral();
10662 assert!(spec.classification.is_none());
10663 assert!(
10664 spec.input_arity_is_many(),
10665 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_many=true)",
10666 );
10667 }
10668
10669 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10670 /// identically through [`Self::input_arity_is_many`] AND through
10671 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_many()`
10672 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10673 /// classification, `Some(_)` classification on every
10674 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10675 /// so a future regression on either side of the resolver fails
10676 /// HERE at the parity boundary. Byte-for-byte peer of
10677 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
10678 /// on the antisymmetric closed-set arm via the same resolver-hop
10679 /// shape.
10680 #[test]
10681 fn input_arity_is_many_matches_point_peer_through_lowered_classification() {
10682 // Absent classification.
10683 let eph = empty_ephemeral();
10684 let lowered: ProcessSpec = eph.clone().into();
10685 assert_eq!(
10686 eph.input_arity_is_many(),
10687 lowered.classification.input_arity_is_many(),
10688 "None-classification parity drift",
10689 );
10690 // Authored classification.
10691 for populated in ConvergencePointType::ALL {
10692 let mut classification = Classification::gate_compute();
10693 classification.point_type = populated;
10694 let mut eph = empty_ephemeral();
10695 eph.classification = Some(classification);
10696 let lowered: ProcessSpec = eph.clone().into();
10697 assert_eq!(
10698 eph.input_arity_is_many(),
10699 lowered.classification.input_arity_is_many(),
10700 "authored point_type={populated:?}: parity drift",
10701 );
10702 }
10703 }
10704
10705 /// BINARY XOR PARTITION pin — for the absent-classification
10706 /// baseline AND every
10707 /// [`crate::classification::ConvergencePointType::ALL`] variant,
10708 /// EXACTLY ONE of [`Self::input_arity_is_one`] and
10709 /// [`Self::input_arity_is_many`] returns `true`. CLOSES the
10710 /// input-arity axis into the FULL binary XOR partition contract
10711 /// on the ephemeral surface — the resolver-hop peer of the
10712 /// parent-composed
10713 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`
10714 /// test. Binary counterpart of the ternary XOR partitions sealed
10715 /// on the sibling `point_type` and `substrate` axes by
10716 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10717 /// and
10718 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10719 /// structural twin of the calm/data/direction binary partitions
10720 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
10721 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`,
10722 /// and
10723 /// `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
10724 /// This pin is the SEVENTH classification axis to reach the
10725 /// closed XOR partition landmark on the ephemeral resolver-hop
10726 /// surface — the FIRST closed axis on the derived-typed-
10727 /// projection stratum of this surface, opening the stratum beyond
10728 /// the six stored classification slots. Guarantees the absent-
10729 /// classification case lands in the definite multi-input bucket
10730 /// (`gate_compute` → point_type=Gate → input_arity=Many →
10731 /// is_one=false, is_many=true), so every unadorned
10732 /// `(defephemeral …)` audits under a definite non-empty input-
10733 /// arity bucket.
10734 #[test]
10735 fn ephemeral_input_arity_probes_form_binary_xor_partition_over_all() {
10736 // Absent classification.
10737 let eph = empty_ephemeral();
10738 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
10739 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10740 assert_eq!(
10741 hits, 1,
10742 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10743 );
10744 // Authored classification.
10745 for populated in ConvergencePointType::ALL {
10746 let mut classification = Classification::gate_compute();
10747 classification.point_type = populated;
10748 let mut eph = empty_ephemeral();
10749 eph.classification = Some(classification);
10750 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
10751 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10752 assert_eq!(
10753 hits, 1,
10754 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10755 );
10756 }
10757 }
10758
10759 // ── EphemeralSpec::output_arity_is_one pins ─────────────────────
10760 //
10761 // Fail-before-pass-after granularity: `output_arity_is_one` did not
10762 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10763 // the "does this ephemeral spec's DAG-composition output port emit
10764 // to a single downstream edge?" question went through
10765 // `.resolved_classification().point_type.output_arity().is_one()`.
10766 // Post-lift the EIGHTEENTH derived-nullary-boolean peer on the
10767 // ephemeral surface (FIRST on the output-arity axis, opening the
10768 // EIGHTH classification axis into the fixed-tag algebra + the
10769 // SECOND peer on the derived-typed-projection stratum after
10770 // [`Self::input_arity_is_one`]) routes through the SAME
10771 // [`Self::resolved_classification`] resolver + the sibling
10772 // substrate primitive
10773 // [`crate::classification::Classification::output_arity_is_one`],
10774 // so the two-surface parity contract holds by construction.
10775
10776 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10777 /// [`Classification`] carries `point_type: kind` answers
10778 /// [`Self::output_arity_is_one`] matching the closed set's own
10779 /// [`crate::classification::ConvergencePointType::output_arity`]
10780 /// truth table projected through [`Arity::is_one`]. Sweep
10781 /// [`crate::classification::ConvergencePointType::ALL`] so a
10782 /// regression that (a) hard-coded the body to a fixed answer,
10783 /// (b) inverted the projection, (c) dropped the resolver hop, or
10784 /// (d) crossed the wires with the sibling `input_arity`
10785 /// projection (which disagrees on six of eight variants) fails
10786 /// HERE at the substrate primitive before drifting through the
10787 /// future `single-output-arity` fixed tag or the peer point
10788 /// surface.
10789 #[test]
10790 fn output_arity_is_one_returns_output_arity_projection_per_kind() {
10791 for populated in ConvergencePointType::ALL {
10792 let mut classification = Classification::gate_compute();
10793 classification.point_type = populated;
10794 let mut spec = empty_ephemeral();
10795 spec.classification = Some(classification);
10796 assert_eq!(
10797 spec.output_arity_is_one(),
10798 populated.output_arity().is_one(),
10799 "authored point_type={populated:?}: output_arity_is_one() drift",
10800 );
10801 }
10802 }
10803
10804 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10805 /// with `classification: None` routes through the
10806 /// [`Self::resolved_classification`] resolver's substrate default
10807 /// [`Classification::gate_compute`], which carries `point_type:
10808 /// Gate` and `Gate.output_arity() = One`, so
10809 /// [`Self::output_arity_is_one`] returns `true`. Pins the
10810 /// resolver's default-arm short-circuit reaching this derived-
10811 /// nullary predicate — every unadorned `(defephemeral …)` lands
10812 /// in the single-output bucket under the substrate default.
10813 /// Mirror-inverted from the sibling `output_arity_is_many`
10814 /// baseline on the same resolver walk (the XOR partition forces
10815 /// exactly one bucket per baseline). Note the workspace-baseline
10816 /// answer FLIPS between the input-arity and output-arity axes on
10817 /// the exact same absent-classification baseline: the input-arity
10818 /// sibling `input_arity_is_one` answers `false`, but this
10819 /// output-arity peer answers `true` — direct evidence at the
10820 /// resolver-hop layer that the two axes carve the closed set
10821 /// into structurally different partitions.
10822 #[test]
10823 fn output_arity_is_one_probes_true_on_absent_classification() {
10824 let spec = empty_ephemeral();
10825 assert!(spec.classification.is_none());
10826 assert!(
10827 spec.output_arity_is_one(),
10828 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_one=true)",
10829 );
10830 }
10831
10832 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10833 /// identically through [`Self::output_arity_is_one`] AND through
10834 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_one()`
10835 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10836 /// classification, `Some(_)` classification on every
10837 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10838 /// so a future regression on either side of the resolver fails
10839 /// HERE at the parity boundary. Byte-for-byte peer of
10840 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
10841 /// on the sibling output-arity projection via the same
10842 /// resolver-hop shape.
10843 #[test]
10844 fn output_arity_is_one_matches_point_peer_through_lowered_classification() {
10845 // Absent classification.
10846 let eph = empty_ephemeral();
10847 let lowered: ProcessSpec = eph.clone().into();
10848 assert_eq!(
10849 eph.output_arity_is_one(),
10850 lowered.classification.output_arity_is_one(),
10851 "None-classification parity drift",
10852 );
10853 // Authored classification.
10854 for populated in ConvergencePointType::ALL {
10855 let mut classification = Classification::gate_compute();
10856 classification.point_type = populated;
10857 let mut eph = empty_ephemeral();
10858 eph.classification = Some(classification);
10859 let lowered: ProcessSpec = eph.clone().into();
10860 assert_eq!(
10861 eph.output_arity_is_one(),
10862 lowered.classification.output_arity_is_one(),
10863 "authored point_type={populated:?}: parity drift",
10864 );
10865 }
10866 }
10867
10868 // ── EphemeralSpec::output_arity_is_many pins ────────────────────
10869 //
10870 // Fail-before-pass-after granularity: `output_arity_is_many` did
10871 // not exist pre-lift on `impl EphemeralSpec` — the multi-output
10872 // framing peer of [`Self::output_arity_is_one`] had no ephemeral-
10873 // surface substrate owner. Post-lift the NINETEENTH derived-
10874 // nullary-boolean peer on the ephemeral surface (SECOND on the
10875 // output-arity axis, CLOSING the EIGHTH classification axis into
10876 // a binary XOR partition on this surface) routes through the SAME
10877 // [`Self::resolved_classification`] resolver + the sibling
10878 // substrate primitive
10879 // [`crate::classification::Classification::output_arity_is_many`],
10880 // so the two-surface parity contract holds by construction, AND
10881 // the two-way single/many split on this surface CLOSES the
10882 // output-arity axis into the FULL binary XOR partition contract
10883 // via `ephemeral_output_arity_probes_form_binary_xor_partition_over_all`,
10884 // completing the DAG-composition arity PAIR on the ephemeral
10885 // derived-typed-projection stratum.
10886
10887 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10888 /// [`Classification`] carries `point_type: kind` answers
10889 /// [`Self::output_arity_is_many`] matching the closed set's own
10890 /// [`crate::classification::ConvergencePointType::output_arity`]
10891 /// truth table projected through [`Arity::is_many`]. Sweep
10892 /// [`crate::classification::ConvergencePointType::ALL`] so a
10893 /// regression that (a) hard-coded the body to a fixed answer,
10894 /// (b) inverted the projection, (c) dropped the resolver hop, or
10895 /// (d) crossed the wires with the sibling `input_arity`
10896 /// projection fails HERE at the substrate primitive before
10897 /// drifting through the future `multi-output-arity` fixed tag or
10898 /// the peer point surface.
10899 #[test]
10900 fn output_arity_is_many_returns_output_arity_projection_per_kind() {
10901 for populated in ConvergencePointType::ALL {
10902 let mut classification = Classification::gate_compute();
10903 classification.point_type = populated;
10904 let mut spec = empty_ephemeral();
10905 spec.classification = Some(classification);
10906 assert_eq!(
10907 spec.output_arity_is_many(),
10908 populated.output_arity().is_many(),
10909 "authored point_type={populated:?}: output_arity_is_many() drift",
10910 );
10911 }
10912 }
10913
10914 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10915 /// with `classification: None` routes through the
10916 /// [`Self::resolved_classification`] resolver's substrate default
10917 /// [`Classification::gate_compute`], which carries `point_type:
10918 /// Gate` and `Gate.output_arity() = One`, so
10919 /// [`Self::output_arity_is_many`] returns `false`. Pins the
10920 /// resolver's default-arm short-circuit reaching this derived-
10921 /// nullary predicate — every unadorned `(defephemeral …)` lands
10922 /// in the single-output bucket under the substrate default.
10923 /// Mirror-inverted from the sibling `output_arity_is_one`
10924 /// baseline on the same resolver walk (the XOR partition forces
10925 /// exactly one bucket per baseline).
10926 #[test]
10927 fn output_arity_is_many_probes_false_on_absent_classification() {
10928 let spec = empty_ephemeral();
10929 assert!(spec.classification.is_none());
10930 assert!(
10931 !spec.output_arity_is_many(),
10932 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_many=false)",
10933 );
10934 }
10935
10936 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10937 /// identically through [`Self::output_arity_is_many`] AND through
10938 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_many()`
10939 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10940 /// classification, `Some(_)` classification on every
10941 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10942 /// so a future regression on either side of the resolver fails
10943 /// HERE at the parity boundary. Byte-for-byte peer of
10944 /// `output_arity_is_one_matches_point_peer_through_lowered_classification`
10945 /// on the antisymmetric closed-set arm via the same resolver-hop
10946 /// shape.
10947 #[test]
10948 fn output_arity_is_many_matches_point_peer_through_lowered_classification() {
10949 // Absent classification.
10950 let eph = empty_ephemeral();
10951 let lowered: ProcessSpec = eph.clone().into();
10952 assert_eq!(
10953 eph.output_arity_is_many(),
10954 lowered.classification.output_arity_is_many(),
10955 "None-classification parity drift",
10956 );
10957 // Authored classification.
10958 for populated in ConvergencePointType::ALL {
10959 let mut classification = Classification::gate_compute();
10960 classification.point_type = populated;
10961 let mut eph = empty_ephemeral();
10962 eph.classification = Some(classification);
10963 let lowered: ProcessSpec = eph.clone().into();
10964 assert_eq!(
10965 eph.output_arity_is_many(),
10966 lowered.classification.output_arity_is_many(),
10967 "authored point_type={populated:?}: parity drift",
10968 );
10969 }
10970 }
10971
10972 /// BINARY XOR PARTITION pin — for the absent-classification
10973 /// baseline AND every
10974 /// [`crate::classification::ConvergencePointType::ALL`] variant,
10975 /// EXACTLY ONE of [`Self::output_arity_is_one`] and
10976 /// [`Self::output_arity_is_many`] returns `true`. CLOSES the
10977 /// output-arity axis into the FULL binary XOR partition contract
10978 /// on the ephemeral surface — the resolver-hop peer of the
10979 /// parent-composed
10980 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`
10981 /// test. Binary counterpart of the ternary XOR partitions sealed
10982 /// on the sibling `point_type` and `substrate` axes by
10983 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10984 /// and
10985 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10986 /// structural twin of the calm/data/direction/input-arity binary
10987 /// partitions on this surface. This pin is the EIGHTH
10988 /// classification axis to reach the closed XOR partition landmark
10989 /// on the ephemeral resolver-hop surface — the SECOND closed axis
10990 /// on the derived-typed-projection stratum of this surface,
10991 /// completing the DAG-composition arity PAIR on the ephemeral
10992 /// stratum after the input-arity closure. Guarantees the absent-
10993 /// classification case lands in the definite single-output bucket
10994 /// (`gate_compute` → point_type=Gate → output_arity=One →
10995 /// is_one=true, is_many=false), so every unadorned
10996 /// `(defephemeral …)` audits under a definite non-empty
10997 /// output-arity bucket.
10998 #[test]
10999 fn ephemeral_output_arity_probes_form_binary_xor_partition_over_all() {
11000 // Absent classification.
11001 let eph = empty_ephemeral();
11002 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
11003 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11004 assert_eq!(
11005 hits, 1,
11006 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11007 );
11008 // Authored classification.
11009 for populated in ConvergencePointType::ALL {
11010 let mut classification = Classification::gate_compute();
11011 classification.point_type = populated;
11012 let mut eph = empty_ephemeral();
11013 eph.classification = Some(classification);
11014 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
11015 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11016 assert_eq!(
11017 hits, 1,
11018 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11019 );
11020 }
11021 }
11022
11023 /// BINARY XOR PARTITION pin — for the absent-classification
11024 /// baseline AND every
11025 /// [`crate::classification::HorizonKind::ALL`] variant, EXACTLY
11026 /// ONE of [`Self::horizon_terminates`] and
11027 /// [`Self::horizon_requires_metric_axes`] returns `true`. CLOSES
11028 /// the horizon axis into the FULL binary XOR partition contract
11029 /// on the ephemeral surface — the resolver-hop peer of the
11030 /// parent-composed
11031 /// `classification_horizon_probes_form_binary_xor_partition_over_all`
11032 /// test. Binary counterpart of the ternary XOR partitions sealed
11033 /// on the sibling `point_type` and `substrate` axes by
11034 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11035 /// and
11036 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11037 /// structural twin of the calm/data binary partitions
11038 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`
11039 /// and
11040 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11041 /// This pin is the FIFTH (and final) classification axis to reach
11042 /// the closed XOR partition landmark on the ephemeral resolver-
11043 /// hop surface, sealing every classification axis under the
11044 /// SAME `hits == 1` bucket-array contract. Guarantees the absent-
11045 /// classification case lands in the definite terminating bucket
11046 /// (`gate_compute` → HorizonKind::Bounded → terminates = true,
11047 /// requires_metric_axes = false), so every unadorned
11048 /// `(defephemeral …)` audits under a definite non-empty horizon
11049 /// bucket. Rewritten from the earlier binary-XOR-only form
11050 /// (walked as `a ^ b`) into the canonical bucket-array shape
11051 /// shared with the calm/data partitions.
11052 #[test]
11053 fn ephemeral_horizon_probes_form_binary_xor_partition_over_all() {
11054 // Absent classification.
11055 let eph = empty_ephemeral();
11056 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
11057 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11058 assert_eq!(
11059 hits, 1,
11060 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11061 );
11062 // Authored classification.
11063 for populated in HorizonKind::ALL {
11064 let classification = Classification::gate_compute_with_axis(populated);
11065 let mut eph = empty_ephemeral();
11066 eph.classification = Some(classification);
11067 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
11068 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11069 assert_eq!(
11070 hits, 1,
11071 "authored horizon.kind={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11072 );
11073 }
11074 }
11075
11076 // ── EphemeralSpec::has_routing_form pins ─────────────────────────
11077 //
11078 // Fail-before-pass-after granularity: `has_routing_form` did not
11079 // exist pre-lift on `impl EphemeralSpec` — the point-surface
11080 // `routing-form-<kind>` prefix family in tatara-check routed
11081 // through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`
11082 // inline, so the ephemeral surface had no matching primitive to
11083 // publish the SAME `routing-form-<kind>` prefix family through
11084 // the `strip_and_classify_prefixed_kind` substrate. Post-lift the
11085 // Option-gated derived-scalar-child probe body lives at ONE
11086 // inherent site on [`EphemeralSpec`] and every consumer (this
11087 // module's peer-symmetry tests, tatara-check's ephemeral
11088 // require-tag classifier, any future audit dispatcher walking
11089 // [`RoutingForm::ALL`] over the ephemeral surface) binds through
11090 // the SAME `has_routing_form(kind)` shape.
11091
11092 fn routing_spec(is_stable: bool) -> RoutingSpec {
11093 use crate::routing::{RoutingBackend, RoutingHostname};
11094 RoutingSpec {
11095 hostnames: vec![RoutingHostname::content_hashed("api")],
11096 backend: RoutingBackend::plain("svc", 80),
11097 stable_name_claim: is_stable,
11098 priority: 0,
11099 }
11100 }
11101
11102 /// POPULATED-slot pin — a populated `routing` slot answers `true`
11103 /// exactly for the [`RoutingForm`] variant its
11104 /// [`RoutingSpec::has_form`] derived-scalar arm agrees with, and
11105 /// `false` for every other variant. Sweep the two-boolean × ALL
11106 /// cross so a regression that (a) hard-coded the arm to a single
11107 /// variant, (b) dropped the Option-parent gate (silently reading
11108 /// through `.unwrap_or_default()` on an absent routing slot), or
11109 /// (c) crossed the wires from
11110 /// [`RoutingForm::from_is_stable`] to a fixed variant fails
11111 /// HERE before landing at the operator-facing checks.lisp
11112 /// surface.
11113 #[test]
11114 fn has_routing_form_returns_true_iff_populated_routing_derives_form_per_kind() {
11115 for is_stable in [true, false] {
11116 let populated = RoutingForm::from_is_stable(is_stable);
11117 let mut spec = empty_ephemeral();
11118 spec.routing = Some(routing_spec(is_stable));
11119 for query in RoutingForm::ALL {
11120 let expected = query == populated;
11121 assert_eq!(
11122 spec.has_routing_form(query),
11123 expected,
11124 "ephemeral routing.stable_name_claim={is_stable} (derives {populated:?}): query {query:?} drifted",
11125 );
11126 }
11127 }
11128 }
11129
11130 /// OPTION-PARENT SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
11131 /// `routing` slot is `None` returns `false` for every
11132 /// [`RoutingForm`] variant, INCLUDING the closed set's
11133 /// derived-default [`RoutingForm::Instance`]. Locks the
11134 /// Option-parent silencing contract so a regression that dropped
11135 /// the `spec.routing.as_ref()` gate (silently probing an absent
11136 /// routing slot as if it carried the defaulted `Instance` form)
11137 /// fails HERE. Peer to
11138 /// [`evaluate_point_require_tag_returns_false_on_absent_routing_for_every_routing_form_kind`]
11139 /// on the point surface — the two-surface symmetry means both
11140 /// classifiers publish the SAME Option-parent silencing at ONE
11141 /// substrate site per surface.
11142 #[test]
11143 fn has_routing_form_returns_false_on_absent_routing_for_every_kind() {
11144 let spec = empty_ephemeral();
11145 assert!(spec.routing.is_none());
11146 for kind in RoutingForm::ALL {
11147 assert!(
11148 !spec.has_routing_form(kind),
11149 "absent ephemeral routing must return false for {kind:?}",
11150 );
11151 }
11152 }
11153
11154 /// DEFAULT-ARM SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
11155 /// `routing` slot is a [`RoutingSpec`] with `stable_name_claim`
11156 /// at its `#[serde(default)]` (bool default = `false`) answers
11157 /// `true` on [`RoutingForm::Instance`] and `false` on every other
11158 /// variant WITHOUT the operator naming the routing-form axis on
11159 /// the routing spec. Peer to
11160 /// [`evaluate_point_require_tag_returns_true_on_default_routing_form_for_instance_only`]
11161 /// on the point surface — both surfaces read the derived-child
11162 /// arm through the ONE substrate composer
11163 /// [`RoutingForm::from_is_stable`], so a future normalization at
11164 /// the derivation lands at ONE site and every downstream
11165 /// (routing-form require-tag families on both surfaces,
11166 /// closed-set audit dispatchers) picks it up mechanically.
11167 #[test]
11168 fn has_routing_form_probes_instance_only_on_default_populated_routing() {
11169 let mut spec = empty_ephemeral();
11170 spec.routing = Some(routing_spec(bool::default()));
11171 for kind in RoutingForm::ALL {
11172 let expected = kind == RoutingForm::Instance;
11173 assert_eq!(
11174 spec.has_routing_form(kind),
11175 expected,
11176 "default-populated ephemeral routing (stable_name_claim=false → Instance) baseline: query {kind:?} must be {expected}",
11177 );
11178 }
11179 }
11180
11181 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
11182 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
11183 /// answer identically on every [`RoutingForm`] × `is_stable`
11184 /// combination. Locks the byte-for-byte parity between
11185 /// [`EphemeralSpec::has_routing_form`] (this new primitive) and
11186 /// the point surface's `spec.routing.as_ref().is_some_and(|r|
11187 /// r.has_form(k))` inline projection at the tatara-check dispatch
11188 /// site. A regression that (a) diverged the ephemeral probe from
11189 /// the lowered point probe (e.g., dropped the Option-parent gate
11190 /// on ONE side, crossed the derived-child arm on the OTHER), or
11191 /// (b) diverged the `From<EphemeralSpec>` lowering's
11192 /// `routing: e.routing` copy from byte-for-byte forwarding, fails
11193 /// HERE at the two-surface boundary.
11194 #[test]
11195 fn has_routing_form_matches_point_peer_through_lowered_routing() {
11196 for is_stable in [true, false] {
11197 let mut authored = empty_ephemeral();
11198 authored.routing = Some(routing_spec(is_stable));
11199 let lowered: ProcessSpec = authored.clone().into();
11200 for kind in RoutingForm::ALL {
11201 let ephemeral_answer = authored.has_routing_form(kind);
11202 let point_answer = lowered.routing.as_ref().is_some_and(|r| r.has_form(kind));
11203 assert_eq!(
11204 ephemeral_answer, point_answer,
11205 "two-surface routing-form parity drift: stable_name_claim={is_stable}, kind={kind:?}",
11206 );
11207 }
11208 }
11209 }
11210
11211 // ── EphemeralSpec::has_applicable_exports_at substrate pins ───────
11212 //
11213 // Fail-before-pass-after granularity: `has_applicable_exports_at`
11214 // did not exist pre-lift on `impl EphemeralSpec` — the peer
11215 // `EphemeralLifetime::has_applicable_exports` on the lowered
11216 // `ProcessSpec` surface routed through the compound
11217 // `.iter().any(|e| e.when.fires_on(phase))` chain inline, so the
11218 // sugar surface had no matching primitive to publish an
11219 // `exports-fire-on-<phase>` prefix family through the
11220 // `strip_and_classify_prefixed_kind` substrate. Post-lift the
11221 // compound-`(when, phase) → fires_on(phase)` probe body lives at
11222 // ONE slice-level substrate site (`ExportSpecSliceExt::has_applicable_at`),
11223 // this ephemeral surface routes through it directly, and the
11224 // point surface reaches the same primitive through
11225 // `spec.lifetime.resolved_ephemeral().is_some_and(|e|
11226 // e.exports.has_applicable_at(phase))`.
11227
11228 fn export_at(when: crate::export::ExportTrigger) -> ExportSpec {
11229 use crate::export::{ArtifactSource, ReceiptsSource, StdoutChannel, VectorChannel};
11230 ExportSpec {
11231 source: ArtifactSource {
11232 receipts: Some(ReceiptsSource::default()),
11233 ..ArtifactSource::default()
11234 },
11235 channel: VectorChannel {
11236 stdout: Some(StdoutChannel::default()),
11237 ..VectorChannel::default()
11238 },
11239 when,
11240 experiment_id_override: None,
11241 }
11242 }
11243
11244 /// EMPTY-EXPORTS pin — an ephemeral spec with an empty `exports`
11245 /// vec returns `false` for EVERY [`ProcessPhase`]. Sweep
11246 /// [`ProcessPhase::ALL`] so a new variant added without a matching
11247 /// arm in [`crate::export::ExportTrigger::fires_on`] surfaces at
11248 /// rustc's exhaustiveness gate on the `ALL` literal (arity forced
11249 /// by `[Self; 11]`) rather than as a silent false-positive at
11250 /// every downstream `exports-fire-on-<phase>` ephemeral require-tag
11251 /// callsite.
11252 #[test]
11253 fn has_applicable_exports_at_returns_false_on_empty_exports_for_every_phase() {
11254 let spec = empty_ephemeral();
11255 assert!(spec.exports.is_empty());
11256 for phase in ProcessPhase::ALL {
11257 assert!(
11258 !spec.has_applicable_exports_at(phase),
11259 "empty-exports ephemeral must return false for {phase:?}",
11260 );
11261 }
11262 }
11263
11264 /// PER-TRIGGER × PER-PHASE pin — an ephemeral spec with a single
11265 /// export answers `has_applicable_exports_at` identically to the
11266 /// [`crate::export::ExportTrigger::fires_on`] truth table on that
11267 /// (trigger, phase) pair, for every combination. Sweep the
11268 /// [`crate::export::ExportTrigger::ALL`] × [`ProcessPhase::ALL`]
11269 /// cross so a regression that (a) short-circuited to raw `when ==
11270 /// kind` equality, (b) missed `Always`'s dual-phase coverage, or
11271 /// (c) inverted a non-terminal phase to return `true` fails HERE
11272 /// at the substrate primitive rather than at each downstream
11273 /// `exports-fire-on-<phase>` classifier callsite.
11274 #[test]
11275 fn has_applicable_exports_at_matches_fires_on_truth_table_per_pair() {
11276 for trigger in crate::export::ExportTrigger::ALL {
11277 let mut spec = empty_ephemeral();
11278 spec.exports = vec![export_at(trigger)];
11279 for phase in ProcessPhase::ALL {
11280 let expected = trigger.fires_on(phase);
11281 assert_eq!(
11282 spec.has_applicable_exports_at(phase),
11283 expected,
11284 "ephemeral trigger={trigger:?} phase={phase:?} drifted from fires_on",
11285 );
11286 }
11287 }
11288 }
11289
11290 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
11291 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
11292 /// answer identically on every [`ProcessPhase`] × trigger
11293 /// combination. Locks the byte-for-byte parity between
11294 /// [`EphemeralSpec::has_applicable_exports_at`] (this new primitive)
11295 /// and the point surface's `spec.lifetime.resolved_ephemeral()
11296 /// .is_some_and(|e| e.exports.has_applicable_at(phase))` projection
11297 /// at the tatara-check dispatch site. A regression that (a)
11298 /// diverged the ephemeral probe from the lowered-lifetime probe,
11299 /// (b) diverged the `From<EphemeralSpec>` lowering's
11300 /// `exports: e.exports` copy from byte-for-byte forwarding, fails
11301 /// HERE at the two-surface boundary.
11302 #[test]
11303 fn has_applicable_exports_at_matches_point_peer_through_lowered_exports() {
11304 for trigger in crate::export::ExportTrigger::ALL {
11305 let mut authored = empty_ephemeral();
11306 authored.exports = vec![export_at(trigger)];
11307 let lowered: ProcessSpec = authored.clone().into();
11308 for phase in ProcessPhase::ALL {
11309 let ephemeral_answer = authored.has_applicable_exports_at(phase);
11310 let point_answer = lowered
11311 .lifetime
11312 .resolved_ephemeral()
11313 .is_some_and(|e| e.exports.has_applicable_at(phase));
11314 assert_eq!(
11315 ephemeral_answer, point_answer,
11316 "two-surface exports-fire-on parity drift: trigger={trigger:?}, phase={phase:?}",
11317 );
11318 }
11319 }
11320 }
11321
11322 /// SUBSTRATE-DELEGATION pin (EphemeralSpec saturation-predicate
11323 /// triad) — the three `is_*_kind_saturated` methods on
11324 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
11325 /// [`ConditionSliceExt::is_kind_saturated`] over the two
11326 /// `Vec<Condition>` slots (precondition + postcondition) and
11327 /// compose the union via `ConditionKind::ALL.iter().all(|k|
11328 /// has_condition_kind(*k))`. Two-surface parity pin against
11329 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on the
11330 /// point-domain [`ProcessSpec`] surface — the two struct-level
11331 /// saturation callers compose against the SAME slice-level
11332 /// substrate primitive so a regression at the per-slice `all`
11333 /// short-circuit fails at that primitive's tests rather than as
11334 /// silent drift at either sugar-surface arm.
11335 #[test]
11336 fn is_condition_kind_saturated_triad_delegates_to_slice_is_kind_saturated() {
11337 // Empty ephemeral spec — every arm returns false.
11338 let spec = empty_ephemeral();
11339 assert!(
11340 !spec.is_precondition_kind_saturated(),
11341 "empty ephemeral must return false on is_precondition_kind_saturated",
11342 );
11343 assert!(
11344 !spec.is_postcondition_kind_saturated(),
11345 "empty ephemeral must return false on is_postcondition_kind_saturated",
11346 );
11347 assert!(
11348 !spec.is_condition_kind_saturated(),
11349 "empty ephemeral must return false on is_condition_kind_saturated",
11350 );
11351 assert_eq!(
11352 spec.is_condition_kind_saturated(),
11353 spec.missing_condition_kinds().is_empty(),
11354 "empty is_condition_kind_saturated must equal missing_condition_kinds().is_empty()",
11355 );
11356
11357 // Single-populated per side — sweep ALL × ALL.
11358 for pre_kind in ConditionKind::ALL {
11359 for post_kind in ConditionKind::ALL {
11360 let mut spec = empty_ephemeral();
11361 spec.preconditions.push(cond(pre_kind));
11362 spec.postconditions.push(cond(post_kind));
11363 assert_eq!(
11364 spec.is_precondition_kind_saturated(),
11365 spec.preconditions.is_kind_saturated(),
11366 "EphemeralSpec::is_precondition_kind_saturated must delegate verbatim to \
11367 preconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
11368 );
11369 assert_eq!(
11370 spec.is_postcondition_kind_saturated(),
11371 spec.postconditions.is_kind_saturated(),
11372 "EphemeralSpec::is_postcondition_kind_saturated must delegate verbatim to \
11373 postconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
11374 );
11375 let expected_union = ConditionKind::ALL
11376 .iter()
11377 .all(|k| pre_kind == *k || post_kind == *k);
11378 assert_eq!(
11379 spec.is_condition_kind_saturated(),
11380 expected_union,
11381 "EphemeralSpec::is_condition_kind_saturated must equal all-ALL-covered-by-either-slice \
11382 for pre={pre_kind:?} post={post_kind:?}",
11383 );
11384
11385 // Two-surface parity: lowered ProcessSpec's Boundary
11386 // must agree bit-for-bit with the ephemeral sugar
11387 // triad on every arm.
11388 let lowered: ProcessSpec = spec.clone().into();
11389 assert_eq!(
11390 spec.is_precondition_kind_saturated(),
11391 lowered.boundary.is_precondition_kind_saturated(),
11392 "two-surface is_precondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
11393 );
11394 assert_eq!(
11395 spec.is_postcondition_kind_saturated(),
11396 lowered.boundary.is_postcondition_kind_saturated(),
11397 "two-surface is_postcondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
11398 );
11399 assert_eq!(
11400 spec.is_condition_kind_saturated(),
11401 lowered.boundary.is_condition_kind_saturated(),
11402 "two-surface is_condition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
11403 );
11404 }
11405 }
11406
11407 // Saturated ephemeral — both slices carry every ConditionKind,
11408 // every arm returns true.
11409 let mut spec = empty_ephemeral();
11410 for k in ConditionKind::ALL {
11411 spec.preconditions.push(cond(k));
11412 spec.postconditions.push(cond(k));
11413 }
11414 assert!(
11415 spec.is_precondition_kind_saturated(),
11416 "saturated ephemeral must return true on is_precondition_kind_saturated",
11417 );
11418 assert!(
11419 spec.is_postcondition_kind_saturated(),
11420 "saturated ephemeral must return true on is_postcondition_kind_saturated",
11421 );
11422 assert!(
11423 spec.is_condition_kind_saturated(),
11424 "saturated ephemeral must return true on is_condition_kind_saturated",
11425 );
11426 }
11427
11428 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
11429 /// triad) — the three `has_any_missing_*_condition_kind` methods
11430 /// on [`EphemeralSpec`] delegate to the slice-level substrate
11431 /// primitive
11432 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
11433 /// over the two `Vec<Condition>` slots (precondition +
11434 /// postcondition) and compose the union via
11435 /// `!self.is_condition_kind_saturated()`. Two-surface parity pin
11436 /// against
11437 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
11438 /// the point-domain [`ProcessSpec`] surface — the two struct-level
11439 /// at-least-one halfspace callers compose against the SAME slice-
11440 /// level substrate primitive so a regression at the per-slice
11441 /// `all` short-circuit under negation fails at that primitive's
11442 /// tests rather than as silent drift at either sugar-surface arm.
11443 #[test]
11444 fn has_any_missing_condition_kind_triad_delegates_to_slice_has_any_missing_kind() {
11445 // Empty ephemeral spec — every arm returns true (every kind is
11446 // missing from every slice + from the union).
11447 let spec = empty_ephemeral();
11448 assert!(
11449 spec.has_any_missing_precondition_kind(),
11450 "empty ephemeral must return true on has_any_missing_precondition_kind",
11451 );
11452 assert!(
11453 spec.has_any_missing_postcondition_kind(),
11454 "empty ephemeral must return true on has_any_missing_postcondition_kind",
11455 );
11456 assert!(
11457 spec.has_any_missing_condition_kind(),
11458 "empty ephemeral must return true on has_any_missing_condition_kind",
11459 );
11460 assert_eq!(
11461 spec.has_any_missing_condition_kind(),
11462 !spec.is_condition_kind_saturated(),
11463 "empty has_any_missing_condition_kind must equal !is_condition_kind_saturated()",
11464 );
11465
11466 // Single-populated per side — sweep ALL × ALL, then pin the
11467 // (pre, post, union) triad + two-surface parity against the
11468 // lowered ProcessSpec's Boundary.
11469 for pre_kind in ConditionKind::ALL {
11470 for post_kind in ConditionKind::ALL {
11471 let mut spec = empty_ephemeral();
11472 spec.preconditions.push(cond(pre_kind));
11473 spec.postconditions.push(cond(post_kind));
11474 assert_eq!(
11475 spec.has_any_missing_precondition_kind(),
11476 spec.preconditions.has_any_missing_kind(),
11477 "EphemeralSpec::has_any_missing_precondition_kind must delegate verbatim to \
11478 preconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11479 );
11480 assert_eq!(
11481 spec.has_any_missing_postcondition_kind(),
11482 spec.postconditions.has_any_missing_kind(),
11483 "EphemeralSpec::has_any_missing_postcondition_kind must delegate verbatim to \
11484 postconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11485 );
11486 let expected_union = !ConditionKind::ALL
11487 .iter()
11488 .all(|k| pre_kind == *k || post_kind == *k);
11489 assert_eq!(
11490 spec.has_any_missing_condition_kind(),
11491 expected_union,
11492 "EphemeralSpec::has_any_missing_condition_kind must equal \
11493 !all-ALL-covered-by-either-slice \
11494 for pre={pre_kind:?} post={post_kind:?}",
11495 );
11496
11497 // Two-surface parity: lowered ProcessSpec's Boundary
11498 // must agree bit-for-bit with the ephemeral sugar
11499 // triad on every arm.
11500 let lowered: ProcessSpec = spec.clone().into();
11501 assert_eq!(
11502 spec.has_any_missing_precondition_kind(),
11503 lowered.boundary.has_any_missing_precondition_kind(),
11504 "two-surface has_any_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11505 );
11506 assert_eq!(
11507 spec.has_any_missing_postcondition_kind(),
11508 lowered.boundary.has_any_missing_postcondition_kind(),
11509 "two-surface has_any_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11510 );
11511 assert_eq!(
11512 spec.has_any_missing_condition_kind(),
11513 lowered.boundary.has_any_missing_condition_kind(),
11514 "two-surface has_any_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11515 );
11516 }
11517 }
11518
11519 // Saturated ephemeral — both slices carry every ConditionKind,
11520 // every arm returns false.
11521 let mut spec = empty_ephemeral();
11522 for k in ConditionKind::ALL {
11523 spec.preconditions.push(cond(k));
11524 spec.postconditions.push(cond(k));
11525 }
11526 assert!(
11527 !spec.has_any_missing_precondition_kind(),
11528 "saturated ephemeral must return false on has_any_missing_precondition_kind",
11529 );
11530 assert!(
11531 !spec.has_any_missing_postcondition_kind(),
11532 "saturated ephemeral must return false on has_any_missing_postcondition_kind",
11533 );
11534 assert!(
11535 !spec.has_any_missing_condition_kind(),
11536 "saturated ephemeral must return false on has_any_missing_condition_kind",
11537 );
11538 }
11539
11540 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-mid-endpoint
11541 /// triad) — the three `has_unique_missing_*_condition_kind`
11542 /// methods on [`EphemeralSpec`] delegate to the slice-level
11543 /// substrate primitive
11544 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
11545 /// over the two `Vec<Condition>` slots (precondition +
11546 /// postcondition) and compose the union via a two-step-short-
11547 /// circuit walk over [`ConditionKind::ALL`] under negated
11548 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
11549 /// against
11550 /// [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
11551 /// on the point-domain [`ProcessSpec`] surface — the two struct-
11552 /// level near-saturation-endpoint callers compose against the
11553 /// SAME slice-level substrate primitive so a regression at the
11554 /// per-slice two-step short-circuit walk under negation fails at
11555 /// that primitive's tests rather than as silent drift at either
11556 /// sugar-surface arm.
11557 #[test]
11558 fn has_unique_missing_condition_kind_triad_delegates_to_slice_has_unique_missing_kind() {
11559 // Empty ephemeral spec — every arm returns false (all N
11560 // missing, not exactly 1) on any N ≥ 2 closed set.
11561 assert!(
11562 ConditionKind::ALL.len() >= 2,
11563 "test assumes ConditionKind::ALL has ≥ 2 variants",
11564 );
11565 let spec = empty_ephemeral();
11566 assert!(
11567 !spec.has_unique_missing_precondition_kind(),
11568 "empty ephemeral must return false on has_unique_missing_precondition_kind",
11569 );
11570 assert!(
11571 !spec.has_unique_missing_postcondition_kind(),
11572 "empty ephemeral must return false on has_unique_missing_postcondition_kind",
11573 );
11574 assert!(
11575 !spec.has_unique_missing_condition_kind(),
11576 "empty ephemeral must return false on has_unique_missing_condition_kind",
11577 );
11578 assert_eq!(
11579 spec.has_unique_missing_condition_kind(),
11580 spec.missing_condition_kind_count() == 1,
11581 "empty has_unique_missing_condition_kind must equal (missing_condition_kind_count() == 1)",
11582 );
11583
11584 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
11585 // sets. Every per-slice arm returns false; the union returns
11586 // true iff exactly one ALL variant is uncovered.
11587 if ConditionKind::ALL.len() >= 3 {
11588 for pre_kind in ConditionKind::ALL {
11589 for post_kind in ConditionKind::ALL {
11590 let mut spec = empty_ephemeral();
11591 spec.preconditions.push(cond(pre_kind));
11592 spec.postconditions.push(cond(post_kind));
11593 assert_eq!(
11594 spec.has_unique_missing_precondition_kind(),
11595 spec.preconditions.has_unique_missing_kind(),
11596 "EphemeralSpec::has_unique_missing_precondition_kind must delegate verbatim to \
11597 preconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11598 );
11599 assert_eq!(
11600 spec.has_unique_missing_postcondition_kind(),
11601 spec.postconditions.has_unique_missing_kind(),
11602 "EphemeralSpec::has_unique_missing_postcondition_kind must delegate verbatim to \
11603 postconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11604 );
11605 let uncovered = ConditionKind::ALL
11606 .into_iter()
11607 .filter(|k| *k != pre_kind && *k != post_kind)
11608 .count();
11609 let expected_union = uncovered == 1;
11610 assert_eq!(
11611 spec.has_unique_missing_condition_kind(),
11612 expected_union,
11613 "EphemeralSpec::has_unique_missing_condition_kind must equal \
11614 (uncovered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
11615 );
11616
11617 // Two-surface parity: lowered ProcessSpec's
11618 // Boundary must agree bit-for-bit with the
11619 // ephemeral sugar triad on every arm.
11620 let lowered: ProcessSpec = spec.clone().into();
11621 assert_eq!(
11622 spec.has_unique_missing_precondition_kind(),
11623 lowered.boundary.has_unique_missing_precondition_kind(),
11624 "two-surface has_unique_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11625 );
11626 assert_eq!(
11627 spec.has_unique_missing_postcondition_kind(),
11628 lowered.boundary.has_unique_missing_postcondition_kind(),
11629 "two-surface has_unique_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11630 );
11631 assert_eq!(
11632 spec.has_unique_missing_condition_kind(),
11633 lowered.boundary.has_unique_missing_condition_kind(),
11634 "two-surface has_unique_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11635 );
11636 }
11637 }
11638 }
11639
11640 // Near-saturation-endpoint per side — each slice carries
11641 // every ConditionKind except one. Every per-slice arm returns
11642 // true; the union returns true iff BOTH slices omit the SAME
11643 // kind.
11644 for pre_omit in ConditionKind::ALL {
11645 for post_omit in ConditionKind::ALL {
11646 let mut spec = empty_ephemeral();
11647 for k in ConditionKind::ALL {
11648 if k != pre_omit {
11649 spec.preconditions.push(cond(k));
11650 }
11651 if k != post_omit {
11652 spec.postconditions.push(cond(k));
11653 }
11654 }
11655 assert!(
11656 spec.has_unique_missing_precondition_kind(),
11657 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_unique_missing_precondition_kind",
11658 );
11659 assert!(
11660 spec.has_unique_missing_postcondition_kind(),
11661 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_unique_missing_postcondition_kind",
11662 );
11663 let expected_union = pre_omit == post_omit;
11664 assert_eq!(
11665 spec.has_unique_missing_condition_kind(),
11666 expected_union,
11667 "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:?}",
11668 );
11669
11670 // Two-surface parity for near-saturation arm.
11671 let lowered: ProcessSpec = spec.clone().into();
11672 assert_eq!(
11673 spec.has_unique_missing_precondition_kind(),
11674 lowered.boundary.has_unique_missing_precondition_kind(),
11675 "two-surface has_unique_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11676 );
11677 assert_eq!(
11678 spec.has_unique_missing_postcondition_kind(),
11679 lowered.boundary.has_unique_missing_postcondition_kind(),
11680 "two-surface has_unique_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11681 );
11682 assert_eq!(
11683 spec.has_unique_missing_condition_kind(),
11684 lowered.boundary.has_unique_missing_condition_kind(),
11685 "two-surface has_unique_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11686 );
11687 }
11688 }
11689
11690 // Saturated ephemeral — every arm returns false (0 missing,
11691 // not exactly 1).
11692 let mut spec = empty_ephemeral();
11693 for k in ConditionKind::ALL {
11694 spec.preconditions.push(cond(k));
11695 spec.postconditions.push(cond(k));
11696 }
11697 assert!(
11698 !spec.has_unique_missing_precondition_kind(),
11699 "saturated ephemeral must return false on has_unique_missing_precondition_kind",
11700 );
11701 assert!(
11702 !spec.has_unique_missing_postcondition_kind(),
11703 "saturated ephemeral must return false on has_unique_missing_postcondition_kind",
11704 );
11705 assert!(
11706 !spec.has_unique_missing_condition_kind(),
11707 "saturated ephemeral must return false on has_unique_missing_condition_kind",
11708 );
11709 }
11710
11711 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
11712 /// triad) — the three `has_multiple_missing_*_condition_kind`
11713 /// methods on [`EphemeralSpec`] delegate to the slice-level
11714 /// substrate primitive
11715 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
11716 /// over the two `Vec<Condition>` slots (precondition +
11717 /// postcondition) and compose the union via a two-step-short-
11718 /// circuit walk over [`ConditionKind::ALL`] under negated
11719 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
11720 /// against
11721 /// [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
11722 /// on the point-domain [`ProcessSpec`] surface — the two struct-
11723 /// level cardinality-many-arm callers compose against the SAME
11724 /// slice-level substrate primitive so a regression at the per-
11725 /// slice two-step short-circuit walk under negation fails at that
11726 /// primitive's tests rather than as silent drift at either sugar-
11727 /// surface arm.
11728 #[test]
11729 fn has_multiple_missing_condition_kind_triad_delegates_to_slice_has_multiple_missing_kinds() {
11730 // Empty ephemeral spec — every arm returns true (all N
11731 // missing, ≥ 2) on any N ≥ 2 closed set.
11732 assert!(
11733 ConditionKind::ALL.len() >= 2,
11734 "test assumes ConditionKind::ALL has ≥ 2 variants",
11735 );
11736 let spec = empty_ephemeral();
11737 assert!(
11738 spec.has_multiple_missing_precondition_kind(),
11739 "empty ephemeral must return true on has_multiple_missing_precondition_kind",
11740 );
11741 assert!(
11742 spec.has_multiple_missing_postcondition_kind(),
11743 "empty ephemeral must return true on has_multiple_missing_postcondition_kind",
11744 );
11745 assert!(
11746 spec.has_multiple_missing_condition_kind(),
11747 "empty ephemeral must return true on has_multiple_missing_condition_kind",
11748 );
11749 assert_eq!(
11750 spec.has_multiple_missing_condition_kind(),
11751 spec.missing_condition_kind_count() >= 2,
11752 "empty has_multiple_missing_condition_kind must equal (missing_condition_kind_count() >= 2)",
11753 );
11754
11755 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
11756 // sets. Every per-slice arm returns true; the union returns
11757 // true iff ≥ 2 ALL variants are uncovered.
11758 if ConditionKind::ALL.len() >= 3 {
11759 for pre_kind in ConditionKind::ALL {
11760 for post_kind in ConditionKind::ALL {
11761 let mut spec = empty_ephemeral();
11762 spec.preconditions.push(cond(pre_kind));
11763 spec.postconditions.push(cond(post_kind));
11764 assert_eq!(
11765 spec.has_multiple_missing_precondition_kind(),
11766 spec.preconditions.has_multiple_missing_kinds(),
11767 "EphemeralSpec::has_multiple_missing_precondition_kind must delegate verbatim to \
11768 preconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
11769 );
11770 assert_eq!(
11771 spec.has_multiple_missing_postcondition_kind(),
11772 spec.postconditions.has_multiple_missing_kinds(),
11773 "EphemeralSpec::has_multiple_missing_postcondition_kind must delegate verbatim to \
11774 postconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
11775 );
11776 let uncovered = ConditionKind::ALL
11777 .into_iter()
11778 .filter(|k| *k != pre_kind && *k != post_kind)
11779 .count();
11780 let expected_union = uncovered >= 2;
11781 assert_eq!(
11782 spec.has_multiple_missing_condition_kind(),
11783 expected_union,
11784 "EphemeralSpec::has_multiple_missing_condition_kind must equal \
11785 (uncovered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
11786 );
11787
11788 // Two-surface parity: lowered ProcessSpec's
11789 // Boundary must agree bit-for-bit with the
11790 // ephemeral sugar triad on every arm.
11791 let lowered: ProcessSpec = spec.clone().into();
11792 assert_eq!(
11793 spec.has_multiple_missing_precondition_kind(),
11794 lowered.boundary.has_multiple_missing_precondition_kind(),
11795 "two-surface has_multiple_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11796 );
11797 assert_eq!(
11798 spec.has_multiple_missing_postcondition_kind(),
11799 lowered.boundary.has_multiple_missing_postcondition_kind(),
11800 "two-surface has_multiple_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11801 );
11802 assert_eq!(
11803 spec.has_multiple_missing_condition_kind(),
11804 lowered.boundary.has_multiple_missing_condition_kind(),
11805 "two-surface has_multiple_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11806 );
11807 }
11808 }
11809 }
11810
11811 // Near-saturation-endpoint per side — each slice carries
11812 // every ConditionKind except one. Every per-slice arm returns
11813 // false (exactly 1 missing per slice, not ≥ 2). The union
11814 // has at most 1 missing (pre and post's omissions either
11815 // coincide → 1 missing, or differ → 0 missing), so the union
11816 // is always false on this arm.
11817 for pre_omit in ConditionKind::ALL {
11818 for post_omit in ConditionKind::ALL {
11819 let mut spec = empty_ephemeral();
11820 for k in ConditionKind::ALL {
11821 if k != pre_omit {
11822 spec.preconditions.push(cond(k));
11823 }
11824 if k != post_omit {
11825 spec.postconditions.push(cond(k));
11826 }
11827 }
11828 assert!(
11829 !spec.has_multiple_missing_precondition_kind(),
11830 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return false on has_multiple_missing_precondition_kind",
11831 );
11832 assert!(
11833 !spec.has_multiple_missing_postcondition_kind(),
11834 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return false on has_multiple_missing_postcondition_kind",
11835 );
11836 assert!(
11837 !spec.has_multiple_missing_condition_kind(),
11838 "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:?}",
11839 );
11840
11841 // Two-surface parity for near-saturation arm.
11842 let lowered: ProcessSpec = spec.clone().into();
11843 assert_eq!(
11844 spec.has_multiple_missing_precondition_kind(),
11845 lowered.boundary.has_multiple_missing_precondition_kind(),
11846 "two-surface has_multiple_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11847 );
11848 assert_eq!(
11849 spec.has_multiple_missing_postcondition_kind(),
11850 lowered.boundary.has_multiple_missing_postcondition_kind(),
11851 "two-surface has_multiple_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11852 );
11853 assert_eq!(
11854 spec.has_multiple_missing_condition_kind(),
11855 lowered.boundary.has_multiple_missing_condition_kind(),
11856 "two-surface has_multiple_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11857 );
11858 }
11859 }
11860
11861 // Saturated ephemeral — every arm returns false (0 missing,
11862 // not ≥ 2).
11863 let mut spec = empty_ephemeral();
11864 for k in ConditionKind::ALL {
11865 spec.preconditions.push(cond(k));
11866 spec.postconditions.push(cond(k));
11867 }
11868 assert!(
11869 !spec.has_multiple_missing_precondition_kind(),
11870 "saturated ephemeral must return false on has_multiple_missing_precondition_kind",
11871 );
11872 assert!(
11873 !spec.has_multiple_missing_postcondition_kind(),
11874 "saturated ephemeral must return false on has_multiple_missing_postcondition_kind",
11875 );
11876 assert!(
11877 !spec.has_multiple_missing_condition_kind(),
11878 "saturated ephemeral must return false on has_multiple_missing_condition_kind",
11879 );
11880 }
11881
11882 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1"
11883 /// triad) — the three `has_at_most_one_missing_*_condition_kind`
11884 /// methods on [`EphemeralSpec`] delegate to the slice-level
11885 /// substrate primitive
11886 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
11887 /// over the two `Vec<Condition>` slots (precondition +
11888 /// postcondition) and compose the union via
11889 /// `!self.has_multiple_missing_condition_kind()` — a definitional
11890 /// negation of the many-arm union primitive. Two-surface parity
11891 /// pin against
11892 /// [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
11893 /// on the point-domain [`ProcessSpec`] surface — the two struct-
11894 /// level cardinality "≤ 1" callers compose against the SAME
11895 /// slice-level substrate primitive so a regression at the per-
11896 /// slice "≤ 1" negation fails at that primitive's tests rather
11897 /// than as silent drift at either sugar-surface arm.
11898 #[test]
11899 fn has_at_most_one_missing_condition_kind_triad_delegates_to_slice_has_at_most_one_missing_kind(
11900 ) {
11901 // Empty ephemeral spec — every arm returns false (all N
11902 // missing, not ≤ 1) on any N ≥ 2 closed set.
11903 assert!(
11904 ConditionKind::ALL.len() >= 2,
11905 "test assumes ConditionKind::ALL has ≥ 2 variants",
11906 );
11907 let spec = empty_ephemeral();
11908 assert!(
11909 !spec.has_at_most_one_missing_precondition_kind(),
11910 "empty ephemeral must return false on has_at_most_one_missing_precondition_kind",
11911 );
11912 assert!(
11913 !spec.has_at_most_one_missing_postcondition_kind(),
11914 "empty ephemeral must return false on has_at_most_one_missing_postcondition_kind",
11915 );
11916 assert!(
11917 !spec.has_at_most_one_missing_condition_kind(),
11918 "empty ephemeral must return false on has_at_most_one_missing_condition_kind",
11919 );
11920 assert_eq!(
11921 spec.has_at_most_one_missing_condition_kind(),
11922 spec.missing_condition_kind_count() <= 1,
11923 "empty has_at_most_one_missing_condition_kind must equal (missing_condition_kind_count() <= 1)",
11924 );
11925
11926 // Single-populated per side — sweep ALL × ALL on N ≥ 3
11927 // closed sets. Every per-slice arm returns false; the union
11928 // returns true iff ≤ 1 ALL variant is uncovered.
11929 if ConditionKind::ALL.len() >= 3 {
11930 for pre_kind in ConditionKind::ALL {
11931 for post_kind in ConditionKind::ALL {
11932 let mut spec = empty_ephemeral();
11933 spec.preconditions.push(cond(pre_kind));
11934 spec.postconditions.push(cond(post_kind));
11935 assert_eq!(
11936 spec.has_at_most_one_missing_precondition_kind(),
11937 spec.preconditions.has_at_most_one_missing_kind(),
11938 "EphemeralSpec::has_at_most_one_missing_precondition_kind must delegate verbatim to \
11939 preconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11940 );
11941 assert_eq!(
11942 spec.has_at_most_one_missing_postcondition_kind(),
11943 spec.postconditions.has_at_most_one_missing_kind(),
11944 "EphemeralSpec::has_at_most_one_missing_postcondition_kind must delegate verbatim to \
11945 postconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11946 );
11947 let uncovered = ConditionKind::ALL
11948 .into_iter()
11949 .filter(|k| *k != pre_kind && *k != post_kind)
11950 .count();
11951 let expected_union = uncovered <= 1;
11952 assert_eq!(
11953 spec.has_at_most_one_missing_condition_kind(),
11954 expected_union,
11955 "EphemeralSpec::has_at_most_one_missing_condition_kind must equal \
11956 (uncovered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
11957 );
11958
11959 // Two-surface parity: lowered ProcessSpec's
11960 // Boundary must agree bit-for-bit with the
11961 // ephemeral sugar triad on every arm.
11962 let lowered: ProcessSpec = spec.clone().into();
11963 assert_eq!(
11964 spec.has_at_most_one_missing_precondition_kind(),
11965 lowered.boundary.has_at_most_one_missing_precondition_kind(),
11966 "two-surface has_at_most_one_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11967 );
11968 assert_eq!(
11969 spec.has_at_most_one_missing_postcondition_kind(),
11970 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
11971 "two-surface has_at_most_one_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11972 );
11973 assert_eq!(
11974 spec.has_at_most_one_missing_condition_kind(),
11975 lowered.boundary.has_at_most_one_missing_condition_kind(),
11976 "two-surface has_at_most_one_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11977 );
11978 }
11979 }
11980 }
11981
11982 // Near-saturation-endpoint per side — each slice carries
11983 // every ConditionKind except one. Every per-slice arm returns
11984 // true (exactly 1 missing per slice, ≤ 1). The union has ≤ 1
11985 // missing (pre and post's omissions either coincide → 1
11986 // missing, or differ → 0 missing), so the union is always
11987 // true on this arm.
11988 for pre_omit in ConditionKind::ALL {
11989 for post_omit in ConditionKind::ALL {
11990 let mut spec = empty_ephemeral();
11991 for k in ConditionKind::ALL {
11992 if k != pre_omit {
11993 spec.preconditions.push(cond(k));
11994 }
11995 if k != post_omit {
11996 spec.postconditions.push(cond(k));
11997 }
11998 }
11999 assert!(
12000 spec.has_at_most_one_missing_precondition_kind(),
12001 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_at_most_one_missing_precondition_kind",
12002 );
12003 assert!(
12004 spec.has_at_most_one_missing_postcondition_kind(),
12005 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_at_most_one_missing_postcondition_kind",
12006 );
12007 assert!(
12008 spec.has_at_most_one_missing_condition_kind(),
12009 "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:?}",
12010 );
12011
12012 // Two-surface parity for near-saturation arm.
12013 let lowered: ProcessSpec = spec.clone().into();
12014 assert_eq!(
12015 spec.has_at_most_one_missing_precondition_kind(),
12016 lowered.boundary.has_at_most_one_missing_precondition_kind(),
12017 "two-surface has_at_most_one_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12018 );
12019 assert_eq!(
12020 spec.has_at_most_one_missing_postcondition_kind(),
12021 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
12022 "two-surface has_at_most_one_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12023 );
12024 assert_eq!(
12025 spec.has_at_most_one_missing_condition_kind(),
12026 lowered.boundary.has_at_most_one_missing_condition_kind(),
12027 "two-surface has_at_most_one_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
12028 );
12029 }
12030 }
12031
12032 // Saturated ephemeral — every arm returns true (0 missing,
12033 // ≤ 1).
12034 let mut spec = empty_ephemeral();
12035 for k in ConditionKind::ALL {
12036 spec.preconditions.push(cond(k));
12037 spec.postconditions.push(cond(k));
12038 }
12039 assert!(
12040 spec.has_at_most_one_missing_precondition_kind(),
12041 "saturated ephemeral must return true on has_at_most_one_missing_precondition_kind",
12042 );
12043 assert!(
12044 spec.has_at_most_one_missing_postcondition_kind(),
12045 "saturated ephemeral must return true on has_at_most_one_missing_postcondition_kind",
12046 );
12047 assert!(
12048 spec.has_at_most_one_missing_condition_kind(),
12049 "saturated ephemeral must return true on has_at_most_one_missing_condition_kind",
12050 );
12051 }
12052
12053 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind-complement
12054 /// triad) — the three `lacks_*_condition_kind` methods on
12055 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
12056 /// [`ConditionSliceExt::lacks_kind`] over the two `Vec<Condition>`
12057 /// slots (precondition + postcondition) and compose the union via
12058 /// `!self.has_condition_kind(kind)`. Two-surface parity pin against
12059 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
12060 /// point-domain [`ProcessSpec`] surface — the two struct-level
12061 /// per-kind-complement callers compose against the SAME slice-level
12062 /// substrate primitive so a regression at the per-slice negation
12063 /// fails at that primitive's tests rather than as silent drift at
12064 /// either sugar-surface arm. Also pins the composition laws
12065 /// `lacks_*_condition_kind(k) == !has_*_condition_kind(k)` at each
12066 /// arm AND `lacks_condition_kind(k) == lacks_precondition_kind(k) &&
12067 /// lacks_postcondition_kind(k)` (the union AND-composition dual of
12068 /// `has`'s OR-composition).
12069 #[test]
12070 fn lacks_condition_kind_triad_delegates_to_slice_lacks_kind() {
12071 // Empty ephemeral spec — every arm returns true on every kind.
12072 let spec = empty_ephemeral();
12073 for kind in ConditionKind::ALL {
12074 assert!(
12075 spec.lacks_precondition_kind(kind),
12076 "empty ephemeral must return true on lacks_precondition_kind for {kind:?}",
12077 );
12078 assert!(
12079 spec.lacks_postcondition_kind(kind),
12080 "empty ephemeral must return true on lacks_postcondition_kind for {kind:?}",
12081 );
12082 assert!(
12083 spec.lacks_condition_kind(kind),
12084 "empty ephemeral must return true on lacks_condition_kind for {kind:?}",
12085 );
12086 assert_eq!(
12087 spec.lacks_condition_kind(kind),
12088 !spec.has_condition_kind(kind),
12089 "empty lacks_condition_kind must equal !has_condition_kind for {kind:?}",
12090 );
12091 }
12092
12093 // Single-populated per side — sweep ALL × ALL, then probe every
12094 // ConditionKind on the (pre, post, union) triad + two-surface
12095 // parity against the lowered ProcessSpec's Boundary.
12096 for pre_kind in ConditionKind::ALL {
12097 for post_kind in ConditionKind::ALL {
12098 let mut spec = empty_ephemeral();
12099 spec.preconditions.push(cond(pre_kind));
12100 spec.postconditions.push(cond(post_kind));
12101 let lowered: ProcessSpec = spec.clone().into();
12102 for probe in ConditionKind::ALL {
12103 assert_eq!(
12104 spec.lacks_precondition_kind(probe),
12105 spec.preconditions.lacks_kind(probe),
12106 "EphemeralSpec::lacks_precondition_kind must delegate verbatim to preconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12107 );
12108 assert_eq!(
12109 spec.lacks_postcondition_kind(probe),
12110 spec.postconditions.lacks_kind(probe),
12111 "EphemeralSpec::lacks_postcondition_kind must delegate verbatim to postconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12112 );
12113 let expected_union = pre_kind != probe && post_kind != probe;
12114 assert_eq!(
12115 spec.lacks_condition_kind(probe),
12116 expected_union,
12117 "EphemeralSpec::lacks_condition_kind must equal all-ALL-absent-in-both-slices for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12118 );
12119 assert_eq!(
12120 spec.lacks_condition_kind(probe),
12121 !spec.has_condition_kind(probe),
12122 "EphemeralSpec::lacks_condition_kind must equal !has_condition_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12123 );
12124 assert_eq!(
12125 spec.lacks_condition_kind(probe),
12126 spec.lacks_precondition_kind(probe)
12127 && spec.lacks_postcondition_kind(probe),
12128 "EphemeralSpec::lacks_condition_kind must equal AND-of-half-slice-arms for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12129 );
12130
12131 // Two-surface parity: lowered ProcessSpec's Boundary
12132 // must agree bit-for-bit with the ephemeral sugar
12133 // triad on every arm.
12134 assert_eq!(
12135 spec.lacks_precondition_kind(probe),
12136 lowered.boundary.lacks_precondition_kind(probe),
12137 "two-surface lacks_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12138 );
12139 assert_eq!(
12140 spec.lacks_postcondition_kind(probe),
12141 lowered.boundary.lacks_postcondition_kind(probe),
12142 "two-surface lacks_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12143 );
12144 assert_eq!(
12145 spec.lacks_condition_kind(probe),
12146 lowered.boundary.lacks_condition_kind(probe),
12147 "two-surface lacks_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
12148 );
12149 }
12150 }
12151 }
12152
12153 // Saturated ephemeral — both slices carry every ConditionKind,
12154 // every arm returns false on every kind.
12155 let mut spec = empty_ephemeral();
12156 for k in ConditionKind::ALL {
12157 spec.preconditions.push(cond(k));
12158 spec.postconditions.push(cond(k));
12159 }
12160 for kind in ConditionKind::ALL {
12161 assert!(
12162 !spec.lacks_precondition_kind(kind),
12163 "saturated ephemeral must return false on lacks_precondition_kind for {kind:?}",
12164 );
12165 assert!(
12166 !spec.lacks_postcondition_kind(kind),
12167 "saturated ephemeral must return false on lacks_postcondition_kind for {kind:?}",
12168 );
12169 assert!(
12170 !spec.lacks_condition_kind(kind),
12171 "saturated ephemeral must return false on lacks_condition_kind for {kind:?}",
12172 );
12173 }
12174 }
12175}