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` carries NO
1564 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
1565 /// — the peer of
1566 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
1567 /// [`EphemeralSpec`] sugar surface.
1568 ///
1569 /// # Composed body — byte-identical to
1570 /// [`crate::boundary::Boundary::lacks_condition_kind`]
1571 ///
1572 /// `!self.has_condition_kind(kind)` — the definitional negation of
1573 /// the two-slice union primitive [`Self::has_condition_kind`].
1574 /// Byte-identical to the peer method on the point-domain
1575 /// [`crate::boundary::Boundary`] surface — both compose against
1576 /// the SAME slice-level substrate primitive
1577 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] via the
1578 /// two-slice union so a regression at the per-slice negation
1579 /// fails at that primitive's tests rather than as silent drift at
1580 /// either struct-level complement caller.
1581 ///
1582 /// # Sibling to [`Self::missing_condition_kinds`] /
1583 /// [`Self::missing_condition_kind_count`]
1584 ///
1585 /// Per-kind Boolean projection of the widened + scalar closed-set-
1586 /// complement primitives on the ephemeral-union surface — where
1587 /// those primitives return the FULL missing SET (a `Vec` of every
1588 /// absent kind) and its cardinality (a `usize`),
1589 /// `lacks_condition_kind` collapses the missing SET to its
1590 /// per-kind membership Boolean for ONE addressed kind. Strictly
1591 /// cheaper than reaching for the widened primitive on every
1592 /// per-kind question because the negation short-circuits through
1593 /// [`Self::has_condition_kind`] rather than allocating the
1594 /// closed-set-complement scan.
1595 ///
1596 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1597 /// preserves proofs — the per-kind closed-set-complement
1598 /// projection composes the SAME two-slice union negation on both
1599 /// this ephemeral surface and the point-domain
1600 /// [`crate::boundary::Boundary`] surface under definitional
1601 /// negation). THEORY.md §VI.1 (generation over composition — a
1602 /// future [`ConditionKind`] variant reaches both surfaces'
1603 /// per-kind-complement triads mechanically through the delegated
1604 /// union primitive).
1605 #[must_use]
1606 pub fn lacks_condition_kind(&self, kind: ConditionKind) -> bool {
1607 !self.has_condition_kind(kind)
1608 }
1609
1610 /// `true` iff [`Self::preconditions`] carries NO
1611 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
1612 /// — the precondition-side arm of the (precondition, postcondition,
1613 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
1614 /// Thin typed delegate to
1615 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
1616 /// [`Self::preconditions`].
1617 ///
1618 /// Peer of
1619 /// [`crate::boundary::Boundary::lacks_precondition_kind`] on the
1620 /// point-domain surface — both peers compose against the SAME
1621 /// slice-level substrate primitive so a regression at the
1622 /// per-slice negation fails at that primitive's tests rather than
1623 /// as silent drift at either struct-level arm.
1624 #[must_use]
1625 pub fn lacks_precondition_kind(&self, kind: ConditionKind) -> bool {
1626 self.preconditions.lacks_kind(kind)
1627 }
1628
1629 /// `true` iff [`Self::postconditions`] carries NO
1630 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
1631 /// — the postcondition-side arm of the (precondition, postcondition,
1632 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
1633 /// Thin typed delegate to
1634 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
1635 /// [`Self::postconditions`].
1636 ///
1637 /// Peer of
1638 /// [`crate::boundary::Boundary::lacks_postcondition_kind`] on the
1639 /// point-domain surface. See [`Self::lacks_precondition_kind`] for
1640 /// the full rationale — the two methods share ONE lift motivation,
1641 /// ONE fail-before-pass-after composition-law pin, and ONE
1642 /// two-surface parity contract with the point-domain
1643 /// [`crate::boundary::Boundary`] per-kind-complement peer methods.
1644 #[must_use]
1645 pub fn lacks_postcondition_kind(&self, kind: ConditionKind) -> bool {
1646 self.postconditions.lacks_kind(kind)
1647 }
1648
1649 /// True iff this ephemeral spec's stored [`TeardownPolicy`] equals
1650 /// `kind` — the substrate primitive that owns the
1651 /// (`&EphemeralSpec`, [`TeardownPolicy`]) → `bool` presence-probe
1652 /// shape on the sugar-surface type.
1653 ///
1654 /// # Peer to [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
1655 ///
1656 /// [`EphemeralLifetime::has_teardown_policy`] carries the same
1657 /// `(&self, TeardownPolicy) -> bool` signature on the point-surface
1658 /// carrier ([`ProcessSpec`]'s nested [`crate::lifetime::Lifetime`]
1659 /// slot reached through
1660 /// [`crate::lifetime::Lifetime::resolved_ephemeral`]); this peer
1661 /// composes byte-identical `==` semantics on
1662 /// [`EphemeralSpec`]'s direct `teardown: TeardownPolicy` scalar
1663 /// slot, so both surfaces' `teardown-policy-<kind>` require-tag
1664 /// families ([`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
1665 /// on the point surface, this peer on the ephemeral surface) route
1666 /// through the SAME scalar `==` shape. A future normalization at
1667 /// the probe shape (a widened return carrying a `TerminatePolicy`
1668 /// disambiguator, a debug-build assertion on operator-set vs
1669 /// defaulted overrides, a fleet-wide warn on `Never` combined with
1670 /// short TTLs) lands at ONE site per surface and every downstream
1671 /// `teardown-policy-<kind>` require-tag family + closed-set audit
1672 /// dispatcher picks it up mechanically.
1673 ///
1674 /// # Semantics — VARIANT match, not POPULATED slot
1675 ///
1676 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
1677 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
1678 /// absent state to detect. `has_teardown_policy(kind)` returns
1679 /// `true` iff `self.teardown == kind`. On a hand-authored
1680 /// [`EphemeralSpec`] that omits `:teardown` from the
1681 /// `(defephemeral …)` form (or a Rust builder that reaches
1682 /// [`TeardownPolicy::default`]) the probe returns `true` for
1683 /// [`TeardownPolicy::Always`] and `false` for every other variant
1684 /// — distinct from the Option-slot axis where a default carrier
1685 /// returns `false` for EVERY kind. An operator who left
1686 /// `:teardown` at the substrate default IS configured for
1687 /// `Always`, and a `:requires (teardown-policy-Always)` check
1688 /// should pass; only an operator who deliberately overrode the
1689 /// policy to `OnAttested` / `OnFailed` / `Never` fails the tag on
1690 /// this axis.
1691 ///
1692 /// # Corner — (required-scalar-child)
1693 ///
1694 /// Fresh corner on the ephemeral surface's presence-probe algebra:
1695 /// [`EphemeralSpec`] has no Option-parent hop between the sugar
1696 /// struct and the `teardown` scalar (the point surface reaches
1697 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
1698 /// through the Option-parent `resolved_ephemeral()` gate), so the
1699 /// probe body is a bare scalar `==` on a required field. Distinct
1700 /// from [`Self::has_condition_kind`] on this same surface, which
1701 /// walks a `Vec<Condition>` slice-child.
1702 ///
1703 /// # Compounding
1704 ///
1705 /// The ephemeral require-tag classifier composes this primitive
1706 /// with the closed-set `FromStr` autoderived on [`TeardownPolicy`]
1707 /// through the `strip_and_classify_prefixed_kind` substrate to
1708 /// publish a `teardown-policy-<kind>` prefix family byte-for-byte
1709 /// symmetrical with the point surface's family via
1710 /// [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]. A
1711 /// future fifth [`TeardownPolicy`] variant added to `ALL` (a
1712 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
1713 /// reaches BOTH surfaces' `teardown-policy-<kind>` prefix families
1714 /// through the SAME closed-set walk with no per-caller edit — the
1715 /// two-surface symmetry means adding a variant on the closed set
1716 /// publishes it in lockstep across every downstream consumer.
1717 ///
1718 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1719 /// preserves proofs — the scalar-carrier presence-probe body lives
1720 /// at ONE substrate site per surface so every downstream
1721 /// (`teardown-policy-<kind>` require-tag families on both surfaces
1722 /// in tatara-check, closed-set audit dispatchers, future variant
1723 /// additions on [`TeardownPolicy`]) binds through the SAME
1724 /// `has(kind)` shape rather than restating the `<eph>.teardown ==
1725 /// kind` closure body at each call site). THEORY.md §VI.1
1726 /// (generation over composition — a future variant lands at ONE
1727 /// `ALL` entry + one `as_str` arm on the closed set and the probe
1728 /// picks it up mechanically without further per-consumer edits).
1729 #[must_use]
1730 pub fn has_teardown_policy(&self, kind: TeardownPolicy) -> bool {
1731 self.teardown == kind
1732 }
1733
1734 /// Derived-bool-predicate presence probe on the stored
1735 /// [`Self::teardown`] slot — `true` iff this ephemeral sugar's
1736 /// [`TeardownPolicy`] would auto-SIGTERM the Process on the
1737 /// queried [`ProcessPhase`] transition (as read through
1738 /// [`TeardownPolicy::should_teardown_on`]).
1739 ///
1740 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
1741 ///
1742 /// Same shape, same axis, one refinement lower: the point-surface
1743 /// peer on [`crate::lifetime::EphemeralLifetime`] composes the SAME
1744 /// [`TeardownPolicy::should_teardown_on`] predicate against the
1745 /// SAME stored `teardown_policy` slot; this method composes the
1746 /// same predicate against the sugar surface's flattened
1747 /// [`Self::teardown`] slot. Both bodies delegate to the ONE
1748 /// substrate owner [`TeardownPolicy::should_teardown_on`], so a
1749 /// regression at the (policy, phase) → bool truth table surfaces
1750 /// at THAT primitive's tests rather than as silent drift at
1751 /// either struct-level caller.
1752 ///
1753 /// # Corner — (required-scalar-parent × derived-bool-predicate-child)
1754 ///
1755 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
1756 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
1757 /// Option-parent hop between the sugar struct and the `teardown`
1758 /// scalar (the point surface reaches
1759 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
1760 /// through the Option-parent `resolved_ephemeral()` gate). The
1761 /// probe body is a bare predicate application on a required
1762 /// field. Distinct from [`Self::has_teardown_policy`] on this
1763 /// same surface, which reads the raw stored variant for equality
1764 /// (`self.teardown == kind`) rather than the derived firing-arm
1765 /// predicate against a [`ProcessPhase`] argument.
1766 ///
1767 /// # Compounding
1768 ///
1769 /// The ephemeral require-tag classifier composes this primitive
1770 /// with the closed-set [`crate::phase::ProcessPhase`]'s
1771 /// autoderived `FromStr` through the
1772 /// `strip_and_classify_prefixed_kind` substrate to publish a
1773 /// `teardown-fires-on-<phase>` prefix family byte-for-byte
1774 /// symmetrical with the point surface's family via
1775 /// [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`].
1776 /// A future fifth [`TeardownPolicy`] variant added to `ALL` (a
1777 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
1778 /// reaches BOTH surfaces' `teardown-fires-on-<phase>` prefix
1779 /// families through the SAME
1780 /// [`TeardownPolicy::should_teardown_on`] match with no per-
1781 /// caller edit — the two-surface symmetry means adding a variant
1782 /// on the closed set publishes it in lockstep across every
1783 /// downstream consumer.
1784 ///
1785 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1786 /// preserves proofs — the derived-bool-predicate presence-probe
1787 /// body lives at ONE substrate site per surface, both composing
1788 /// the SAME [`TeardownPolicy::should_teardown_on`] projection, so
1789 /// every downstream (`teardown-fires-on-<phase>` require-tag
1790 /// families on both surfaces in tatara-check, closed-set audit
1791 /// dispatchers, future variant additions on either
1792 /// [`TeardownPolicy`] or [`crate::phase::ProcessPhase`]) binds
1793 /// through the SAME `has_teardown_firing_on(phase)` shape rather
1794 /// than restating the `<eph>.teardown.should_teardown_on(phase)`
1795 /// closure body at each call site). THEORY.md §VI.1 (generation
1796 /// over composition — a future variant lands at ONE `ALL` entry +
1797 /// one `as_str` arm + one `should_teardown_on` arm on the closed
1798 /// set and the probe picks it up mechanically without further
1799 /// per-consumer edits).
1800 #[must_use]
1801 pub const fn has_teardown_firing_on(&self, phase: ProcessPhase) -> bool {
1802 self.teardown.should_teardown_on(phase)
1803 }
1804
1805 /// Resolve the operator-authored [`Self::classification`] slot to
1806 /// the concrete [`Classification`] the point surface sees, filling
1807 /// `None` through the same [`default_ephemeral_class`] baseline the
1808 /// `From<EphemeralSpec> for ProcessSpec` lowering uses when the
1809 /// operator omits `:classification` from the `(defephemeral …)`
1810 /// form. Returns [`Cow::Borrowed`] on the populated arm (zero
1811 /// allocation), else [`Cow::Owned`] with the workspace-baseline
1812 /// `(Gate, Compute, Bounded, Monotone, Internal)` value the sibling
1813 /// primitive [`Classification::gate_compute`] owns.
1814 ///
1815 /// # ONE substrate primitive for `Option<Classification>` resolution
1816 ///
1817 /// This is the ONE `EphemeralSpec`-inherent primitive that owns the
1818 /// `Option<Classification>` → resolved-[`Classification`] walk.
1819 /// Every downstream classification-axis presence probe on the
1820 /// [`EphemeralSpec`] surface ([`Self::has_point_type`],
1821 /// [`Self::has_substrate`], [`Self::has_calm`],
1822 /// [`Self::has_data_classification`], [`Self::has_horizon_kind`],
1823 /// [`Self::has_optimization_direction`], [`Self::has_input_arity`],
1824 /// [`Self::has_output_arity`]) routes through THIS
1825 /// primitive so the "`None` fills through
1826 /// [`default_ephemeral_class`]" resolution lives at ONE site rather
1827 /// than being restated in each per-axis probe body. A future
1828 /// regression on the fill-through (a shift from the `(Gate,
1829 /// Compute, …)` baseline to a different `default_ephemeral_class`
1830 /// body, a shift from the `Option`-carrier shape to a
1831 /// serde-defaulted required-field carrier, an eventual audit hook
1832 /// naming the resolved-vs-authored provenance) lands at ONE site
1833 /// and every downstream axis-probe on the ephemeral surface picks
1834 /// it up mechanically.
1835 ///
1836 /// # Sibling to the `From<EphemeralSpec>` lowering
1837 ///
1838 /// The lowering `From<EphemeralSpec> for ProcessSpec` fills
1839 /// [`ProcessSpec::classification`] through the SAME
1840 /// `.unwrap_or_else(default_ephemeral_class)` walk that this
1841 /// primitive owns on the borrow-friendly `Cow` return. Both sites
1842 /// resolve the same operator-authored slot through the same default
1843 /// so a future two-surface parity contract on the classification
1844 /// axes (`point-type-<kind>` on both surfaces, `substrate-<kind>`
1845 /// on both surfaces, …) reads identically through the sibling
1846 /// point-surface probe [`Classification::has_<axis>`] on the
1847 /// lowered `ProcessSpec` and through THIS primitive on the same
1848 /// authored [`EphemeralSpec`].
1849 ///
1850 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1851 /// preserves proofs; the `Option<Classification>` resolution body
1852 /// lives at ONE substrate primitive on the ephemeral surface so
1853 /// every downstream classification-axis probe binds through the
1854 /// SAME `resolved_classification()` shape rather than restating
1855 /// the `self.classification.as_ref().unwrap_or(&default_…)`
1856 /// closure body at each callsite. THEORY.md §VI.1 — generation
1857 /// over composition; a future classification-axis peer
1858 /// (`has_substrate`, `has_calm`, …) lands as ONE inherent method
1859 /// that delegates through the resolver's `has_<axis>(kind)` call
1860 /// on the sibling [`Classification`] closed-set primitive with no
1861 /// per-axis restatement of the fill-through logic.
1862 #[must_use]
1863 pub fn resolved_classification(&self) -> Cow<'_, Classification> {
1864 match &self.classification {
1865 Some(c) => Cow::Borrowed(c),
1866 None => Cow::Owned(default_ephemeral_class()),
1867 }
1868 }
1869
1870 /// Overlay a single [`ClassificationAxis`] variant onto this
1871 /// ephemeral spec's authored [`Self::classification`] slot, filling
1872 /// `None` through [`Classification::gate_compute`] before the
1873 /// overlay so the resulting slot carries `Some(_)` regardless of
1874 /// the pre-call state. Fluent chaining primitive: the peer of
1875 /// [`ProcessSpec::gate_compute_with_axis`] (fresh-spec × axis
1876 /// overlay) and [`Classification::with_axis`] (arbitrary-base ×
1877 /// axis overlay) on the ephemeral sugar surface.
1878 ///
1879 /// # Substrate ergonomics
1880 ///
1881 /// Pre-lift the four-line shape `let mut classification =
1882 /// Classification::gate_compute(); classification.<axis> =
1883 /// populated; let spec = EphemeralSpec { classification:
1884 /// Some(classification), ..ephemeral_fixture() };` (and its newer
1885 /// three-line peer `let classification =
1886 /// Classification::gate_compute_with_axis(populated); let spec =
1887 /// EphemeralSpec { classification: Some(classification),
1888 /// ..ephemeral_fixture() };`) recurred at THIRTY-SIX hand-authored
1889 /// callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger
1890 /// inside `tatara-reconciler::bin::tatara-check`'s
1891 /// `evaluate_ephemeral_require_tag_*` classifier-facing test
1892 /// module. Post-lift each callsite reads
1893 /// `let spec = ephemeral_fixture().with_classification_axis(populated);`
1894 /// — one line, one immutable binding, and every per-axis loop
1895 /// dispatches its per-iteration axis mutation through the SAME
1896 /// [`ClassificationAxis::overlay`] trait rather than by directly
1897 /// poking a `classification.<axis>` field or restating the
1898 /// `Some(_)` wrap.
1899 ///
1900 /// # Fluent chaining semantics
1901 ///
1902 /// * `EphemeralSpec { classification: None, .. }
1903 /// .with_classification_axis(axis)` produces
1904 /// `EphemeralSpec { classification:
1905 /// Some(Classification::gate_compute_with_axis(axis)), .. }` —
1906 /// the `None`-arm short-circuit fills through
1907 /// [`Classification::gate_compute`] identically to the sibling
1908 /// [`Self::resolved_classification`] resolver on the read side.
1909 /// * `EphemeralSpec { classification: Some(prior), .. }
1910 /// .with_classification_axis(axis)` produces
1911 /// `EphemeralSpec { classification: Some(prior.with_axis(axis)),
1912 /// .. }` — the axis overlay composes onto the existing carrier
1913 /// via [`ClassificationAxis::overlay`], preserving every other
1914 /// axis slot on `prior`. Chained calls
1915 /// `.with_classification_axis(a).with_classification_axis(b)`
1916 /// compose arbitrary N-axis conjunctions on the ephemeral
1917 /// sugar surface with the same order-independence guarantee
1918 /// [`Classification::with_axis`] carries on distinct-slot axes.
1919 ///
1920 /// # Sibling to [`ProcessSpec::gate_compute_with_axis`]
1921 ///
1922 /// Same (spec-carrier × axis) shape, one refinement lower on
1923 /// the composition-depth axis: `ProcessSpec::gate_compute_with_axis`
1924 /// owns the (fresh-`gate_compute_defaults`-spec × axis-overlay)
1925 /// construction on the point-surface carrier;
1926 /// [`Self::with_classification_axis`] owns the
1927 /// (arbitrary-`EphemeralSpec` × axis-overlay-onto-authored-classification)
1928 /// construction on the ephemeral sugar-surface carrier. Both
1929 /// primitives compose through the SAME
1930 /// [`ClassificationAxis::overlay`] trait so a regression on any
1931 /// axis's overlay surfaces at both composer owners' pin sets
1932 /// simultaneously.
1933 ///
1934 /// # Compounding
1935 ///
1936 /// A future SIXTH classification axis lands as ONE peer
1937 /// `impl ClassificationAxis` — every ephemeral-surface fixture
1938 /// that binds through this primitive picks up the sixth axis
1939 /// mechanically without a `classification.<new-axis> = value;`
1940 /// restatement per site. A future audit dispatcher walking the
1941 /// (ephemeral-surface × axis-loop) shape (per-axis matrix
1942 /// generator, closed-set-sweep sagas, per-axis-XOR-partition-
1943 /// witness synthesis on the ephemeral side) binds through the
1944 /// SAME composer regardless of which axis it targets. Directly
1945 /// benefits the P1 caixa-tatara renderer target
1946 /// (`(defaplicacao …)` → `Process` mechanical lowering test
1947 /// fixtures that construct authored classifications through the
1948 /// ephemeral sugar surface) and future ephemeral-surface XOR-
1949 /// partition landmark tests peer to the point-surface pins in
1950 /// `tatara-check.rs`.
1951 ///
1952 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1953 /// preserves proofs; the [`ClassificationAxis::overlay`] trait
1954 /// owns the axis-dispatch proof at ONE site and this primitive
1955 /// extends the ONE-site guarantee to the (ephemeral-spec ×
1956 /// authored-classification × axis-overlay) construction shape.
1957 /// THEORY.md §VI.1 — generation over composition; the 3-to-4-line
1958 /// hand-authored classification-then-wrap shape recurred at ≥ 36
1959 /// hand-authored callsites past the ★★ PRIME-DIRECTIVE ≥ 2
1960 /// duplication threshold and is lifted onto ONE substrate owner
1961 /// here.
1962 #[must_use]
1963 pub fn with_classification_axis<A: ClassificationAxis>(mut self, axis: A) -> Self {
1964 let mut c = self
1965 .classification
1966 .take()
1967 .unwrap_or_else(Classification::gate_compute);
1968 axis.overlay(&mut c);
1969 self.classification = Some(c);
1970 self
1971 }
1972
1973 /// True iff the resolved [`Classification`] carries the given
1974 /// [`ConvergencePointType`] on its `point_type` slot — byte-for-
1975 /// byte peer of [`Classification::has_point_type`] wrapped through
1976 /// the [`Self::resolved_classification`] resolver so an
1977 /// operator-omitted `:classification` slot reads as the
1978 /// [`default_ephemeral_class`] baseline the sibling
1979 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
1980 ///
1981 /// # Two-surface parity contract
1982 ///
1983 /// A given [`EphemeralSpec`] classifies identically through this
1984 /// primitive AND through
1985 /// `<eph.clone().into::<ProcessSpec>>().classification.has_point_type(kind)`
1986 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
1987 /// resolver on this side and the `.unwrap_or_else(...)` fill on
1988 /// the lowering side both dereference the same
1989 /// `default_ephemeral_class()` value on `None` and the same
1990 /// authored value on `Some(_)`. This means the ephemeral-surface
1991 /// `point-type-<kind>` `:requires` family in
1992 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
1993 /// truth on the SAME authored spec as the point-surface family
1994 /// on the mechanically-lowered `ProcessSpec`.
1995 ///
1996 /// # Sibling to the seven other classification axes
1997 ///
1998 /// FIRST classification-axis peer on the [`EphemeralSpec`]
1999 /// surface. Six future sibling axes on the SAME `Cow`-resolver
2000 /// carrier ([`Self::has_substrate`] opened the SECOND,
2001 /// [`Self::has_calm`] the THIRD,
2002 /// [`Self::has_data_classification`] the FOURTH,
2003 /// [`Self::has_horizon_kind`] the FIFTH,
2004 /// [`Self::has_optimization_direction`] the SIXTH; then
2005 /// `has_input_arity`, `has_output_arity`) land as one-line
2006 /// wrappers around the SAME resolver + the sibling
2007 /// [`Classification`] closed-set primitive, so a future variant
2008 /// added to [`ConvergencePointType`] (or any of the seven other
2009 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2010 /// families through the SAME closed-set walk with no per-caller
2011 /// edit.
2012 ///
2013 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2014 /// preserves proofs; the classification-axis presence-probe body
2015 /// composes ONE resolver primitive
2016 /// ([`Self::resolved_classification`]) with ONE closed-set
2017 /// primitive ([`Classification::has_point_type`]) so every
2018 /// downstream (`point-type-<kind>` require-tag families on both
2019 /// surfaces in tatara-check, closed-set audit dispatchers, future
2020 /// variant additions on [`ConvergencePointType`]) binds through
2021 /// the SAME `has(kind)` shape rather than restating either the
2022 /// resolver walk or the closed-set equality at the callsite.
2023 #[must_use]
2024 pub fn has_point_type(&self, kind: ConvergencePointType) -> bool {
2025 self.resolved_classification().has_point_type(kind)
2026 }
2027
2028 /// True iff the resolved [`Classification`] carries the given
2029 /// [`SubstrateType`] on its `substrate` slot — byte-for-byte peer
2030 /// of [`Classification::has_substrate`] wrapped through the
2031 /// [`Self::resolved_classification`] resolver so an operator-
2032 /// omitted `:classification` slot reads as the
2033 /// [`default_ephemeral_class`] baseline the sibling
2034 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2035 ///
2036 /// # Two-surface parity contract
2037 ///
2038 /// A given [`EphemeralSpec`] classifies identically through this
2039 /// primitive AND through
2040 /// `<eph.clone().into::<ProcessSpec>>().classification.has_substrate(kind)`
2041 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2042 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2043 /// the lowering side both dereference the same
2044 /// `default_ephemeral_class()` value on `None` and the same
2045 /// authored value on `Some(_)`. This means the ephemeral-surface
2046 /// `substrate-<kind>` `:requires` family in
2047 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2048 /// truth on the SAME authored spec as the point-surface family
2049 /// on the mechanically-lowered `ProcessSpec`.
2050 ///
2051 /// # SECOND classification-axis peer on the ephemeral surface
2052 ///
2053 /// Peer of [`Self::has_point_type`] — both route through the SAME
2054 /// [`Self::resolved_classification`] resolver, so the operator-
2055 /// omitted `:classification` slot's fill-through logic lives at
2056 /// ONE substrate primitive rather than being restated in each
2057 /// per-axis probe body. Five future sibling axes on the SAME
2058 /// `Cow`-resolver carrier ([`Self::has_calm`] opened the THIRD,
2059 /// [`Self::has_data_classification`] the FOURTH,
2060 /// [`Self::has_horizon_kind`] the FIFTH,
2061 /// [`Self::has_optimization_direction`] the SIXTH; then
2062 /// `has_input_arity`, `has_output_arity`) land as one-line
2063 /// wrappers around the SAME resolver + the sibling
2064 /// [`Classification`] closed-set primitive, so a future variant
2065 /// added to [`SubstrateType`] (or any of the six other closed
2066 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
2067 /// through the SAME closed-set walk with no per-caller edit.
2068 ///
2069 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2070 /// preserves proofs; the classification-axis presence-probe body
2071 /// composes ONE resolver primitive
2072 /// ([`Self::resolved_classification`]) with ONE closed-set
2073 /// primitive ([`Classification::has_substrate`]) so every
2074 /// downstream (`substrate-<kind>` require-tag families on both
2075 /// surfaces in tatara-check, closed-set audit dispatchers, future
2076 /// variant additions on [`SubstrateType`]) binds through the
2077 /// SAME `has(kind)` shape rather than restating either the
2078 /// resolver walk or the closed-set equality at the callsite.
2079 #[must_use]
2080 pub fn has_substrate(&self, kind: SubstrateType) -> bool {
2081 self.resolved_classification().has_substrate(kind)
2082 }
2083
2084 /// True iff the resolved [`Classification`] carries the given
2085 /// [`CalmClassification`] on its `calm` slot — byte-for-byte peer
2086 /// of [`Classification::has_calm`] wrapped through the
2087 /// [`Self::resolved_classification`] resolver so an operator-
2088 /// omitted `:classification` slot reads as the
2089 /// [`default_ephemeral_class`] baseline the sibling
2090 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2091 ///
2092 /// # Two-surface parity contract
2093 ///
2094 /// A given [`EphemeralSpec`] classifies identically through this
2095 /// primitive AND through
2096 /// `<eph.clone().into::<ProcessSpec>>().classification.has_calm(kind)`
2097 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2098 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2099 /// the lowering side both dereference the same
2100 /// `default_ephemeral_class()` value on `None` and the same
2101 /// authored value on `Some(_)`. This means the ephemeral-surface
2102 /// `calm-<kind>` `:requires` family in
2103 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2104 /// truth on the SAME authored spec as the point-surface family
2105 /// on the mechanically-lowered `ProcessSpec`.
2106 ///
2107 /// # THIRD classification-axis peer on the ephemeral surface
2108 ///
2109 /// Peer of [`Self::has_point_type`] and [`Self::has_substrate`] —
2110 /// all three route through the SAME
2111 /// [`Self::resolved_classification`] resolver, so the operator-
2112 /// omitted `:classification` slot's fill-through logic lives at
2113 /// ONE substrate primitive rather than being restated in each
2114 /// per-axis probe body. FIRST occupant on the (Option-parent ×
2115 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
2116 /// of the ephemeral-surface presence-probe algebra — distinct
2117 /// from the (Option-parent × NON-DEFAULT-scalar-child) corner
2118 /// the first two classification-axis peers opened, since
2119 /// [`CalmClassification`] carries `#[default] = Monotone` on the
2120 /// closed set. The default-arm short-circuit on the absent-
2121 /// classification arm reads `true` on the [`CalmClassification`]
2122 /// child's `#[default]` variant precisely because BOTH the parent
2123 /// Option's fill-through baseline (`default_ephemeral_class`) AND
2124 /// the child's own `#[default]` land on the SAME variant
2125 /// ([`CalmClassification::Monotone`]) — a two-defaults
2126 /// composition property distinct from the NON-DEFAULT-scalar
2127 /// peers, whose absent-classification arm defaults through a
2128 /// specific chosen baseline (`ConvergencePointType::Gate`,
2129 /// `SubstrateType::Compute`) rather than through the child's own
2130 /// `#[default]`. Four future sibling axes on the SAME
2131 /// `Cow`-resolver carrier ([`Self::has_data_classification`]
2132 /// opened the FOURTH, [`Self::has_horizon_kind`] the FIFTH,
2133 /// [`Self::has_optimization_direction`] the SIXTH; then
2134 /// `has_input_arity`, `has_output_arity`) land as one-line
2135 /// wrappers around the SAME resolver + the sibling
2136 /// [`Classification`] closed-set primitive, so a future variant
2137 /// added to [`CalmClassification`] (or any of the five other
2138 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2139 /// families through the SAME closed-set walk with no per-caller
2140 /// edit.
2141 ///
2142 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2143 /// preserves proofs; the classification-axis presence-probe body
2144 /// composes ONE resolver primitive
2145 /// ([`Self::resolved_classification`]) with ONE closed-set
2146 /// primitive ([`Classification::has_calm`]) so every downstream
2147 /// (`calm-<kind>` require-tag families on both surfaces in
2148 /// tatara-check, closed-set audit dispatchers, future variant
2149 /// additions on [`CalmClassification`]) binds through the SAME
2150 /// `has(kind)` shape rather than restating either the resolver
2151 /// walk or the closed-set equality at the callsite.
2152 #[must_use]
2153 pub fn has_calm(&self, kind: CalmClassification) -> bool {
2154 self.resolved_classification().has_calm(kind)
2155 }
2156
2157 /// True iff the resolved [`Classification`] carries the given
2158 /// [`DataClassification`] on its `data_classification` slot —
2159 /// byte-for-byte peer of [`Classification::has_data_classification`]
2160 /// wrapped through the [`Self::resolved_classification`] resolver
2161 /// so an operator-omitted `:classification` slot reads as the
2162 /// [`default_ephemeral_class`] baseline the sibling
2163 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2164 ///
2165 /// # Two-surface parity contract
2166 ///
2167 /// A given [`EphemeralSpec`] classifies identically through this
2168 /// primitive AND through
2169 /// `<eph.clone().into::<ProcessSpec>>().classification.has_data_classification(kind)`
2170 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2171 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2172 /// the lowering side both dereference the same
2173 /// `default_ephemeral_class()` value on `None` and the same
2174 /// authored value on `Some(_)`. This means the ephemeral-surface
2175 /// `data-classification-<kind>` `:requires` family in
2176 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2177 /// truth on the SAME authored spec as the point-surface family
2178 /// on the mechanically-lowered `ProcessSpec`.
2179 ///
2180 /// # FOURTH classification-axis peer on the ephemeral surface
2181 ///
2182 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`], and
2183 /// [`Self::has_calm`] — all four route through the SAME
2184 /// [`Self::resolved_classification`] resolver, so the operator-
2185 /// omitted `:classification` slot's fill-through logic lives at
2186 /// ONE substrate primitive rather than being restated in each
2187 /// per-axis probe body. SECOND occupant on the (Option-parent ×
2188 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
2189 /// of the ephemeral-surface presence-probe algebra alongside
2190 /// [`Self::has_calm`] — both probe REQUIRED [`Classification`]
2191 /// sub-slots whose child closed set carries its own `#[default]`
2192 /// ([`DataClassification::Internal`] here,
2193 /// [`CalmClassification::Monotone`] on the peer), so the
2194 /// default-arm short-circuit on the absent-classification arm
2195 /// reads `true` on the [`DataClassification`] child's
2196 /// `#[default]` variant precisely because BOTH the parent
2197 /// Option's fill-through baseline (`default_ephemeral_class`)
2198 /// AND the child's own `#[default]` land on the SAME variant
2199 /// ([`DataClassification::Internal`]). The two-defaults
2200 /// composition property now walks TWO independent defaulted-
2201 /// scalar-child slots on the SAME ephemeral resolver — a
2202 /// regression that promoted a different [`DataClassification`]
2203 /// variant to `#[default]` (or wired the arm to a fixed variant
2204 /// answer) fails HERE at ONE narrow substrate site before
2205 /// drifting through every unadorned ephemeral spec's baseline
2206 /// data-classification answer. Distinct from the FIRST + SECOND
2207 /// peers on the (Option-parent × NON-DEFAULT-scalar-child)
2208 /// corner, whose absent-classification arm defaults through a
2209 /// specific chosen baseline (`ConvergencePointType::Gate`,
2210 /// `SubstrateType::Compute`) rather than through the child's own
2211 /// `#[default]`. Four future sibling axes on the SAME
2212 /// `Cow`-resolver carrier ([`Self::has_horizon_kind`] opened the
2213 /// FIFTH, [`Self::has_optimization_direction`] the SIXTH; then
2214 /// `has_input_arity`, `has_output_arity`) land as one-line
2215 /// wrappers around the SAME resolver + the sibling
2216 /// [`Classification`] closed-set primitive, so a future variant
2217 /// added to [`DataClassification`] (or any of the four other
2218 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2219 /// families through the SAME closed-set walk with no per-caller
2220 /// edit.
2221 ///
2222 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2223 /// preserves proofs; the classification-axis presence-probe body
2224 /// composes ONE resolver primitive
2225 /// ([`Self::resolved_classification`]) with ONE closed-set
2226 /// primitive ([`Classification::has_data_classification`]) so
2227 /// every downstream (`data-classification-<kind>` require-tag
2228 /// families on both surfaces in tatara-check, closed-set audit
2229 /// dispatchers, future variant additions on
2230 /// [`DataClassification`]) binds through the SAME `has(kind)`
2231 /// shape rather than restating either the resolver walk or the
2232 /// closed-set equality at the callsite.
2233 #[must_use]
2234 pub fn has_data_classification(&self, kind: DataClassification) -> bool {
2235 self.resolved_classification().has_data_classification(kind)
2236 }
2237
2238 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
2239 /// carries the given [`HorizonKind`] discriminator on its
2240 /// `horizon.kind` slot — byte-for-byte peer of
2241 /// [`Classification::has_horizon_kind`] wrapped through the
2242 /// [`Self::resolved_classification`] resolver so an operator-
2243 /// omitted `:classification` slot reads as the
2244 /// [`default_ephemeral_class`] baseline the sibling
2245 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2246 ///
2247 /// # Two-surface parity contract
2248 ///
2249 /// A given [`EphemeralSpec`] classifies identically through this
2250 /// primitive AND through
2251 /// `<eph.clone().into::<ProcessSpec>>().classification.has_horizon_kind(kind)`
2252 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2253 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2254 /// the lowering side both dereference the same
2255 /// `default_ephemeral_class()` value on `None` and the same
2256 /// authored value on `Some(_)`. This means the ephemeral-surface
2257 /// `horizon-<kind>` `:requires` family in
2258 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
2259 /// truth on the SAME authored spec as the point-surface family
2260 /// on the mechanically-lowered `ProcessSpec`.
2261 ///
2262 /// # FIFTH classification-axis peer on the ephemeral surface
2263 ///
2264 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2265 /// [`Self::has_calm`], and [`Self::has_data_classification`] — all
2266 /// five route through the SAME [`Self::resolved_classification`]
2267 /// resolver, so the operator-omitted `:classification` slot's
2268 /// fill-through logic lives at ONE substrate primitive rather
2269 /// than being restated in each per-axis probe body. OPENS a fresh
2270 /// (Option-parent × NESTED-STRUCT-scalar-child ×
2271 /// operator-resolvable-baseline) corner on the ephemeral-surface
2272 /// presence-probe algebra — the four prior peers on this surface
2273 /// all read the closed-set discriminator DIRECTLY off a scalar
2274 /// [`Classification`] slot (`point_type`, `substrate`, `calm`,
2275 /// `data_classification`); this probe instead threads through a
2276 /// NESTED-STRUCT intermediary ([`Horizon`], the defaulted nested
2277 /// struct owning the `horizon` axis) to reach a scalar
2278 /// [`HorizonKind`] discriminator on `horizon.kind`. The
2279 /// default-arm short-circuit on the absent-classification arm
2280 /// reads `true` on the [`HorizonKind`] child's `#[default]`
2281 /// variant precisely because BOTH the parent Option's fill-
2282 /// through baseline ([`default_ephemeral_class`], which fills
2283 /// `horizon: Horizon::default()`) AND the child's own `#[default]`
2284 /// land on the SAME variant ([`HorizonKind::Bounded`]). A
2285 /// regression that dropped `#[default]` on [`HorizonKind`], or
2286 /// promoted `Asymptotic` to `#[default]`, or wired the arm to a
2287 /// fixed variant answer, or crossed the wires through the wrong
2288 /// nested struct fails HERE at ONE narrow substrate site before
2289 /// drifting through every unadorned ephemeral spec's baseline
2290 /// horizon answer. Distinct from the FIRST + SECOND peers on the
2291 /// (Option-parent × NON-DEFAULT-scalar-child) corner
2292 /// (`has_point_type`, `has_substrate`) whose absent-classification
2293 /// arm defaults through a specific chosen baseline
2294 /// (`ConvergencePointType::Gate`, `SubstrateType::Compute`), AND
2295 /// distinct from the THIRD + FOURTH peers on the (Option-parent ×
2296 /// DEFAULTED-scalar-child) corner (`has_calm`,
2297 /// `has_data_classification`) which reach a defaulted scalar
2298 /// DIRECTLY off the parent without a nested-struct hop. Three
2299 /// future sibling axes on the SAME `Cow`-resolver carrier
2300 /// ([`Self::has_optimization_direction`] opened the SIXTH; then
2301 /// `has_input_arity`, `has_output_arity`) land as one-line
2302 /// wrappers around the SAME resolver + the sibling
2303 /// [`Classification`] closed-set primitive, so a future variant
2304 /// added to [`HorizonKind`] (or any of the three other closed
2305 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
2306 /// through the SAME closed-set walk with no per-caller edit.
2307 ///
2308 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2309 /// preserves proofs; the classification-axis presence-probe body
2310 /// composes ONE resolver primitive
2311 /// ([`Self::resolved_classification`]) with ONE closed-set
2312 /// primitive ([`Classification::has_horizon_kind`]) so every
2313 /// downstream (`horizon-<kind>` require-tag families on both
2314 /// surfaces in tatara-check, closed-set audit dispatchers, future
2315 /// variant additions on [`HorizonKind`]) binds through the SAME
2316 /// `has(kind)` shape rather than restating either the resolver
2317 /// walk or the closed-set equality at the callsite.
2318 #[must_use]
2319 pub fn has_horizon_kind(&self, kind: HorizonKind) -> bool {
2320 self.resolved_classification().has_horizon_kind(kind)
2321 }
2322
2323 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
2324 /// carries the given [`OptimizationDirection`] discriminator on its
2325 /// `horizon.direction` slot (with the substrate
2326 /// `Option::unwrap_or_default` treating `None` as the closed set's
2327 /// `#[default] Minimize`) — byte-for-byte peer of
2328 /// [`Classification::has_optimization_direction`] wrapped through
2329 /// the [`Self::resolved_classification`] resolver so an operator-
2330 /// omitted `:classification` slot reads as the
2331 /// [`default_ephemeral_class`] baseline the sibling
2332 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
2333 ///
2334 /// # Two-surface parity contract
2335 ///
2336 /// A given [`EphemeralSpec`] classifies identically through this
2337 /// primitive AND through
2338 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
2339 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2340 /// resolver on this side and the `.unwrap_or_else(...)` fill on
2341 /// the lowering side both dereference the same
2342 /// `default_ephemeral_class()` value on `None` and the same
2343 /// authored value on `Some(_)`, and the sibling
2344 /// [`Classification::has_optimization_direction`] applies the same
2345 /// `Option::unwrap_or_default` collapse on the inner
2346 /// `horizon.direction` slot on both sides. This means the
2347 /// ephemeral-surface `optimization-direction-<kind>` `:requires`
2348 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2349 /// SAME truth on the SAME authored spec as the point-surface
2350 /// family on the mechanically-lowered `ProcessSpec`.
2351 ///
2352 /// # SIXTH classification-axis peer on the ephemeral surface
2353 ///
2354 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2355 /// [`Self::has_calm`], [`Self::has_data_classification`], and
2356 /// [`Self::has_horizon_kind`] — all six route through the SAME
2357 /// [`Self::resolved_classification`] resolver, so the operator-
2358 /// omitted `:classification` slot's fill-through logic lives at
2359 /// ONE substrate primitive rather than being restated in each per-
2360 /// axis probe body. SECOND occupant on the (Option-parent ×
2361 /// NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
2362 /// corner alongside [`Self::has_horizon_kind`] — both probes thread
2363 /// through the SAME nested [`Horizon`] intermediary to reach a
2364 /// scalar discriminator on the six-axis classification lattice, but
2365 /// this method additionally traverses an `Option`-slot with
2366 /// `unwrap_or_default` so a Process filled through
2367 /// [`crate::classification::Horizon::default`] (leaves `direction:
2368 /// None`) still reads `true` on the closed set's default arm
2369 /// ([`OptimizationDirection::Minimize`]). The corner therefore
2370 /// admits BOTH direct nested-scalar shapes ([`Self::has_horizon_kind`]
2371 /// walks `horizon.kind: HorizonKind` directly) AND Option-nested-
2372 /// scalar shapes (this method walks `horizon.direction:
2373 /// Option<OptimizationDirection>` through `unwrap_or_default`),
2374 /// pinning the corner as a proven-repeatable primitive shape on the
2375 /// ephemeral surface rather than a single-example curiosity. The
2376 /// two-defaults composition property (parent Option's fill-through
2377 /// baseline via `default_ephemeral_class` AND child's closed-set
2378 /// `#[default]` land on the SAME variant) reaches through TWO
2379 /// hops here: the parent Option's `.unwrap_or_else(default_…)`
2380 /// AND the inner Option's `.unwrap_or_default()` both dereference
2381 /// to the same [`OptimizationDirection::Minimize`] baseline the
2382 /// closed set publishes. A regression that flipped
2383 /// [`OptimizationDirection`]'s `#[default]` off `Minimize` (which
2384 /// would silently invert every unadorned `Asymptotic` Process's
2385 /// rate-window evaluator polarity), or that dropped the resolver
2386 /// hop, or that wired the arm to a fixed variant answer, fails
2387 /// HERE at ONE narrow substrate site before drifting through every
2388 /// unadorned ephemeral spec's baseline direction answer. Two future
2389 /// sibling axes on the SAME `Cow`-resolver carrier
2390 /// (`has_input_arity`, `has_output_arity`) land as one-line
2391 /// wrappers around the SAME resolver + the sibling
2392 /// [`Classification`] closed-set primitive, so a future variant
2393 /// added to [`OptimizationDirection`] (or any of the two other
2394 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2395 /// families through the SAME closed-set walk with no per-caller
2396 /// edit.
2397 ///
2398 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2399 /// preserves proofs; the classification-axis presence-probe body
2400 /// composes ONE resolver primitive
2401 /// ([`Self::resolved_classification`]) with ONE closed-set
2402 /// primitive ([`Classification::has_optimization_direction`]) so
2403 /// every downstream (`optimization-direction-<kind>` require-tag
2404 /// families on both surfaces in tatara-check, closed-set audit
2405 /// dispatchers, future variant additions on
2406 /// [`OptimizationDirection`]) binds through the SAME `has(kind)`
2407 /// shape rather than restating either the resolver walk or the
2408 /// closed-set equality plus the nested-struct-Option-hop at the
2409 /// callsite.
2410 #[must_use]
2411 pub fn has_optimization_direction(&self, kind: OptimizationDirection) -> bool {
2412 self.resolved_classification()
2413 .has_optimization_direction(kind)
2414 }
2415
2416 /// True iff the resolved [`Classification`]'s nested
2417 /// [`ConvergencePointType`] projects (via the many-to-one
2418 /// [`ConvergencePointType::input_arity`] typed projection) to the
2419 /// given [`Arity`] discriminator — byte-for-byte peer of
2420 /// [`Classification::has_input_arity`] wrapped through the
2421 /// [`Self::resolved_classification`] resolver so an operator-omitted
2422 /// `:classification` slot reads as the [`default_ephemeral_class`]
2423 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
2424 /// lowering fills.
2425 ///
2426 /// # Two-surface parity contract
2427 ///
2428 /// A given [`EphemeralSpec`] classifies identically through this
2429 /// primitive AND through
2430 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
2431 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2432 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
2433 /// lowering side both dereference the same
2434 /// `default_ephemeral_class()` value on `None` and the same
2435 /// authored value on `Some(_)`, and the sibling
2436 /// [`Classification::has_input_arity`] applies the same
2437 /// `point_type.input_arity()` typed projection on both sides. This
2438 /// means the ephemeral-surface `input-arity-<kind>` `:requires`
2439 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2440 /// SAME truth on the SAME authored spec as the point-surface family
2441 /// on the mechanically-lowered `ProcessSpec`.
2442 ///
2443 /// # SEVENTH classification-axis peer on the ephemeral surface — first via a derived-typed-projection
2444 ///
2445 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2446 /// [`Self::has_calm`], [`Self::has_data_classification`],
2447 /// [`Self::has_horizon_kind`], and
2448 /// [`Self::has_optimization_direction`] — all seven route through
2449 /// the SAME [`Self::resolved_classification`] resolver, so the
2450 /// operator-omitted `:classification` slot's fill-through logic
2451 /// lives at ONE substrate primitive rather than being restated in
2452 /// each per-axis probe body. FIRST occupant on the (Option-parent ×
2453 /// NESTED-STRUCT-scalar-child × derived-typed-projection) corner on
2454 /// the ephemeral surface — byte-for-byte symmetric with the
2455 /// derived-typed-projection precedent set by
2456 /// [`Classification::has_input_arity`] on the point surface: THAT
2457 /// peer routes through [`ConvergencePointType::input_arity`] on a
2458 /// required [`Classification`] carrier; THIS peer routes through the
2459 /// SAME projection on the `Cow`-resolver carrier so the resolver
2460 /// walk composes with the projection at ONE substrate site rather
2461 /// than being restated per surface. Distinct from the SIXTH peer
2462 /// [`Self::has_optimization_direction`] (which walks
2463 /// `horizon.direction` through an `Option::unwrap_or_default`
2464 /// collapse to reach a defaulted scalar child) and the FIFTH peer
2465 /// [`Self::has_horizon_kind`] (which walks `horizon.kind` DIRECTLY
2466 /// as a scalar without any typed-projection hop) on ONE dimension:
2467 /// this probe threads through the many-to-one closed-set typed
2468 /// projection [`ConvergencePointType::input_arity`] (`Transform |
2469 /// Fork | Broadcast | Observe → One`, `Join | Gate | Select |
2470 /// Reduce → Many`) so the child's closed set ([`Arity`]) is REACHED
2471 /// THROUGH a projection layer, not read raw off a scalar. The
2472 /// corner therefore admits three ephemeral-surface traversal
2473 /// shapes through the SAME `resolved_classification().<field>`
2474 /// walk: direct-nested-scalar
2475 /// ([`Self::has_horizon_kind`] reads `horizon.kind: HorizonKind`
2476 /// directly), Option-nested-scalar
2477 /// ([`Self::has_optimization_direction`] reads `horizon.direction:
2478 /// Option<OptimizationDirection>` through `unwrap_or_default`), and
2479 /// derived-typed-projection (this method reads
2480 /// `point_type.input_arity(): Arity` through a many-to-one
2481 /// projection). The co-tenant derived-typed-projection axis on the
2482 /// SAME `Cow`-resolver carrier ([`Self::has_output_arity`]) lands as
2483 /// a one-line wrapper around the SAME resolver + the sibling
2484 /// [`Classification`] closed-set primitive, so a future variant
2485 /// added to [`Arity`] or to [`ConvergencePointType`] reaches BOTH
2486 /// surfaces' `<axis>-<kind>` prefix families through the SAME
2487 /// closed-set walk with no per-caller edit.
2488 ///
2489 /// # Semantics — VARIANT match on the projected image
2490 ///
2491 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
2492 /// `#[default]`), so exactly ONE of the two arms answers `true` per
2493 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
2494 /// shortcut. The absent-`:classification` baseline
2495 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
2496 /// [`ConvergencePointType::input_arity`] projects `Gate → Many`, so
2497 /// the ephemeral sugar surface's `input-arity-Many` require-tag
2498 /// reads `true` on every operator-authored spec that omits the
2499 /// `:classification` slot — pinning the workspace's convergent-by-
2500 /// default point posture on the input side. The many-to-one
2501 /// projection shape means the answer is invariant under intra-
2502 /// bucket point-type swaps (`Transform ↔ Fork ↔ Broadcast ↔
2503 /// Observe` all keep `input-arity-One = true`) and flips at bucket
2504 /// boundaries (`Transform ↔ Join` flips `input-arity-One` from
2505 /// `true` to `false`). A regression that dropped the resolver hop,
2506 /// probed [`ConvergencePointType`] directly (dropping the
2507 /// `.input_arity()` call), inverted the projection (`One ↔ Many`),
2508 /// or crossed the wires with the sibling
2509 /// [`ConvergencePointType::output_arity`] projection fails HERE at
2510 /// ONE narrow substrate site before drifting through every
2511 /// unadorned ephemeral spec's baseline input-arity answer.
2512 ///
2513 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2514 /// preserves proofs; the classification-axis presence-probe body
2515 /// composes ONE resolver primitive
2516 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
2517 /// ([`Classification::has_input_arity`]) so every downstream
2518 /// (`input-arity-<kind>` require-tag families on both surfaces in
2519 /// tatara-check, closed-set audit dispatchers, future variant
2520 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
2521 /// through the SAME `has(kind)` shape rather than restating either
2522 /// the resolver walk or the closed-set equality plus the typed-
2523 /// projection hop at the callsite.
2524 #[must_use]
2525 pub fn has_input_arity(&self, kind: Arity) -> bool {
2526 self.resolved_classification().has_input_arity(kind)
2527 }
2528
2529 /// True iff the resolved [`Classification`]'s nested
2530 /// [`ConvergencePointType`] projects (via the many-to-one
2531 /// [`ConvergencePointType::output_arity`] typed projection) to the
2532 /// given [`Arity`] discriminator — byte-for-byte peer of
2533 /// [`Classification::has_output_arity`] wrapped through the
2534 /// [`Self::resolved_classification`] resolver so an operator-omitted
2535 /// `:classification` slot reads as the [`default_ephemeral_class`]
2536 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
2537 /// lowering fills.
2538 ///
2539 /// # Two-surface parity contract
2540 ///
2541 /// A given [`EphemeralSpec`] classifies identically through this
2542 /// primitive AND through
2543 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
2544 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2545 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
2546 /// lowering side both dereference the same
2547 /// `default_ephemeral_class()` value on `None` and the same
2548 /// authored value on `Some(_)`, and the sibling
2549 /// [`Classification::has_output_arity`] applies the same
2550 /// `point_type.output_arity()` typed projection on both sides. This
2551 /// means the ephemeral-surface `output-arity-<kind>` `:requires`
2552 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2553 /// SAME truth on the SAME authored spec as the point-surface family
2554 /// on the mechanically-lowered `ProcessSpec`.
2555 ///
2556 /// # EIGHTH classification-axis peer — closes the ephemeral-side DAG-composition arity pair
2557 ///
2558 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2559 /// [`Self::has_calm`], [`Self::has_data_classification`],
2560 /// [`Self::has_horizon_kind`], [`Self::has_optimization_direction`],
2561 /// and [`Self::has_input_arity`] — all eight route through the SAME
2562 /// [`Self::resolved_classification`] resolver, so the operator-
2563 /// omitted `:classification` slot's fill-through logic lives at ONE
2564 /// substrate primitive rather than being restated in each per-axis
2565 /// probe body. SECOND occupant on the (Option-parent × NESTED-
2566 /// STRUCT-scalar-child × derived-typed-projection) corner on the
2567 /// ephemeral surface — co-tenant with [`Self::has_input_arity`] on
2568 /// the SAME `point_type` scalar carrier through the SAME [`Arity`]
2569 /// closed set but through the sibling many-to-one typed projection
2570 /// [`ConvergencePointType::output_arity`] (`Transform | Join | Gate
2571 /// | Select | Reduce | Observe → One`, `Fork | Broadcast → Many`).
2572 /// Closes the DAG-composition arity pair on the ephemeral side —
2573 /// the two projections DISAGREE on the diffusive arms `Fork |
2574 /// Broadcast` (input `One` vs. output `Many`) and on the convergent
2575 /// arms `Join | Gate | Select | Reduce` (input `Many` vs. output
2576 /// `One`), and AGREE on the endomorphic arms `Transform | Observe`
2577 /// (both `One`). Byte-for-byte symmetric with the DAG-composition
2578 /// arity pair on the point surface ([`Classification::has_input_arity`] +
2579 /// [`Classification::has_output_arity`]) — THAT pair walks a required
2580 /// [`Classification`] carrier; THIS pair walks the SAME projection
2581 /// pair on the `Cow`-resolver carrier so the resolver walk composes
2582 /// with the projection at ONE substrate site rather than being
2583 /// restated per surface.
2584 ///
2585 /// # Semantics — VARIANT match on the projected image
2586 ///
2587 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
2588 /// `#[default]`), so exactly ONE of the two arms answers `true` per
2589 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
2590 /// shortcut. The absent-`:classification` baseline
2591 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
2592 /// [`ConvergencePointType::output_arity`] projects `Gate → One`, so
2593 /// the ephemeral sugar surface's `output-arity-One` require-tag
2594 /// reads `true` on every operator-authored spec that omits the
2595 /// `:classification` slot — pinning the workspace's convergent-by-
2596 /// default point posture on the output side. The many-to-one
2597 /// projection shape means the answer is invariant under intra-
2598 /// bucket point-type swaps (`Fork ↔ Broadcast` both keep
2599 /// `output-arity-Many = true`; `Transform ↔ Join ↔ Gate ↔ Select ↔
2600 /// Reduce ↔ Observe` all keep `output-arity-One = true`) and flips
2601 /// at bucket boundaries (`Fork ↔ Transform` flips `output-arity-
2602 /// Many` from `true` to `false`). A regression that dropped the
2603 /// resolver hop, probed [`ConvergencePointType`] directly (dropping
2604 /// the `.output_arity()` call), inverted the projection (`One ↔
2605 /// Many`), or crossed the wires with the sibling
2606 /// [`ConvergencePointType::input_arity`] projection fails HERE at
2607 /// ONE narrow substrate site before drifting through every
2608 /// unadorned ephemeral spec's baseline output-arity answer.
2609 ///
2610 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2611 /// preserves proofs; the classification-axis presence-probe body
2612 /// composes ONE resolver primitive
2613 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
2614 /// ([`Classification::has_output_arity`]) so every downstream
2615 /// (`output-arity-<kind>` require-tag families on both surfaces in
2616 /// tatara-check, closed-set audit dispatchers, future variant
2617 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
2618 /// through the SAME `has(kind)` shape rather than restating either
2619 /// the resolver walk or the closed-set equality plus the typed-
2620 /// projection hop at the callsite.
2621 #[must_use]
2622 pub fn has_output_arity(&self, kind: Arity) -> bool {
2623 self.resolved_classification().has_output_arity(kind)
2624 }
2625
2626 /// Derived-boolean predicate — does this ephemeral spec's
2627 /// resolved [`Classification`]'s [`Horizon`] project to `true`
2628 /// under [`crate::classification::HorizonKind::terminates`]?
2629 /// Byte-for-byte peer of
2630 /// [`Classification::horizon_terminates`] wrapped through the
2631 /// [`Self::resolved_classification`] resolver so an operator-
2632 /// omitted `:classification` slot on `(defephemeral …)` still
2633 /// answers via the substrate default. The ONE ephemeral-surface
2634 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2635 /// derived-nullary-boolean walk on the classification-horizon
2636 /// axis.
2637 ///
2638 /// # Two-surface parity — resolver hop + Classification primitive
2639 ///
2640 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2641 /// [`Self::has_calm`], [`Self::has_data_classification`],
2642 /// [`Self::has_horizon_kind`],
2643 /// [`Self::has_optimization_direction`],
2644 /// [`Self::has_input_arity`], and [`Self::has_output_arity`] on
2645 /// the (resolver-hop × [`Classification`] presence primitive)
2646 /// axis: all nine methods route through the SAME
2647 /// [`Self::resolved_classification`] resolver, and each composes
2648 /// against ONE [`Classification`] primitive. This method
2649 /// distinguishes itself by targeting the [`Classification`]
2650 /// primitive [`Classification::horizon_terminates`] which is the
2651 /// FIRST derived-nullary-boolean (no closed-set argument)
2652 /// primitive on the [`Classification`] surface — every prior
2653 /// peer probe on [`Classification`] admits a closed-set `kind`
2654 /// argument and answers a variant-equality question, while this
2655 /// probe collapses [`HorizonKind::ALL`] onto a single boolean
2656 /// via the closed set's own [`HorizonKind::terminates`]
2657 /// predicate.
2658 ///
2659 /// # Semantics — resolver hop + derived-nullary-boolean
2660 ///
2661 /// `horizon_terminates()` returns `true` iff
2662 /// `self.resolved_classification().horizon_terminates()`. The
2663 /// resolver returns the authored [`Classification`] when
2664 /// present and the substrate default
2665 /// [`Classification::gate_compute`] on absence. Because
2666 /// [`Classification::gate_compute`] uses [`Horizon::default`]
2667 /// (whose `kind` field defaults to [`HorizonKind::Bounded`] via
2668 /// `#[default]`), a bare ephemeral spec with no `:classification`
2669 /// slot answers `true` — the default-arm short-circuit
2670 /// propagates through THREE layers of `Default`
2671 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
2672 /// [`HorizonKind::default`]) to this predicate's answer, matching
2673 /// the default-arm shortcut every prior defaulted-child probe
2674 /// on this surface publishes. A regression that dropped the
2675 /// resolver hop, probed [`Classification::has_horizon_kind`]
2676 /// directly (dropping the `.terminates()` projection), or
2677 /// crossed the wires with the antisymmetric partner
2678 /// [`HorizonKind::requires_metric_axes`] fails HERE at ONE
2679 /// narrow substrate site before drifting through every
2680 /// unadorned ephemeral spec's baseline horizon-terminates
2681 /// answer.
2682 ///
2683 /// # Compounding
2684 ///
2685 /// The ephemeral require-tag classifier composes this primitive
2686 /// as a fixed tag `terminating-horizon` on
2687 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2688 /// surface's `terminating-horizon` fixed tag on
2689 /// `POINT_FIXED_TAG_ARMS` via [`Classification::horizon_terminates`]
2690 /// directly. The two-surface parity contract holds by
2691 /// construction: both surfaces route through the SAME
2692 /// [`Classification::horizon_terminates`] primitive after the
2693 /// ephemeral surface pays ONE resolver hop — a future
2694 /// [`HorizonKind`] variant or a future normalization at the
2695 /// substrate primitive lands at ONE site and both surfaces'
2696 /// `terminating-horizon` fixed tags inherit the shift
2697 /// mechanically. A future co-tenant peer on this surface (a
2698 /// hypothetical `horizon_requires_metric_axes` composing the
2699 /// antisymmetric partner [`HorizonKind::requires_metric_axes`]
2700 /// through the SAME resolver hop) lands as ONE peer inherent
2701 /// method with the same nullary-derived body.
2702 ///
2703 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2704 /// preserves proofs; the classification-axis derived-nullary-
2705 /// boolean probe body composes ONE resolver primitive
2706 /// ([`Self::resolved_classification`]) with ONE
2707 /// [`Classification`] primitive
2708 /// ([`Classification::horizon_terminates`]) so every downstream
2709 /// (`terminating-horizon` fixed tags on both surfaces in
2710 /// tatara-check, future scheduler / termination-shape
2711 /// validators, future variant additions on [`HorizonKind`])
2712 /// binds through the SAME `horizon_terminates()` shape rather
2713 /// than restating either the resolver walk or the closed-set
2714 /// projection composition at the callsite. THEORY.md §VI.1 —
2715 /// generation over composition; a future [`HorizonKind`]
2716 /// variant lands at ONE `ALL` entry + ONE `terminates` arm on
2717 /// the closed set and both surfaces pick it up mechanically.
2718 #[must_use]
2719 pub fn horizon_terminates(&self) -> bool {
2720 self.resolved_classification().horizon_terminates()
2721 }
2722
2723 /// Derived-boolean predicate — does this ephemeral spec's
2724 /// resolved [`Classification`]'s [`Horizon`] project to `true`
2725 /// under [`crate::classification::HorizonKind::requires_metric_axes`]?
2726 /// Byte-for-byte peer of
2727 /// [`Classification::horizon_requires_metric_axes`] wrapped
2728 /// through the [`Self::resolved_classification`] resolver so an
2729 /// operator-omitted `:classification` slot on `(defephemeral …)`
2730 /// still answers via the substrate default. The ONE ephemeral-
2731 /// surface substrate primitive that owns the
2732 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on
2733 /// the metric-axes-required question over the classification-
2734 /// horizon axis.
2735 ///
2736 /// # Antisymmetric peer of [`Self::horizon_terminates`]
2737 ///
2738 /// Byte-for-byte antisymmetric peer of [`Self::horizon_terminates`]
2739 /// via the SAME [`Self::resolved_classification`] resolver hop
2740 /// and the SAME closed set [`crate::classification::HorizonKind`]:
2741 /// [`Self::horizon_terminates`] composes
2742 /// [`Classification::horizon_terminates`] (walking
2743 /// [`crate::classification::HorizonKind::terminates`]); this
2744 /// method composes the ANTISYMMETRIC partner
2745 /// [`Classification::horizon_requires_metric_axes`] (walking
2746 /// [`crate::classification::HorizonKind::requires_metric_axes`]).
2747 /// The closed set pins the XOR contract
2748 /// `terminates() ^ requires_metric_axes()` on every variant, so
2749 /// exactly ONE of these two ephemeral-surface derived-nullary
2750 /// probes answers `true` per resolved [`Classification`] and the
2751 /// two probes together partition the resolver's output space into
2752 /// two disjoint buckets on every ephemeral spec — authored or
2753 /// defaulted.
2754 ///
2755 /// # Semantics — resolver hop + derived-nullary-boolean
2756 ///
2757 /// `horizon_requires_metric_axes()` returns `true` iff
2758 /// `self.resolved_classification().horizon_requires_metric_axes()`.
2759 /// The resolver returns the authored [`Classification`] when
2760 /// present and the substrate default
2761 /// [`Classification::gate_compute`] on absence. Because
2762 /// [`Classification::gate_compute`] uses [`Horizon::default`]
2763 /// (whose `kind` field defaults to
2764 /// [`crate::classification::HorizonKind::Bounded`] via
2765 /// `#[default]`), a bare ephemeral spec with no `:classification`
2766 /// slot answers `false` — the default-arm short-circuit
2767 /// propagates through THREE layers of `Default`
2768 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
2769 /// [`crate::classification::HorizonKind::default`]) to this
2770 /// predicate's answer, the mirror image of
2771 /// [`Self::horizon_terminates`]'s default-arm `true` answer. A
2772 /// regression that dropped the resolver hop, probed
2773 /// [`Classification::has_horizon_kind`] directly (dropping the
2774 /// `.requires_metric_axes()` projection), or crossed the wires
2775 /// with the antisymmetric partner
2776 /// [`crate::classification::HorizonKind::terminates`] fails HERE
2777 /// at ONE narrow substrate site before drifting through every
2778 /// unadorned ephemeral spec's baseline metric-provisioning
2779 /// answer.
2780 ///
2781 /// # Compounding
2782 ///
2783 /// The ephemeral require-tag classifier composes this primitive
2784 /// as a fixed tag `metric-axes-required` on
2785 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2786 /// surface's `metric-axes-required` fixed tag on
2787 /// `POINT_FIXED_TAG_ARMS` via
2788 /// [`Classification::horizon_requires_metric_axes`] directly. The
2789 /// two-surface parity contract holds by construction: both
2790 /// surfaces route through the SAME
2791 /// [`Classification::horizon_requires_metric_axes`] primitive
2792 /// after the ephemeral surface pays ONE resolver hop — a future
2793 /// [`crate::classification::HorizonKind`] variant or a future
2794 /// normalization at the substrate primitive lands at ONE site and
2795 /// both surfaces' `metric-axes-required` fixed tags inherit the
2796 /// shift mechanically.
2797 ///
2798 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2799 /// preserves proofs; the classification-axis derived-nullary-
2800 /// boolean probe body composes ONE resolver primitive
2801 /// ([`Self::resolved_classification`]) with ONE
2802 /// [`Classification`] primitive
2803 /// ([`Classification::horizon_requires_metric_axes`]) so every
2804 /// downstream (`metric-axes-required` fixed tags on both
2805 /// surfaces in tatara-check, future scheduler / metric-
2806 /// provisioning validators, future variant additions on
2807 /// [`crate::classification::HorizonKind`]) binds through the
2808 /// SAME `horizon_requires_metric_axes()` shape rather than
2809 /// restating either the resolver walk or the closed-set
2810 /// projection composition at the callsite. THEORY.md §VI.1 —
2811 /// generation over composition; a future
2812 /// [`crate::classification::HorizonKind`] variant lands at ONE
2813 /// `ALL` entry + ONE `requires_metric_axes` arm on the closed
2814 /// set and both surfaces pick it up mechanically.
2815 #[must_use]
2816 pub fn horizon_requires_metric_axes(&self) -> bool {
2817 self.resolved_classification()
2818 .horizon_requires_metric_axes()
2819 }
2820
2821 /// Derived-boolean predicate — does this ephemeral spec's
2822 /// resolved [`Classification`]'s [`crate::classification::CalmClassification`]
2823 /// project to `true` under
2824 /// [`crate::classification::CalmClassification::requires_coordination`]?
2825 /// Byte-for-byte peer of
2826 /// [`Classification::calm_requires_coordination`] wrapped through
2827 /// the [`Self::resolved_classification`] resolver so an operator-
2828 /// omitted `:classification` slot on `(defephemeral …)` still
2829 /// answers via the substrate default. The ONE ephemeral-surface
2830 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2831 /// derived-nullary-boolean walk on the coordination-required
2832 /// question over the classification-calm axis.
2833 ///
2834 /// # Third derived-nullary-boolean peer on the ephemeral surface
2835 ///
2836 /// Peer of [`Self::horizon_terminates`] and
2837 /// [`Self::horizon_requires_metric_axes`] on the ephemeral
2838 /// surface's (resolver-hop × derived-nullary-bool) shape — the
2839 /// FIRST peer threading the classification-calm axis rather than
2840 /// the classification-horizon axis. Distinct from both prior
2841 /// derived-nullary peers by ONE structural degree at the underlying
2842 /// [`Classification`] primitive: [`Self::horizon_terminates`] +
2843 /// [`Self::horizon_requires_metric_axes`] both walk the nested
2844 /// `.horizon.kind` sub-slot's derived projection, while this probe
2845 /// walks the direct scalar `.calm` field's derived projection.
2846 /// The resolver-hop shape is byte-identical.
2847 ///
2848 /// # Semantics — resolver hop + derived-nullary-boolean
2849 ///
2850 /// `calm_requires_coordination()` returns `true` iff
2851 /// `self.resolved_classification().calm_requires_coordination()`.
2852 /// The resolver returns the authored [`Classification`] when
2853 /// present and the substrate default
2854 /// [`Classification::gate_compute`] on absence. Because
2855 /// [`Classification::gate_compute`] carries
2856 /// [`crate::classification::CalmClassification::default = Monotone`],
2857 /// a bare ephemeral spec with no `:classification` slot answers
2858 /// `false` — the default-arm short-circuit propagates through TWO
2859 /// layers of `Default` ([`Classification::gate_compute`] →
2860 /// [`crate::classification::CalmClassification::default`]) to this
2861 /// predicate's answer. Distinct from the two `horizon_*` peers on
2862 /// this surface, which short-circuit through THREE layers of
2863 /// `Default` ([`Classification::gate_compute`] → [`Horizon::default`]
2864 /// → [`HorizonKind::default`]) because the horizon axis has a
2865 /// nested-struct wrapper between the classification field and the
2866 /// closed-set discriminator. A regression that dropped the
2867 /// resolver hop, probed [`Classification::has_calm`] directly
2868 /// (dropping the `.requires_coordination()` projection), or
2869 /// inverted the projection (silently promoting the Monotone
2870 /// baseline to "requires coordination") fails HERE at ONE narrow
2871 /// substrate site before drifting through every unadorned
2872 /// ephemeral spec's baseline coordination-mode answer.
2873 ///
2874 /// # Compounding
2875 ///
2876 /// The ephemeral require-tag classifier composes this primitive
2877 /// as a fixed tag `coordination-required` on
2878 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2879 /// surface's `coordination-required` fixed tag on
2880 /// `POINT_FIXED_TAG_ARMS` via
2881 /// [`Classification::calm_requires_coordination`] directly. The
2882 /// two-surface parity contract holds by construction: both
2883 /// surfaces route through the SAME
2884 /// [`Classification::calm_requires_coordination`] primitive after
2885 /// the ephemeral surface pays ONE resolver hop — a future
2886 /// [`crate::classification::CalmClassification`] variant or a
2887 /// future normalization at the substrate primitive lands at ONE
2888 /// site and both surfaces' `coordination-required` fixed tags
2889 /// inherit the shift mechanically.
2890 ///
2891 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2892 /// preserves proofs; the classification-axis derived-nullary-
2893 /// boolean probe body composes ONE resolver primitive
2894 /// ([`Self::resolved_classification`]) with ONE
2895 /// [`Classification`] primitive
2896 /// ([`Classification::calm_requires_coordination`]) so every
2897 /// downstream (`coordination-required` fixed tags on both
2898 /// surfaces in tatara-check, future scheduler / coordination-mode
2899 /// validators, future variant additions on
2900 /// [`crate::classification::CalmClassification`]) binds through
2901 /// the SAME `calm_requires_coordination()` shape rather than
2902 /// restating either the resolver walk or the closed-set
2903 /// projection composition at the callsite. THEORY.md §VI.1 —
2904 /// generation over composition; a future
2905 /// [`crate::classification::CalmClassification`] variant lands at
2906 /// ONE `ALL` entry + ONE `requires_coordination` arm on the
2907 /// closed set and both surfaces pick it up mechanically.
2908 #[must_use]
2909 pub fn calm_requires_coordination(&self) -> bool {
2910 self.resolved_classification().calm_requires_coordination()
2911 }
2912
2913 /// Derived-boolean predicate — does this ephemeral spec's
2914 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
2915 /// project to `true` under
2916 /// [`crate::classification::DataClassification::is_regulated`]?
2917 /// Byte-for-byte peer of
2918 /// [`Classification::data_is_regulated`] wrapped through the
2919 /// [`Self::resolved_classification`] resolver so an operator-
2920 /// omitted `:classification` slot on `(defephemeral …)` still
2921 /// answers via the substrate default. The ONE ephemeral-surface
2922 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2923 /// derived-nullary-boolean walk on the regulated-data question
2924 /// over the classification-data axis.
2925 ///
2926 /// # Fourth derived-nullary-boolean peer on the ephemeral surface
2927 ///
2928 /// Peer of [`Self::horizon_terminates`],
2929 /// [`Self::horizon_requires_metric_axes`], and
2930 /// [`Self::calm_requires_coordination`] on the ephemeral surface's
2931 /// (resolver-hop × derived-nullary-bool) shape — the FIRST peer
2932 /// threading the classification-data axis rather than the horizon
2933 /// or calm axes. Structural byte-for-byte peer of
2934 /// [`Self::calm_requires_coordination`]: both walk a DIRECT scalar
2935 /// closed-set field's derived projection on the resolved
2936 /// [`Classification`] (`.calm.requires_coordination()` /
2937 /// `.data_classification.is_regulated()`) — TWO layers of
2938 /// `Default` short-circuit ([`Classification::gate_compute`] →
2939 /// the direct scalar child's `#[default]`) — distinct from the
2940 /// two `horizon_*` peers which walk a NESTED-STRUCT projection
2941 /// (`.horizon.kind`) with THREE layers of `Default`. The resolver-
2942 /// hop shape is byte-identical across all four peers.
2943 ///
2944 /// # Semantics — resolver hop + derived-nullary-boolean
2945 ///
2946 /// `data_is_regulated()` returns `true` iff
2947 /// `self.resolved_classification().data_is_regulated()`. The
2948 /// resolver returns the authored [`Classification`] when present
2949 /// and the substrate default [`Classification::gate_compute`] on
2950 /// absence. Because [`Classification::gate_compute`] carries
2951 /// [`crate::classification::DataClassification::default = Internal`],
2952 /// a bare ephemeral spec with no `:classification` slot answers
2953 /// `false` — the default-arm short-circuit propagates through TWO
2954 /// layers of `Default` ([`Classification::gate_compute`] →
2955 /// [`crate::classification::DataClassification::default`]) to
2956 /// this predicate's answer, mirror-image of
2957 /// [`Self::calm_requires_coordination`]'s Monotone-default
2958 /// short-circuit through the same structural depth. Distinct
2959 /// from the two `horizon_*` peers on this surface which short-
2960 /// circuit through THREE layers of `Default` because the horizon
2961 /// axis has a nested-struct wrapper. A regression that dropped
2962 /// the resolver hop, probed [`Classification::has_data_classification`]
2963 /// directly (dropping the `.is_regulated()` projection), or
2964 /// inverted the projection (silently promoting the Internal
2965 /// baseline to "regulated") fails HERE at ONE narrow substrate
2966 /// site before drifting through every unadorned ephemeral spec's
2967 /// baseline regulatory-regime answer.
2968 ///
2969 /// # Compounding
2970 ///
2971 /// The ephemeral require-tag classifier composes this primitive
2972 /// as a fixed tag `data-regulated` on `EPHEMERAL_FIXED_TAG_ARMS`
2973 /// — byte-for-byte peer of the point surface's `data-regulated`
2974 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
2975 /// [`Classification::data_is_regulated`] directly. The two-
2976 /// surface parity contract holds by construction: both surfaces
2977 /// route through the SAME
2978 /// [`Classification::data_is_regulated`] primitive after the
2979 /// ephemeral surface pays ONE resolver hop — a future
2980 /// [`crate::classification::DataClassification`] variant or a
2981 /// future normalization at the substrate primitive lands at ONE
2982 /// site and both surfaces' `data-regulated` fixed tags inherit
2983 /// the shift mechanically.
2984 ///
2985 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2986 /// preserves proofs; the classification-data-axis derived-nullary-
2987 /// boolean probe body composes ONE resolver primitive
2988 /// ([`Self::resolved_classification`]) with ONE
2989 /// [`Classification`] primitive
2990 /// ([`Classification::data_is_regulated`]) so every downstream
2991 /// (`data-regulated` fixed tags on both surfaces in tatara-check,
2992 /// future compliance-baseline / regulatory-regime validators,
2993 /// future variant additions on
2994 /// [`crate::classification::DataClassification`]) binds through
2995 /// the SAME `data_is_regulated()` shape rather than restating
2996 /// either the resolver walk or the closed-set projection
2997 /// composition at the callsite. THEORY.md §VI.1 — generation
2998 /// over composition; a future
2999 /// [`crate::classification::DataClassification`] variant lands
3000 /// at ONE `ALL` entry + ONE `is_regulated` arm on the closed set
3001 /// and both surfaces pick it up mechanically.
3002 #[must_use]
3003 pub fn data_is_regulated(&self) -> bool {
3004 self.resolved_classification().data_is_regulated()
3005 }
3006
3007 /// Derived-boolean predicate — does this ephemeral spec's
3008 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
3009 /// project to `true` under
3010 /// [`crate::classification::DataClassification::is_restricted`]?
3011 /// Byte-for-byte peer of
3012 /// [`Classification::data_is_restricted`] wrapped through the
3013 /// [`Self::resolved_classification`] resolver so an operator-
3014 /// omitted `:classification` slot on `(defephemeral …)` still
3015 /// answers via the substrate default. The ONE ephemeral-surface
3016 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3017 /// derived-nullary-boolean walk on the restricted-data question
3018 /// over the classification-data axis.
3019 ///
3020 /// # Fifth derived-nullary-boolean peer on the ephemeral surface
3021 ///
3022 /// Peer of [`Self::horizon_terminates`],
3023 /// [`Self::horizon_requires_metric_axes`],
3024 /// [`Self::calm_requires_coordination`], and
3025 /// [`Self::data_is_regulated`] on the ephemeral surface's
3026 /// (resolver-hop × derived-nullary-bool) shape — the SECOND peer
3027 /// threading the classification-data axis after
3028 /// [`Self::data_is_regulated`] opened it, pinning the data axis
3029 /// as a proven-repeatable structural sub-corner across TWO sibling
3030 /// closed-set projections (`is_regulated` / `is_restricted`).
3031 /// Structural byte-for-byte peer of
3032 /// [`Self::data_is_regulated`]: both walk the SAME DIRECT scalar
3033 /// closed-set field's derived projection on the resolved
3034 /// [`Classification`] (`.data_classification.is_regulated()` /
3035 /// `.is_restricted()`) — TWO layers of `Default` short-circuit
3036 /// ([`Classification::gate_compute`] → [`crate::classification::DataClassification::default = Internal`])
3037 /// — distinct from the two `horizon_*` peers which walk a NESTED-
3038 /// STRUCT projection (`.horizon.kind`) with THREE layers of
3039 /// `Default`. The resolver-hop shape is byte-identical across all
3040 /// five peers.
3041 ///
3042 /// # Semantics — resolver hop + derived-nullary-boolean
3043 ///
3044 /// `data_is_restricted()` returns `true` iff
3045 /// `self.resolved_classification().data_is_restricted()`. The
3046 /// resolver returns the authored [`Classification`] when present
3047 /// and the substrate default [`Classification::gate_compute`] on
3048 /// absence. Because [`Classification::gate_compute`] carries
3049 /// [`crate::classification::DataClassification::default = Internal`],
3050 /// a bare ephemeral spec with no `:classification` slot answers
3051 /// `true` — the default-arm short-circuit propagates through TWO
3052 /// layers of `Default` ([`Classification::gate_compute`] →
3053 /// [`crate::classification::DataClassification::default`]) to
3054 /// this predicate's answer. FIRST direct-scalar ephemeral-surface
3055 /// peer whose absent-classification default answers `true`, not
3056 /// `false` (`data_is_regulated` and `calm_requires_coordination`
3057 /// both project `false` on the same absent classification),
3058 /// mirror-image of [`Self::horizon_terminates`]'s `Bounded`-default
3059 /// `true` baseline on the nested-struct sub-corner. A regression
3060 /// that dropped the resolver hop, probed
3061 /// [`Classification::has_data_classification`] directly (dropping
3062 /// the `.is_restricted()` projection), or inverted the projection
3063 /// (silently demoting the Internal baseline to "unrestricted")
3064 /// fails HERE at ONE narrow substrate site before drifting
3065 /// through every unadorned ephemeral spec's baseline access-
3066 /// control-mandatory answer.
3067 ///
3068 /// # Compounding
3069 ///
3070 /// The ephemeral require-tag classifier composes this primitive
3071 /// as a fixed tag `data-restricted` on `EPHEMERAL_FIXED_TAG_ARMS`
3072 /// — byte-for-byte peer of the point surface's `data-restricted`
3073 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3074 /// [`Classification::data_is_restricted`] directly. The two-
3075 /// surface parity contract holds by construction: both surfaces
3076 /// route through the SAME
3077 /// [`Classification::data_is_restricted`] primitive after the
3078 /// ephemeral surface pays ONE resolver hop — a future
3079 /// [`crate::classification::DataClassification`] variant or a
3080 /// future normalization at the substrate primitive lands at ONE
3081 /// site and both surfaces' `data-restricted` fixed tags inherit
3082 /// the shift mechanically. The closed-set-internal implication
3083 /// `is_regulated() ⇒ is_restricted()` composes through the
3084 /// resolver hop to
3085 /// `data_is_regulated() ⇒ data_is_restricted()` at this surface
3086 /// too.
3087 ///
3088 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3089 /// preserves proofs; the classification-data-axis derived-nullary-
3090 /// boolean probe body composes ONE resolver primitive
3091 /// ([`Self::resolved_classification`]) with ONE
3092 /// [`Classification`] primitive
3093 /// ([`Classification::data_is_restricted`]) so every downstream
3094 /// (`data-restricted` fixed tags on both surfaces in tatara-check,
3095 /// future compliance-baseline / access-control-mandatory
3096 /// validators, future variant additions on
3097 /// [`crate::classification::DataClassification`]) binds through
3098 /// the SAME `data_is_restricted()` shape rather than restating
3099 /// either the resolver walk or the closed-set projection
3100 /// composition at the callsite. THEORY.md §VI.1 — generation
3101 /// over composition; a future
3102 /// [`crate::classification::DataClassification`] variant lands
3103 /// at ONE `ALL` entry + ONE `is_restricted` arm on the closed set
3104 /// and both surfaces pick it up mechanically.
3105 #[must_use]
3106 pub fn data_is_restricted(&self) -> bool {
3107 self.resolved_classification().data_is_restricted()
3108 }
3109
3110 /// Derived-boolean predicate — does this ephemeral spec's
3111 /// resolved [`Classification`]'s
3112 /// [`crate::classification::ConvergencePointType`] project to
3113 /// `true` under
3114 /// [`crate::classification::ConvergencePointType::is_endomorphic`]?
3115 /// Byte-for-byte peer of
3116 /// [`Classification::point_is_endomorphic`] wrapped through the
3117 /// [`Self::resolved_classification`] resolver so an operator-
3118 /// omitted `:classification` slot on `(defephemeral …)` still
3119 /// answers via the substrate default. The ONE ephemeral-surface
3120 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3121 /// derived-nullary-boolean walk on the 1→1 topology-bucket
3122 /// question over the classification-`point_type` axis.
3123 ///
3124 /// # Sixth derived-nullary-boolean peer on the ephemeral surface
3125 ///
3126 /// Peer of [`Self::horizon_terminates`],
3127 /// [`Self::horizon_requires_metric_axes`],
3128 /// [`Self::calm_requires_coordination`],
3129 /// [`Self::data_is_regulated`], and [`Self::data_is_restricted`]
3130 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
3131 /// shape — the FIRST peer threading the classification-`point_type`
3132 /// axis after the two `horizon_*`, one `calm_*`, and two `data_*`
3133 /// peers populated the horizon, calm, and data axes. Direct-scalar
3134 /// peer of the sibling `data_*` and `calm_*` arms but distinct by
3135 /// ONE structural degree at the underlying [`Classification`]
3136 /// primitive: [`crate::classification::ConvergencePointType`] has
3137 /// NO [`Default`] impl, so the absent-`:classification` baseline
3138 /// answers `false` via the resolver's substrate default
3139 /// [`Classification::gate_compute`] carrying its chosen
3140 /// `point_type: Gate` field (not via a `#[default]` short-circuit
3141 /// on the point-type axis itself). The resolver-hop shape is
3142 /// byte-identical across all six peers.
3143 ///
3144 /// # Semantics — resolver hop + derived-nullary-boolean
3145 ///
3146 /// `point_is_endomorphic()` returns `true` iff
3147 /// `self.resolved_classification().point_is_endomorphic()`. The
3148 /// resolver returns the authored [`Classification`] when present
3149 /// and the substrate default [`Classification::gate_compute`] on
3150 /// absence. Because [`Classification::gate_compute`] carries
3151 /// [`crate::classification::ConvergencePointType::Gate`] (a
3152 /// convergent barrier point, not a 1→1 endomorphism), a bare
3153 /// ephemeral spec with no `:classification` slot answers `false`.
3154 /// A regression that dropped the resolver hop, probed the wrong
3155 /// closed-set arm, or inverted the projection fails HERE at ONE
3156 /// narrow substrate site before drifting through every unadorned
3157 /// ephemeral spec's DAG-composition answer.
3158 ///
3159 /// # Compounding
3160 ///
3161 /// The ephemeral require-tag classifier composes this primitive
3162 /// as a fixed tag `endomorphic-point` on
3163 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3164 /// surface's `endomorphic-point` fixed tag on
3165 /// `POINT_FIXED_TAG_ARMS` via
3166 /// [`Classification::point_is_endomorphic`] directly. The two-
3167 /// surface parity contract holds by construction: both surfaces
3168 /// route through the SAME
3169 /// [`Classification::point_is_endomorphic`] primitive after the
3170 /// ephemeral surface pays ONE resolver hop — a future
3171 /// [`crate::classification::ConvergencePointType`] variant or a
3172 /// future normalization at the substrate primitive lands at ONE
3173 /// site and both surfaces' `endomorphic-point` fixed tags inherit
3174 /// the shift mechanically. Sibling projections
3175 /// [`crate::classification::ConvergencePointType::is_diffusive`]
3176 /// and [`crate::classification::ConvergencePointType::is_convergent`]
3177 /// compose byte-identically as future seventh + eighth ephemeral-
3178 /// surface peers; when all three land the three-way partition
3179 /// contract sealed on the closed set by
3180 /// `convergence_point_type_buckets_cover_every_variant` composes
3181 /// through the resolver-hop layer as a substrate-wide theorem.
3182 ///
3183 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3184 /// preserves proofs; the classification-`point_type`-axis derived-
3185 /// nullary-boolean probe body composes ONE resolver primitive
3186 /// ([`Self::resolved_classification`]) with ONE
3187 /// [`Classification`] primitive
3188 /// ([`Classification::point_is_endomorphic`]) so every downstream
3189 /// (`endomorphic-point` fixed tags on both surfaces in tatara-check,
3190 /// future DAG composition / edge-cardinality validators, future
3191 /// variant additions on
3192 /// [`crate::classification::ConvergencePointType`]) binds through
3193 /// the SAME `point_is_endomorphic()` shape rather than restating
3194 /// either the resolver walk or the closed-set projection
3195 /// composition at the callsite. THEORY.md §VI.1 — generation over
3196 /// composition; a future
3197 /// [`crate::classification::ConvergencePointType`] variant lands
3198 /// at ONE `ALL` entry + ONE `is_endomorphic` arm on the closed
3199 /// set and both surfaces pick it up mechanically.
3200 #[must_use]
3201 pub fn point_is_endomorphic(&self) -> bool {
3202 self.resolved_classification().point_is_endomorphic()
3203 }
3204
3205 /// Derived-boolean predicate — does this ephemeral spec's
3206 /// resolved [`Classification`]'s
3207 /// [`crate::classification::ConvergencePointType`] project to
3208 /// `true` under
3209 /// [`crate::classification::ConvergencePointType::is_diffusive`]?
3210 /// Byte-for-byte peer of
3211 /// [`Classification::point_is_diffusive`] wrapped through the
3212 /// [`Self::resolved_classification`] resolver so an operator-
3213 /// omitted `:classification` slot on `(defephemeral …)` still
3214 /// answers via the substrate default. The ONE ephemeral-surface
3215 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3216 /// derived-nullary-boolean walk on the 1→N fan-out topology-bucket
3217 /// question over the classification-`point_type` axis.
3218 ///
3219 /// # Seventh derived-nullary-boolean peer on the ephemeral surface
3220 ///
3221 /// Peer of [`Self::horizon_terminates`],
3222 /// [`Self::horizon_requires_metric_axes`],
3223 /// [`Self::calm_requires_coordination`],
3224 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`], and
3225 /// [`Self::point_is_endomorphic`] on the ephemeral surface's
3226 /// (resolver-hop × derived-nullary-bool) shape — the SEVENTH peer
3227 /// overall and the SECOND peer threading the classification-
3228 /// `point_type` axis. Direct-scalar peer of
3229 /// [`Self::point_is_endomorphic`]: both compose the SAME resolver
3230 /// hop and the SAME closed-set carrier through the SAME chosen-
3231 /// field baseline discipline (`Gate.is_diffusive() = false`,
3232 /// mirror-image of `Gate.is_endomorphic() = false`). The
3233 /// resolver-hop shape is byte-identical across all seven peers.
3234 ///
3235 /// # Semantics — resolver hop + derived-nullary-boolean
3236 ///
3237 /// `point_is_diffusive()` returns `true` iff
3238 /// `self.resolved_classification().point_is_diffusive()`. The
3239 /// resolver returns the authored [`Classification`] when present
3240 /// and the substrate default [`Classification::gate_compute`] on
3241 /// absence. Because [`Classification::gate_compute`] carries
3242 /// [`crate::classification::ConvergencePointType::Gate`] (a
3243 /// convergent barrier, not a fan-out), a bare ephemeral spec with
3244 /// no `:classification` slot answers `false`. A regression that
3245 /// dropped the resolver hop, probed the wrong closed-set arm, or
3246 /// inverted the projection fails HERE at ONE narrow substrate
3247 /// site before drifting through every unadorned ephemeral spec's
3248 /// DAG-composition answer.
3249 ///
3250 /// # Compounding — first ephemeral-surface corner-peer mutex on the `point_type` axis
3251 ///
3252 /// The ephemeral require-tag classifier composes this primitive
3253 /// as a fixed tag `diffusive-point` on `EPHEMERAL_FIXED_TAG_ARMS`
3254 /// — byte-for-byte peer of the point surface's `diffusive-point`
3255 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3256 /// [`Classification::point_is_diffusive`] directly. The two-
3257 /// surface parity contract holds by construction: both surfaces
3258 /// route through the SAME
3259 /// [`Classification::point_is_diffusive`] primitive after the
3260 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
3261 /// surface corner-peer pair on the `point_type` axis (with
3262 /// [`Self::point_is_endomorphic`]) whose two projections carry a
3263 /// non-trivial closed-set-internal MUTEX relationship
3264 /// (`point_is_endomorphic ⇒ ¬point_is_diffusive`), distinct from
3265 /// the sibling `data`-axis ephemeral corner-peer pair whose two
3266 /// projections carry a non-trivial IMPLICATION relationship. When
3267 /// the third sibling [`Self::point_is_convergent`] lands, the
3268 /// mutex closes into the full three-way XOR partition composed
3269 /// through the resolver-hop layer as a substrate-wide theorem.
3270 ///
3271 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3272 /// preserves proofs; the classification-`point_type`-axis derived-
3273 /// nullary-boolean probe body composes ONE resolver primitive
3274 /// ([`Self::resolved_classification`]) with ONE
3275 /// [`Classification`] primitive
3276 /// ([`Classification::point_is_diffusive`]) so every downstream
3277 /// (`diffusive-point` fixed tags on both surfaces in tatara-check,
3278 /// future DAG composition / edge-cardinality validators, future
3279 /// variant additions on
3280 /// [`crate::classification::ConvergencePointType`]) binds through
3281 /// the SAME `point_is_diffusive()` shape rather than restating
3282 /// either the resolver walk or the closed-set projection
3283 /// composition at the callsite. THEORY.md §VI.1 — generation over
3284 /// composition; a future
3285 /// [`crate::classification::ConvergencePointType`] variant lands
3286 /// at ONE `ALL` entry + ONE `is_diffusive` arm on the closed set
3287 /// and both surfaces pick it up mechanically.
3288 #[must_use]
3289 pub fn point_is_diffusive(&self) -> bool {
3290 self.resolved_classification().point_is_diffusive()
3291 }
3292
3293 /// Derived-boolean predicate — does this ephemeral spec's
3294 /// resolved [`Classification`]'s
3295 /// [`crate::classification::ConvergencePointType`] project to
3296 /// `true` under
3297 /// [`crate::classification::ConvergencePointType::is_convergent`]?
3298 /// Byte-for-byte peer of
3299 /// [`Classification::point_is_convergent`] wrapped through the
3300 /// [`Self::resolved_classification`] resolver so an operator-
3301 /// omitted `:classification` slot on `(defephemeral …)` still
3302 /// answers via the substrate default. The ONE ephemeral-surface
3303 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3304 /// derived-nullary-boolean walk on the N→1 fan-in topology-bucket
3305 /// question over the classification-`point_type` axis.
3306 ///
3307 /// # Eighth derived-nullary-boolean peer on the ephemeral surface
3308 ///
3309 /// Peer of [`Self::horizon_terminates`],
3310 /// [`Self::horizon_requires_metric_axes`],
3311 /// [`Self::calm_requires_coordination`],
3312 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3313 /// [`Self::point_is_endomorphic`], and [`Self::point_is_diffusive`]
3314 /// on the ephemeral surface's (resolver-hop × derived-nullary-
3315 /// bool) shape — the EIGHTH peer overall and the THIRD peer
3316 /// threading the classification-`point_type` axis. Direct-scalar
3317 /// peer of [`Self::point_is_endomorphic`] and
3318 /// [`Self::point_is_diffusive`]: the three compose the SAME
3319 /// resolver hop and the SAME closed-set carrier through the SAME
3320 /// chosen-field baseline discipline, but the answer flips on the
3321 /// baseline — `Gate.is_convergent() = true`, so an ephemeral spec
3322 /// with no `:classification` slot answers `true` HERE (mirror-
3323 /// inverted from the two sibling probes which answer `false`).
3324 /// The resolver-hop shape is byte-identical across all eight
3325 /// peers.
3326 ///
3327 /// # Semantics — resolver hop + derived-nullary-boolean
3328 ///
3329 /// `point_is_convergent()` returns `true` iff
3330 /// `self.resolved_classification().point_is_convergent()`. The
3331 /// resolver returns the authored [`Classification`] when present
3332 /// and the substrate default [`Classification::gate_compute`] on
3333 /// absence. Because [`Classification::gate_compute`] carries
3334 /// [`crate::classification::ConvergencePointType::Gate`] (the
3335 /// canonical convergent barrier), a bare ephemeral spec with no
3336 /// `:classification` slot answers `true` — a regression that
3337 /// dropped the resolver hop, probed the wrong closed-set arm, or
3338 /// inverted the projection fails HERE at ONE narrow substrate
3339 /// site before drifting through every unadorned ephemeral spec's
3340 /// DAG-composition answer.
3341 ///
3342 /// # Compounding — closes the three-way XOR partition on the ephemeral surface
3343 ///
3344 /// The ephemeral require-tag classifier composes this primitive
3345 /// as a fixed tag `convergent-point` on `EPHEMERAL_FIXED_TAG_ARMS`
3346 /// — byte-for-byte peer of the point surface's `convergent-point`
3347 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3348 /// [`Classification::point_is_convergent`] directly. The two-
3349 /// surface parity contract holds by construction: both surfaces
3350 /// route through the SAME
3351 /// [`Classification::point_is_convergent`] primitive after the
3352 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
3353 /// surface peer on the `point_type` axis closing the mutex pair
3354 /// [`Self::point_is_endomorphic`] / [`Self::point_is_diffusive`]
3355 /// into the FULL three-way XOR partition contract composed
3356 /// through the resolver-hop layer as a substrate-wide theorem.
3357 ///
3358 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3359 /// preserves proofs; the classification-`point_type`-axis derived-
3360 /// nullary-boolean probe body composes ONE resolver primitive
3361 /// ([`Self::resolved_classification`]) with ONE
3362 /// [`Classification`] primitive
3363 /// ([`Classification::point_is_convergent`]) so every downstream
3364 /// (`convergent-point` fixed tags on both surfaces in tatara-check,
3365 /// future DAG composition / edge-cardinality validators, future
3366 /// variant additions on
3367 /// [`crate::classification::ConvergencePointType`]) binds through
3368 /// the SAME `point_is_convergent()` shape rather than restating
3369 /// either the resolver walk or the closed-set projection
3370 /// composition at the callsite. THEORY.md §VI.1 — generation over
3371 /// composition; a future
3372 /// [`crate::classification::ConvergencePointType`] variant lands
3373 /// at ONE `ALL` entry + ONE `is_convergent` arm on the closed set
3374 /// and both surfaces pick it up mechanically.
3375 #[must_use]
3376 pub fn point_is_convergent(&self) -> bool {
3377 self.resolved_classification().point_is_convergent()
3378 }
3379
3380 /// Derived-boolean predicate — does this ephemeral spec's
3381 /// resolved [`Classification`]'s
3382 /// [`crate::classification::SubstrateType`] project to `true`
3383 /// under [`crate::classification::SubstrateType::is_resource`]?
3384 /// Byte-for-byte peer of
3385 /// [`Classification::substrate_is_resource`] wrapped through the
3386 /// [`Self::resolved_classification`] resolver so an operator-
3387 /// omitted `:classification` slot on `(defephemeral …)` still
3388 /// answers via the substrate default. The ONE ephemeral-surface
3389 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3390 /// derived-nullary-boolean walk on the resource-plane bucket
3391 /// question over the classification-`substrate` axis.
3392 ///
3393 /// # Ninth derived-nullary-boolean peer on the ephemeral surface
3394 ///
3395 /// Peer of [`Self::horizon_terminates`],
3396 /// [`Self::horizon_requires_metric_axes`],
3397 /// [`Self::calm_requires_coordination`],
3398 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3399 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3400 /// and [`Self::point_is_convergent`] on the ephemeral surface's
3401 /// (resolver-hop × derived-nullary-bool) shape — the NINTH peer
3402 /// overall and the FIRST peer threading the classification-
3403 /// `substrate` axis (the fourth of six classification axes
3404 /// participating on this corner, after `horizon`, `calm`,
3405 /// `data_classification`, and `point_type`). The resolver-hop
3406 /// shape is byte-identical across all nine peers.
3407 ///
3408 /// # Semantics — resolver hop + derived-nullary-boolean
3409 ///
3410 /// `substrate_is_resource()` returns `true` iff
3411 /// `self.resolved_classification().substrate_is_resource()`. The
3412 /// resolver returns the authored [`Classification`] when present
3413 /// and the substrate default [`Classification::gate_compute`] on
3414 /// absence. Because [`Classification::gate_compute`] carries
3415 /// [`crate::classification::SubstrateType::Compute`] (the
3416 /// canonical resource-plane substrate), a bare ephemeral spec
3417 /// with no `:classification` slot answers `true` — a regression
3418 /// that dropped the resolver hop, probed the wrong closed-set
3419 /// arm, or inverted the projection fails HERE at ONE narrow
3420 /// substrate site before drifting through every unadorned
3421 /// ephemeral spec's plane-baseline answer.
3422 ///
3423 /// # Compounding — opens the substrate axis on the ephemeral surface
3424 ///
3425 /// The ephemeral require-tag classifier composes this primitive
3426 /// as a fixed tag `resource-substrate` on
3427 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3428 /// surface's `resource-substrate` fixed tag on
3429 /// `POINT_FIXED_TAG_ARMS` via
3430 /// [`Classification::substrate_is_resource`] directly. The two-
3431 /// surface parity contract holds by construction: both surfaces
3432 /// route through the SAME
3433 /// [`Classification::substrate_is_resource`] primitive after the
3434 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
3435 /// surface peer on the `substrate` axis — future sibling
3436 /// projections [`crate::classification::SubstrateType::is_policy`]
3437 /// and [`crate::classification::SubstrateType::is_telemetry`]
3438 /// compose byte-identically as future tenth + eleventh peers,
3439 /// closing the axis into a proven-repeatable three-peer sub-
3440 /// corner exactly as the `point_type` axis was closed on this
3441 /// surface by
3442 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3443 ///
3444 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3445 /// preserves proofs; the classification-`substrate`-axis derived-
3446 /// nullary-boolean probe body composes ONE resolver primitive
3447 /// ([`Self::resolved_classification`]) with ONE
3448 /// [`Classification`] primitive
3449 /// ([`Classification::substrate_is_resource`]) so every
3450 /// downstream (`resource-substrate` fixed tags on both surfaces
3451 /// in tatara-check, future plane-baseline / compliance-baseline
3452 /// selectors, future variant additions on
3453 /// [`crate::classification::SubstrateType`]) binds through the
3454 /// SAME `substrate_is_resource()` shape rather than restating
3455 /// either the resolver walk or the closed-set projection
3456 /// composition at the callsite. THEORY.md §VI.1 — generation
3457 /// over composition; a future
3458 /// [`crate::classification::SubstrateType`] variant lands at ONE
3459 /// `ALL` entry + ONE `is_resource` arm on the closed set and
3460 /// both surfaces pick it up mechanically.
3461 #[must_use]
3462 pub fn substrate_is_resource(&self) -> bool {
3463 self.resolved_classification().substrate_is_resource()
3464 }
3465
3466 /// Derived-boolean predicate — does this ephemeral spec's
3467 /// resolved [`Classification`]'s
3468 /// [`crate::classification::SubstrateType`] project to `true`
3469 /// under [`crate::classification::SubstrateType::is_policy`]?
3470 /// Byte-for-byte peer of
3471 /// [`Classification::substrate_is_policy`] wrapped through the
3472 /// [`Self::resolved_classification`] resolver so an operator-
3473 /// omitted `:classification` slot on `(defephemeral …)` still
3474 /// answers via the substrate default. The ONE ephemeral-surface
3475 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3476 /// derived-nullary-boolean walk on the policy-plane bucket
3477 /// question over the classification-`substrate` axis.
3478 ///
3479 /// # Tenth derived-nullary-boolean peer on the ephemeral surface
3480 ///
3481 /// Peer of [`Self::horizon_terminates`],
3482 /// [`Self::horizon_requires_metric_axes`],
3483 /// [`Self::calm_requires_coordination`],
3484 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3485 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3486 /// [`Self::point_is_convergent`], and
3487 /// [`Self::substrate_is_resource`] on the ephemeral surface's
3488 /// (resolver-hop × derived-nullary-bool) shape — the TENTH peer
3489 /// overall and the SECOND peer threading the classification-
3490 /// `substrate` axis, promoting that axis on this surface from a
3491 /// proven-repeatable one-off to a proven-repeatable pair.
3492 /// FIRST ephemeral-surface substrate-axis corner-peer pair
3493 /// carrying a non-trivial closed-set-internal MUTEX relationship
3494 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`), structural
3495 /// twin of the sibling `point_type`-axis MUTEX pair sealed on
3496 /// this surface by
3497 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
3498 /// The resolver-hop shape is byte-identical across all ten peers.
3499 ///
3500 /// # Semantics — resolver hop + derived-nullary-boolean
3501 ///
3502 /// `substrate_is_policy()` returns `true` iff
3503 /// `self.resolved_classification().substrate_is_policy()`. The
3504 /// resolver returns the authored [`Classification`] when present
3505 /// and the substrate default [`Classification::gate_compute`] on
3506 /// absence. Because [`Classification::gate_compute`] carries
3507 /// [`crate::classification::SubstrateType::Compute`] (the
3508 /// canonical resource-plane substrate, NOT a policy plane), a
3509 /// bare ephemeral spec with no `:classification` slot answers
3510 /// `false` — a regression that dropped the resolver hop, probed
3511 /// the wrong closed-set arm, or inverted the projection fails
3512 /// HERE at ONE narrow substrate site before drifting through
3513 /// every unadorned ephemeral spec's plane-baseline answer.
3514 ///
3515 /// # Compounding — second substrate-axis peer on the ephemeral surface
3516 ///
3517 /// The ephemeral require-tag classifier composes this primitive
3518 /// as a fixed tag `policy-substrate` on
3519 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3520 /// surface's `policy-substrate` fixed tag on
3521 /// `POINT_FIXED_TAG_ARMS` via
3522 /// [`Classification::substrate_is_policy`] directly. The two-
3523 /// surface parity contract holds by construction: both surfaces
3524 /// route through the SAME
3525 /// [`Classification::substrate_is_policy`] primitive after the
3526 /// ephemeral surface pays ONE resolver hop. SECOND ephemeral-
3527 /// surface peer on the `substrate` axis — sibling projection
3528 /// [`crate::classification::SubstrateType::is_telemetry`]
3529 /// composes byte-identically as a future eleventh peer, closing
3530 /// the axis into a proven-repeatable three-peer sub-corner
3531 /// exactly as the `point_type` axis was closed on this surface
3532 /// by
3533 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3534 ///
3535 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3536 /// preserves proofs; the classification-`substrate`-axis derived-
3537 /// nullary-boolean probe body composes ONE resolver primitive
3538 /// ([`Self::resolved_classification`]) with ONE
3539 /// [`Classification`] primitive
3540 /// ([`Classification::substrate_is_policy`]) so every
3541 /// downstream (`policy-substrate` fixed tags on both surfaces
3542 /// in tatara-check, future plane-baseline / compliance-baseline
3543 /// selectors, future variant additions on
3544 /// [`crate::classification::SubstrateType`]) binds through the
3545 /// SAME `substrate_is_policy()` shape rather than restating
3546 /// either the resolver walk or the closed-set projection
3547 /// composition at the callsite. THEORY.md §VI.1 — generation
3548 /// over composition; a future
3549 /// [`crate::classification::SubstrateType`] variant lands at ONE
3550 /// `ALL` entry + ONE `is_policy` arm on the closed set and
3551 /// both surfaces pick it up mechanically.
3552 #[must_use]
3553 pub fn substrate_is_policy(&self) -> bool {
3554 self.resolved_classification().substrate_is_policy()
3555 }
3556
3557 /// Derived-boolean predicate — does this ephemeral spec's
3558 /// resolved [`Classification`]'s
3559 /// [`crate::classification::SubstrateType`] project to `true`
3560 /// under [`crate::classification::SubstrateType::is_telemetry`]?
3561 /// Byte-for-byte peer of
3562 /// [`Classification::substrate_is_telemetry`] wrapped through
3563 /// the [`Self::resolved_classification`] resolver so an operator-
3564 /// omitted `:classification` slot on `(defephemeral …)` still
3565 /// answers via the substrate default. The ONE ephemeral-surface
3566 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3567 /// derived-nullary-boolean walk on the telemetry-plane bucket
3568 /// question over the classification-`substrate` axis.
3569 ///
3570 /// # Eleventh derived-nullary-boolean peer on the ephemeral surface — CLOSES the substrate axis
3571 ///
3572 /// Peer of [`Self::horizon_terminates`],
3573 /// [`Self::horizon_requires_metric_axes`],
3574 /// [`Self::calm_requires_coordination`],
3575 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3576 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3577 /// [`Self::point_is_convergent`], [`Self::substrate_is_resource`],
3578 /// and [`Self::substrate_is_policy`] on the ephemeral surface's
3579 /// (resolver-hop × derived-nullary-bool) shape — the ELEVENTH
3580 /// peer overall and the THIRD peer threading the classification-
3581 /// `substrate` axis. This peer CLOSES the substrate axis on the
3582 /// ephemeral surface into the FULL three-way XOR partition
3583 /// contract `substrate_is_resource ⊕ substrate_is_policy ⊕
3584 /// substrate_is_telemetry` — sealed on this surface by
3585 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
3586 /// the resolver-hop peer of the parent-composed
3587 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`.
3588 /// Structural twin of the sibling `point_type`-axis ternary lift
3589 /// sealed on this surface by
3590 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3591 /// The resolver-hop shape is byte-identical across all eleven
3592 /// peers.
3593 ///
3594 /// # Semantics — resolver hop + derived-nullary-boolean
3595 ///
3596 /// `substrate_is_telemetry()` returns `true` iff
3597 /// `self.resolved_classification().substrate_is_telemetry()`.
3598 /// The resolver returns the authored [`Classification`] when
3599 /// present and the substrate default [`Classification::gate_compute`]
3600 /// on absence. Because [`Classification::gate_compute`] carries
3601 /// [`crate::classification::SubstrateType::Compute`] (the
3602 /// canonical resource-plane substrate, NOT a telemetry plane),
3603 /// a bare ephemeral spec with no `:classification` slot answers
3604 /// `false` — a regression that dropped the resolver hop, probed
3605 /// the wrong closed-set arm, or inverted the projection fails
3606 /// HERE at ONE narrow substrate site before drifting through
3607 /// every unadorned ephemeral spec's plane-baseline answer.
3608 ///
3609 /// # Compounding — CLOSES the substrate axis on the ephemeral surface
3610 ///
3611 /// The ephemeral require-tag classifier composes this primitive
3612 /// as a fixed tag `telemetry-substrate` on
3613 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3614 /// surface's `telemetry-substrate` fixed tag on
3615 /// `POINT_FIXED_TAG_ARMS` via
3616 /// [`Classification::substrate_is_telemetry`] directly. The two-
3617 /// surface parity contract holds by construction: both surfaces
3618 /// route through the SAME
3619 /// [`Classification::substrate_is_telemetry`] primitive after the
3620 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
3621 /// surface peer on the `substrate` axis — closes the axis into a
3622 /// proven-repeatable three-peer sub-corner exactly as the
3623 /// `point_type` axis was closed on this surface by
3624 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3625 ///
3626 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3627 /// preserves proofs; the classification-`substrate`-axis derived-
3628 /// nullary-boolean probe body composes ONE resolver primitive
3629 /// ([`Self::resolved_classification`]) with ONE
3630 /// [`Classification`] primitive
3631 /// ([`Classification::substrate_is_telemetry`]) so every
3632 /// downstream (`telemetry-substrate` fixed tags on both surfaces
3633 /// in tatara-check, future plane-baseline / compliance-baseline
3634 /// selectors, future variant additions on
3635 /// [`crate::classification::SubstrateType`]) binds through the
3636 /// SAME `substrate_is_telemetry()` shape rather than restating
3637 /// either the resolver walk or the closed-set projection
3638 /// composition at the callsite. THEORY.md §VI.1 — generation
3639 /// over composition; a future
3640 /// [`crate::classification::SubstrateType`] variant lands at ONE
3641 /// `ALL` entry + ONE `is_telemetry` arm on the closed set and
3642 /// both surfaces pick it up mechanically.
3643 #[must_use]
3644 pub fn substrate_is_telemetry(&self) -> bool {
3645 self.resolved_classification().substrate_is_telemetry()
3646 }
3647
3648 /// Derived-boolean predicate — does this ephemeral spec's
3649 /// resolved [`Classification`]'s
3650 /// [`crate::classification::CalmClassification`] project to `true`
3651 /// under [`crate::classification::CalmClassification::is_monotone`]?
3652 /// Byte-for-byte peer of [`Classification::calm_is_monotone`]
3653 /// wrapped through the [`Self::resolved_classification`] resolver
3654 /// so an operator-omitted `:classification` slot on
3655 /// `(defephemeral …)` still answers via the substrate default.
3656 /// The ONE ephemeral-surface substrate primitive that owns the
3657 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3658 /// CALM-monotone-plane question — the positive framing peer of
3659 /// [`Self::calm_requires_coordination`].
3660 ///
3661 /// # Twelfth derived-nullary-boolean peer on the ephemeral surface — CLOSES the calm axis
3662 ///
3663 /// Peer of [`Self::horizon_terminates`],
3664 /// [`Self::horizon_requires_metric_axes`],
3665 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3666 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3667 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3668 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3669 /// and [`Self::substrate_is_telemetry`] on the ephemeral
3670 /// surface's (resolver-hop × derived-nullary-bool) shape — the
3671 /// TWELFTH peer overall and the SECOND peer threading the
3672 /// classification-`calm` axis. This peer CLOSES the calm axis
3673 /// on the ephemeral surface into the FULL binary XOR partition
3674 /// contract `calm_is_monotone ⊕ calm_requires_coordination` —
3675 /// sealed on this surface by
3676 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
3677 /// the resolver-hop peer of the parent-composed
3678 /// `classification_calm_probes_form_binary_xor_partition_over_all`.
3679 /// Structural twin of the sibling horizon-axis binary XOR
3680 /// sealed on the closed set by
3681 /// `horizon_kind_terminate_xor_requires_metric_axes`, lifted
3682 /// through the resolver hop to the ephemeral surface. The
3683 /// resolver-hop shape is byte-identical across all twelve peers.
3684 ///
3685 /// # Semantics — resolver hop + derived-nullary-boolean
3686 ///
3687 /// `calm_is_monotone()` returns `true` iff
3688 /// `self.resolved_classification().calm_is_monotone()`. The
3689 /// resolver returns the authored [`Classification`] when present
3690 /// and the substrate default [`Classification::gate_compute`] on
3691 /// absence. Because [`Classification::gate_compute`] carries
3692 /// [`crate::classification::CalmClassification::default =
3693 /// Monotone`] via `#[default]`, a bare ephemeral spec with no
3694 /// `:classification` slot answers `true` — every unadorned
3695 /// `(defephemeral …)` reads as gossip-eligible under the
3696 /// positive CALM framing, safe under Hellerstein's theorem
3697 /// (monotone operations distribute without coordination). A
3698 /// regression that dropped the resolver hop, probed the wrong
3699 /// closed-set arm, or inverted the projection fails HERE at ONE
3700 /// narrow substrate site before drifting through every
3701 /// unadorned ephemeral spec's positive-CALM-framing answer.
3702 /// Mirror-inverted from the sibling
3703 /// `calm_requires_coordination_probes_false_on_absent_classification`
3704 /// (both walk the SAME defaulted `calm` field, so
3705 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
3706 /// closed set's disjoint XOR partition).
3707 ///
3708 /// # Compounding — CLOSES the calm axis on the ephemeral surface
3709 ///
3710 /// The ephemeral require-tag classifier composes this primitive
3711 /// as a fixed tag `monotone-calm` on `EPHEMERAL_FIXED_TAG_ARMS`
3712 /// — byte-for-byte peer of the point surface's `monotone-calm`
3713 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3714 /// [`Classification::calm_is_monotone`] directly. The two-
3715 /// surface parity contract holds by construction: both surfaces
3716 /// route through the SAME [`Classification::calm_is_monotone`]
3717 /// primitive after the ephemeral surface pays ONE resolver hop.
3718 /// SECOND ephemeral-surface peer on the `calm` axis — CLOSES the
3719 /// axis into a proven-repeatable two-peer sub-corner exactly as
3720 /// the `horizon` axis is closed on the closed-set layer by
3721 /// `horizon_kind_terminate_xor_requires_metric_axes`.
3722 ///
3723 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3724 /// preserves proofs; the classification-`calm`-axis derived-
3725 /// nullary-boolean probe body composes ONE resolver primitive
3726 /// ([`Self::resolved_classification`]) with ONE
3727 /// [`Classification`] primitive
3728 /// ([`Classification::calm_is_monotone`]) so every downstream
3729 /// (`monotone-calm` fixed tags on both surfaces in tatara-check,
3730 /// future scheduler / gossip-eligibility validators reading the
3731 /// positive CALM framing, future variant additions on
3732 /// [`crate::classification::CalmClassification`]) binds through
3733 /// the SAME `calm_is_monotone()` shape rather than restating
3734 /// either the resolver walk or the closed-set projection
3735 /// composition at the callsite. THEORY.md §VI.1 — generation
3736 /// over composition; a future
3737 /// [`crate::classification::CalmClassification`] variant lands
3738 /// at ONE `ALL` entry + ONE `is_monotone` arm on the closed set
3739 /// and both surfaces pick it up mechanically.
3740 #[must_use]
3741 pub fn calm_is_monotone(&self) -> bool {
3742 self.resolved_classification().calm_is_monotone()
3743 }
3744
3745 /// Derived-boolean predicate — does this ephemeral spec's
3746 /// resolved [`Classification`]'s
3747 /// [`crate::classification::DataClassification`] project to `true`
3748 /// under [`crate::classification::DataClassification::is_public`]?
3749 /// Byte-for-byte peer of [`Classification::data_is_public`]
3750 /// wrapped through the [`Self::resolved_classification`] resolver
3751 /// so an operator-omitted `:classification` slot on
3752 /// `(defephemeral …)` still answers via the substrate default.
3753 /// The ONE ephemeral-surface substrate primitive that owns the
3754 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3755 /// freely-distributable-data question — the positive framing peer
3756 /// of [`Self::data_is_restricted`].
3757 ///
3758 /// # Thirteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the data axis
3759 ///
3760 /// Peer of [`Self::horizon_terminates`],
3761 /// [`Self::horizon_requires_metric_axes`],
3762 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3763 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3764 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3765 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3766 /// [`Self::substrate_is_telemetry`], and [`Self::calm_is_monotone`]
3767 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
3768 /// shape — the THIRTEENTH peer overall and the THIRD peer
3769 /// threading the classification-`data_classification` axis. This
3770 /// peer CLOSES the data axis on the ephemeral surface into the
3771 /// FULL binary XOR partition contract
3772 /// `data_is_public ⊕ data_is_restricted` — sealed on this surface
3773 /// by `ephemeral_data_probes_form_binary_xor_partition_over_all`,
3774 /// the resolver-hop peer of the parent-composed
3775 /// `classification_data_probes_form_binary_xor_partition_over_all`.
3776 /// Structural twin of the sibling calm-axis binary XOR sealed on
3777 /// this surface by
3778 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
3779 /// lifted through the resolver hop from the six-variant data-axis
3780 /// closed set to the ephemeral surface. The resolver-hop shape is
3781 /// byte-identical across all thirteen peers.
3782 ///
3783 /// # Semantics — resolver hop + derived-nullary-boolean
3784 ///
3785 /// `data_is_public()` returns `true` iff
3786 /// `self.resolved_classification().data_is_public()`. The
3787 /// resolver returns the authored [`Classification`] when present
3788 /// and the substrate default [`Classification::gate_compute`] on
3789 /// absence. Because [`Classification::gate_compute`] carries
3790 /// [`crate::classification::DataClassification::default =
3791 /// Internal`] via `#[default]`, a bare ephemeral spec with no
3792 /// `:classification` slot answers `false` — every unadorned
3793 /// `(defephemeral …)` reads as access-controlled by default (safe
3794 /// under compliance baseline: an operator must deliberately opt
3795 /// the dataset into public distribution rather than the substrate
3796 /// silently promoting an unadorned Process onto the freely-
3797 /// distributable path). A regression that dropped the resolver
3798 /// hop, probed the wrong closed-set arm, or inverted the
3799 /// projection fails HERE at ONE narrow substrate site before
3800 /// drifting through every unadorned ephemeral spec's positive-
3801 /// distribution-framing answer. Mirror-inverted from the sibling
3802 /// `data_is_restricted_probes_true_on_absent_classification`
3803 /// (both walk the SAME defaulted `data_classification` field, so
3804 /// `is_restricted = true` ⇒ `is_public = false` on the closed
3805 /// set's disjoint XOR partition).
3806 ///
3807 /// # Compounding — CLOSES the data axis on the ephemeral surface
3808 ///
3809 /// The ephemeral require-tag classifier composes this primitive
3810 /// as a fixed tag `public-data` on `EPHEMERAL_FIXED_TAG_ARMS`
3811 /// — byte-for-byte peer of the point surface's `public-data`
3812 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3813 /// [`Classification::data_is_public`] directly. The two-
3814 /// surface parity contract holds by construction: both surfaces
3815 /// route through the SAME [`Classification::data_is_public`]
3816 /// primitive after the ephemeral surface pays ONE resolver hop.
3817 /// THIRD ephemeral-surface peer on the `data_classification` axis
3818 /// — CLOSES the axis into a proven-repeatable three-peer sub-
3819 /// corner (data_is_regulated, data_is_restricted, data_is_public)
3820 /// whose complementary XOR partition seals on the closed set by
3821 /// `data_classification_public_xor_restricted` and composes
3822 /// through the resolver hop as a substrate-wide theorem.
3823 ///
3824 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3825 /// preserves proofs; the classification-`data_classification`-axis
3826 /// derived-nullary-boolean probe body composes ONE resolver
3827 /// primitive ([`Self::resolved_classification`]) with ONE
3828 /// [`Classification`] primitive
3829 /// ([`Classification::data_is_public`]) so every downstream
3830 /// (`public-data` fixed tags on both surfaces in tatara-check,
3831 /// future compliance-baseline / audit-log-optional validators
3832 /// reading the positive distribution framing, future variant
3833 /// additions on
3834 /// [`crate::classification::DataClassification`]) binds through
3835 /// the SAME `data_is_public()` shape rather than restating either
3836 /// the resolver walk or the closed-set projection composition at
3837 /// the callsite. THEORY.md §VI.1 — generation over composition; a
3838 /// future [`crate::classification::DataClassification`] variant
3839 /// lands at ONE `ALL` entry + ONE `is_public` arm on the closed
3840 /// set and both surfaces pick it up mechanically.
3841 #[must_use]
3842 pub fn data_is_public(&self) -> bool {
3843 self.resolved_classification().data_is_public()
3844 }
3845
3846 /// Derived-boolean predicate — does this ephemeral spec's resolved
3847 /// [`Classification`]'s
3848 /// [`crate::classification::Horizon::direction`] slot (defaulted
3849 /// through [`crate::classification::OptimizationDirection::default =
3850 /// Minimize`] on absence) project to `true` under
3851 /// [`crate::classification::OptimizationDirection::prefers_lower`]?
3852 /// Byte-for-byte peer of
3853 /// [`crate::classification::Classification::direction_prefers_lower`]
3854 /// wrapped through the [`Self::resolved_classification`] resolver so
3855 /// an operator-omitted `:classification` slot on
3856 /// `(defephemeral …)` still answers via the substrate default. The
3857 /// ONE ephemeral-surface substrate primitive that owns the
3858 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3859 /// lower-is-better optimization-polarity question.
3860 ///
3861 /// # Fourteenth derived-nullary-boolean peer on the ephemeral surface — opens the optimization-direction axis
3862 ///
3863 /// Peer of the thirteen prior nullary-boolean substrate primitives
3864 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
3865 /// [`Self::horizon_requires_metric_axes`],
3866 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3867 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3868 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3869 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3870 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
3871 /// [`Self::data_is_public`]) on the ephemeral surface's
3872 /// (resolver-hop × derived-nullary-bool) shape — the FOURTEENTH
3873 /// peer overall and the FIRST peer threading the classification-
3874 /// `horizon.direction` axis on this surface. Opens the SIXTH
3875 /// classification axis into the ephemeral fixed-tag algebra after
3876 /// the horizon, calm, data, point, and substrate axes. The
3877 /// resolver-hop shape is byte-identical across all fourteen peers.
3878 ///
3879 /// # Semantics — resolver hop + derived-nullary-boolean
3880 ///
3881 /// `direction_prefers_lower()` returns `true` iff
3882 /// `self.resolved_classification().direction_prefers_lower()`. The
3883 /// resolver returns the authored [`Classification`] when present
3884 /// and the substrate default [`Classification::gate_compute`] on
3885 /// absence. Because [`Classification::gate_compute`] carries
3886 /// `horizon: Horizon::default()` whose `direction` field is `None`,
3887 /// and [`crate::classification::OptimizationDirection::default =
3888 /// Minimize`] projects `prefers_lower = true`, a bare ephemeral
3889 /// spec with no `:classification` slot answers `true` — every
3890 /// unadorned `(defephemeral …)` reads as lower-is-better under the
3891 /// substrate polarity default (safe under the asymptotic-health
3892 /// rate-window evaluator's convention: an operator must
3893 /// deliberately opt into Maximize polarity rather than the
3894 /// substrate silently flipping every unadorned Process onto the
3895 /// higher-is-better path). A regression that dropped the resolver
3896 /// hop, probed the wrong closed-set arm, or inverted the projection
3897 /// fails HERE at ONE narrow substrate site before drifting through
3898 /// every unadorned ephemeral spec's rate-window evaluator polarity.
3899 ///
3900 /// # Compounding — opens the optimization-direction axis on the ephemeral surface
3901 ///
3902 /// The ephemeral require-tag classifier composes this primitive as
3903 /// a fixed tag `prefers-lower-direction` on
3904 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3905 /// surface's `prefers-lower-direction` fixed tag on
3906 /// `POINT_FIXED_TAG_ARMS` via
3907 /// [`Classification::direction_prefers_lower`] directly. The
3908 /// two-surface parity contract holds by construction: both surfaces
3909 /// route through the SAME [`Classification::direction_prefers_lower`]
3910 /// primitive after the ephemeral surface pays ONE resolver hop.
3911 /// A future antisymmetric peer (`direction_prefers_higher`) closes
3912 /// the binary XOR partition on this axis — mirror of the calm-axis
3913 /// (`monotone-calm ⊕ coordination-required`) and data-axis
3914 /// (`public-data ⊕ data-restricted`) closures on this surface.
3915 ///
3916 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3917 /// preserves proofs; the classification-`horizon.direction`-axis
3918 /// derived-nullary-boolean probe body composes ONE resolver
3919 /// primitive ([`Self::resolved_classification`]) with ONE
3920 /// [`Classification`] primitive
3921 /// ([`Classification::direction_prefers_lower`]) so every
3922 /// downstream (the `prefers-lower-direction` fixed tags on both
3923 /// surfaces in tatara-check, future asymptotic-health rate-window
3924 /// / regression-detector evaluators, future variant additions on
3925 /// [`crate::classification::OptimizationDirection`]) binds through
3926 /// the SAME `direction_prefers_lower()` shape rather than restating
3927 /// either the resolver walk or the closed-set projection
3928 /// composition at the callsite. THEORY.md §VI.1 — generation over
3929 /// composition; a future
3930 /// [`crate::classification::OptimizationDirection`] variant lands
3931 /// at ONE `ALL` entry + ONE `prefers_lower` arm on the closed set
3932 /// and both surfaces pick it up mechanically.
3933 #[must_use]
3934 pub fn direction_prefers_lower(&self) -> bool {
3935 self.resolved_classification().direction_prefers_lower()
3936 }
3937
3938 /// POSITIVE-FRAMING PEER of [`Self::direction_prefers_lower`] —
3939 /// does this ephemeral spec's resolved [`Classification`]'s
3940 /// [`crate::classification::Horizon::direction`] slot (defaulted
3941 /// through [`crate::classification::OptimizationDirection::default =
3942 /// Minimize`] on absence) project to `true` under
3943 /// [`crate::classification::OptimizationDirection::prefers_higher`]?
3944 /// Byte-for-byte peer of
3945 /// [`crate::classification::Classification::direction_prefers_higher`]
3946 /// wrapped through the [`Self::resolved_classification`] resolver
3947 /// so an operator-omitted `:classification` slot on
3948 /// `(defephemeral …)` still answers via the substrate default. The
3949 /// ONE ephemeral-surface substrate primitive that owns the
3950 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3951 /// higher-is-better optimization-polarity question.
3952 ///
3953 /// # Fifteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the optimization-direction axis
3954 ///
3955 /// Peer of the fourteen prior nullary-boolean substrate primitives
3956 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
3957 /// [`Self::horizon_requires_metric_axes`],
3958 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3959 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3960 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3961 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3962 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
3963 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`]) on
3964 /// the ephemeral surface's (resolver-hop × derived-nullary-bool)
3965 /// shape — the FIFTEENTH peer overall and the SECOND peer
3966 /// threading the classification-`horizon.direction` axis on this
3967 /// surface. CLOSES the SIXTH classification axis into a binary XOR
3968 /// partition on the ephemeral surface after the horizon, calm,
3969 /// data, point, and substrate axes — completing the axis-coverage
3970 /// milestone on this surface: ALL SIX classification axes now
3971 /// have their partitions closed at the ephemeral-surface derived-
3972 /// nullary corner. The resolver-hop shape is byte-identical across
3973 /// all fifteen peers.
3974 ///
3975 /// # Semantics — resolver hop + derived-nullary-boolean
3976 ///
3977 /// `direction_prefers_higher()` returns `true` iff
3978 /// `self.resolved_classification().direction_prefers_higher()`.
3979 /// The resolver returns the authored [`Classification`] when
3980 /// present and the substrate default
3981 /// [`Classification::gate_compute`] on absence. Because
3982 /// [`Classification::gate_compute`] carries `horizon:
3983 /// Horizon::default()` whose `direction` field is `None`, and
3984 /// [`crate::classification::OptimizationDirection::default =
3985 /// Minimize`] projects `prefers_higher = false`, a bare ephemeral
3986 /// spec with no `:classification` slot answers `false` — every
3987 /// unadorned `(defephemeral …)` reads as lower-is-better under the
3988 /// substrate polarity default (safe under the asymptotic-health
3989 /// rate-window evaluator's convention: an operator must
3990 /// deliberately opt into Maximize polarity rather than the
3991 /// substrate silently flipping every unadorned Process onto the
3992 /// higher-is-better path). A regression that dropped the resolver
3993 /// hop, probed the wrong closed-set arm, or inverted the
3994 /// projection fails HERE at ONE narrow substrate site before
3995 /// drifting through every unadorned ephemeral spec's rate-window
3996 /// evaluator polarity.
3997 ///
3998 /// # Compounding — CLOSES the optimization-direction axis on the ephemeral surface
3999 ///
4000 /// The ephemeral require-tag classifier composes this primitive as
4001 /// a fixed tag `prefers-higher-direction` on
4002 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4003 /// surface's `prefers-higher-direction` fixed tag on
4004 /// `POINT_FIXED_TAG_ARMS` via
4005 /// [`Classification::direction_prefers_higher`] directly. The
4006 /// two-surface parity contract holds by construction: both
4007 /// surfaces route through the SAME
4008 /// [`Classification::direction_prefers_higher`] primitive after
4009 /// the ephemeral surface pays ONE resolver hop. SECOND
4010 /// optimization-direction-axis peer CLOSES the axis into the FULL
4011 /// binary XOR partition contract on this surface — the resolver-
4012 /// hop peer of the parent-composed
4013 /// `classification_direction_probes_form_binary_xor_partition_over_all`,
4014 /// mirror of the calm-axis (`monotone-calm ⊕ coordination-required`)
4015 /// and data-axis (`public-data ⊕ data-restricted`) closures on
4016 /// this surface.
4017 ///
4018 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4019 /// preserves proofs; the classification-`horizon.direction`-axis
4020 /// derived-nullary-boolean probe body composes ONE resolver
4021 /// primitive ([`Self::resolved_classification`]) with ONE
4022 /// [`Classification`] primitive
4023 /// ([`Classification::direction_prefers_higher`]) so every
4024 /// downstream (the `prefers-higher-direction` fixed tags on both
4025 /// surfaces in tatara-check, future asymptotic-health rate-window
4026 /// / regression-detector evaluators, future variant additions on
4027 /// [`crate::classification::OptimizationDirection`]) binds through
4028 /// the SAME `direction_prefers_higher()` shape rather than
4029 /// restating either the resolver walk or the closed-set projection
4030 /// composition at the callsite. THEORY.md §VI.1 — generation over
4031 /// composition; a future
4032 /// [`crate::classification::OptimizationDirection`] variant lands
4033 /// at ONE `ALL` entry + ONE `prefers_higher` arm on the closed set
4034 /// and both surfaces pick it up mechanically.
4035 #[must_use]
4036 pub fn direction_prefers_higher(&self) -> bool {
4037 self.resolved_classification().direction_prefers_higher()
4038 }
4039
4040 /// Derived-boolean predicate — does this ephemeral spec's resolved
4041 /// [`Classification`]'s `point_type` slot project to `Arity::One`
4042 /// under
4043 /// [`crate::classification::ConvergencePointType::input_arity`]?
4044 /// Byte-for-byte peer of
4045 /// [`crate::classification::Classification::input_arity_is_one`]
4046 /// wrapped through the [`Self::resolved_classification`] resolver
4047 /// so an operator-omitted `:classification` slot on
4048 /// `(defephemeral …)` still answers via the substrate default. The
4049 /// ONE ephemeral-surface substrate primitive that owns the
4050 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4051 /// single-input side of the DAG-composition input-arity projection.
4052 ///
4053 /// # Sixteenth derived-nullary-boolean peer on the ephemeral surface — opens the input-arity axis
4054 ///
4055 /// Peer of the fifteen prior nullary-boolean substrate primitives
4056 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4057 /// [`Self::horizon_requires_metric_axes`],
4058 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4059 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4060 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4061 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4062 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4063 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4064 /// [`Self::direction_prefers_higher`]) on the ephemeral surface's
4065 /// (resolver-hop × derived-nullary-bool) shape — the SIXTEENTH
4066 /// peer overall and the FIRST peer threading the classification-
4067 /// `point_type`-derived input-arity axis on this surface. Opens
4068 /// the SEVENTH classification axis into the ephemeral fixed-tag
4069 /// algebra after the horizon, calm, data, point-type, substrate,
4070 /// and optimization-direction axes. First peer on the derived-
4071 /// typed-projection stratum of the ephemeral surface — composes
4072 /// an extra closed-set-level projection hop
4073 /// ([`crate::classification::ConvergencePointType::input_arity`])
4074 /// compared to the sibling `point_is_*` triple that walks the raw
4075 /// `point_type` slot through the resolver. The resolver-hop shape
4076 /// is byte-identical across all sixteen peers.
4077 ///
4078 /// # Semantics — resolver hop + derived-nullary-boolean
4079 ///
4080 /// `input_arity_is_one()` returns `true` iff
4081 /// `self.resolved_classification().input_arity_is_one()`. The
4082 /// resolver returns the authored [`Classification`] when present
4083 /// and the substrate default [`Classification::gate_compute`] on
4084 /// absence. Because [`Classification::gate_compute`] carries
4085 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
4086 /// ephemeral spec with no `:classification` slot answers `false` —
4087 /// every unadorned `(defephemeral …)` lands in the multi-input
4088 /// bucket under the substrate default (`Gate` gates a
4089 /// many-to-one bucket dispatch, so the single-input bucket only
4090 /// applies to operator-authored specs on the `Transform | Fork |
4091 /// Broadcast | Observe` arms). A regression that dropped the
4092 /// resolver hop, probed the wrong closed-set arm, or crossed the
4093 /// wires with the sibling
4094 /// [`crate::classification::ConvergencePointType::output_arity`]
4095 /// projection (which disagrees on six of the eight variants) fails
4096 /// HERE at ONE narrow substrate site before drifting through
4097 /// every unadorned ephemeral spec's DAG-composition input-arity
4098 /// audit.
4099 ///
4100 /// # Compounding — opens the input-arity axis on the ephemeral surface
4101 ///
4102 /// The ephemeral require-tag classifier will compose this
4103 /// primitive as a fixed tag `single-input-arity` on
4104 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4105 /// surface's `single-input-arity` fixed tag on
4106 /// `POINT_FIXED_TAG_ARMS` via
4107 /// [`Classification::input_arity_is_one`] directly. The
4108 /// two-surface parity contract holds by construction: both
4109 /// surfaces route through the SAME
4110 /// [`Classification::input_arity_is_one`] primitive after the
4111 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
4112 /// peer ([`Self::input_arity_is_many`]) closes the binary XOR
4113 /// partition on this axis — mirror of the calm-axis
4114 /// (`monotone-calm ⊕ coordination-required`), data-axis
4115 /// (`public-data ⊕ data-restricted`), and optimization-direction-
4116 /// axis (`prefers-lower-direction ⊕ prefers-higher-direction`)
4117 /// closures on this surface.
4118 ///
4119 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4120 /// preserves proofs; the classification-`point_type`-derived
4121 /// input-arity-axis derived-nullary-boolean probe body composes
4122 /// ONE resolver primitive ([`Self::resolved_classification`])
4123 /// with ONE [`Classification`] primitive
4124 /// ([`Classification::input_arity_is_one`]) so every downstream
4125 /// (the future `single-input-arity` fixed tag on the ephemeral
4126 /// surface in tatara-check, future DAG-composition input-arity
4127 /// validators keying on the single-input framing, future variant
4128 /// additions on
4129 /// [`crate::classification::ConvergencePointType`]) binds through
4130 /// the SAME `input_arity_is_one()` shape rather than restating
4131 /// either the resolver walk or the two-hop closed-set projection
4132 /// composition at the callsite. THEORY.md §VI.1 — generation over
4133 /// composition; a future
4134 /// [`crate::classification::ConvergencePointType`] variant lands
4135 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
4136 /// and both surfaces pick it up mechanically.
4137 #[must_use]
4138 pub fn input_arity_is_one(&self) -> bool {
4139 self.resolved_classification().input_arity_is_one()
4140 }
4141
4142 /// ANTISYMMETRIC PEER of [`Self::input_arity_is_one`] — does
4143 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
4144 /// slot project to `Arity::Many` under
4145 /// [`crate::classification::ConvergencePointType::input_arity`]?
4146 /// Byte-for-byte peer of
4147 /// [`crate::classification::Classification::input_arity_is_many`]
4148 /// wrapped through the [`Self::resolved_classification`] resolver
4149 /// so an operator-omitted `:classification` slot on
4150 /// `(defephemeral …)` still answers via the substrate default. The
4151 /// ONE ephemeral-surface substrate primitive that owns the
4152 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4153 /// multi-input side of the DAG-composition input-arity projection.
4154 ///
4155 /// # Seventeenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the input-arity axis
4156 ///
4157 /// Peer of the sixteen prior nullary-boolean substrate primitives
4158 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4159 /// [`Self::horizon_requires_metric_axes`],
4160 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4161 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4162 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4163 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4164 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4165 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4166 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`])
4167 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4168 /// bool) shape — the SEVENTEENTH peer overall and the SECOND peer
4169 /// threading the classification-`point_type`-derived input-arity
4170 /// axis on this surface. CLOSES the SEVENTH classification axis
4171 /// into the FULL binary XOR partition contract
4172 /// `input_arity_is_one ⊕ input_arity_is_many` on the ephemeral
4173 /// surface — the resolver-hop peer of the parent-composed
4174 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`.
4175 /// The resolver-hop shape is byte-identical across all seventeen
4176 /// peers.
4177 ///
4178 /// # Semantics — resolver hop + derived-nullary-boolean
4179 ///
4180 /// `input_arity_is_many()` returns `true` iff
4181 /// `self.resolved_classification().input_arity_is_many()`. The
4182 /// resolver returns the authored [`Classification`] when present
4183 /// and the substrate default [`Classification::gate_compute`] on
4184 /// absence. Because [`Classification::gate_compute`] carries
4185 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
4186 /// ephemeral spec with no `:classification` slot answers `true` —
4187 /// every unadorned `(defephemeral …)` lands in the multi-input
4188 /// bucket under the substrate default. Direct antisymmetric
4189 /// mirror of [`Self::input_arity_is_one`] on the SAME resolver
4190 /// walk + SAME projection through the SAME closed set.
4191 ///
4192 /// # Compounding — CLOSES the input-arity axis on the ephemeral surface
4193 ///
4194 /// The ephemeral require-tag classifier will compose this
4195 /// primitive as a fixed tag `multi-input-arity` on
4196 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4197 /// surface's `multi-input-arity` fixed tag on
4198 /// `POINT_FIXED_TAG_ARMS` via
4199 /// [`Classification::input_arity_is_many`] directly. The
4200 /// two-surface parity contract holds by construction: both
4201 /// surfaces route through the SAME
4202 /// [`Classification::input_arity_is_many`] primitive after the
4203 /// ephemeral surface pays ONE resolver hop. SECOND input-arity-
4204 /// axis peer CLOSES the axis into the FULL binary XOR partition
4205 /// contract on this surface — the resolver-hop peer of the
4206 /// parent-composed
4207 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`,
4208 /// mirror of the calm-axis (`monotone-calm ⊕
4209 /// coordination-required`), data-axis (`public-data ⊕
4210 /// data-restricted`), and optimization-direction-axis
4211 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
4212 /// closures on this surface — the SEVENTH classification axis to
4213 /// reach the closed XOR partition landmark on the ephemeral
4214 /// resolver-hop surface, opening the derived-typed-projection
4215 /// stratum on this surface for the first time.
4216 ///
4217 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4218 /// preserves proofs; the classification-`point_type`-derived
4219 /// input-arity-axis derived-nullary-boolean probe body composes
4220 /// ONE resolver primitive ([`Self::resolved_classification`])
4221 /// with ONE [`Classification`] primitive
4222 /// ([`Classification::input_arity_is_many`]) so every downstream
4223 /// (the future `multi-input-arity` fixed tag on the ephemeral
4224 /// surface in tatara-check, future DAG-composition input-arity
4225 /// validators keying on the multi-input framing, future variant
4226 /// additions on
4227 /// [`crate::classification::ConvergencePointType`]) binds through
4228 /// the SAME `input_arity_is_many()` shape rather than restating
4229 /// either `!self.input_arity_is_one()` or the two-hop
4230 /// `self.resolved_classification().point_type.input_arity().is_many()`
4231 /// chain at each callsite. THEORY.md §VI.1 — generation over
4232 /// composition; a future
4233 /// [`crate::classification::ConvergencePointType`] variant lands
4234 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
4235 /// and both surfaces pick it up mechanically.
4236 #[must_use]
4237 pub fn input_arity_is_many(&self) -> bool {
4238 self.resolved_classification().input_arity_is_many()
4239 }
4240
4241 /// Derived-boolean predicate — does this ephemeral spec's resolved
4242 /// [`Classification`]'s `point_type` slot project to `Arity::One`
4243 /// under
4244 /// [`crate::classification::ConvergencePointType::output_arity`]?
4245 /// Byte-for-byte peer of
4246 /// [`crate::classification::Classification::output_arity_is_one`]
4247 /// wrapped through the [`Self::resolved_classification`] resolver
4248 /// so an operator-omitted `:classification` slot on
4249 /// `(defephemeral …)` still answers via the substrate default. The
4250 /// ONE ephemeral-surface substrate primitive that owns the
4251 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4252 /// single-output side of the DAG-composition output-arity projection.
4253 ///
4254 /// # Eighteenth derived-nullary-boolean peer on the ephemeral surface — opens the output-arity axis
4255 ///
4256 /// Peer of the seventeen prior nullary-boolean substrate primitives
4257 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4258 /// [`Self::horizon_requires_metric_axes`],
4259 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4260 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4261 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4262 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4263 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4264 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4265 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
4266 /// [`Self::input_arity_is_many`]) on the ephemeral surface's
4267 /// (resolver-hop × derived-nullary-bool) shape — the EIGHTEENTH
4268 /// peer overall and the FIRST peer threading the classification-
4269 /// `point_type`-derived OUTPUT-arity axis on this surface. Opens
4270 /// the EIGHTH classification axis into the ephemeral fixed-tag
4271 /// algebra after the horizon, calm, data, point-type, substrate,
4272 /// optimization-direction, and input-arity axes. SECOND peer on
4273 /// the derived-typed-projection stratum of the ephemeral surface
4274 /// (after [`Self::input_arity_is_one`]) — composes an extra
4275 /// closed-set-level projection hop
4276 /// ([`crate::classification::ConvergencePointType::output_arity`])
4277 /// compared to the sibling `point_is_*` triple that walks the raw
4278 /// `point_type` slot through the resolver. The resolver-hop shape
4279 /// is byte-identical across all eighteen peers.
4280 ///
4281 /// # Distinctness from the input-arity axis
4282 ///
4283 /// The input-arity and output-arity axes carve the eight-variant
4284 /// [`crate::classification::ConvergencePointType`] closed set into
4285 /// DISTINCT partitions — six of the eight variants (`Fork |
4286 /// Broadcast | Join | Gate | Select | Reduce`) DISAGREE between the
4287 /// two projections, and only the two endomorphic variants
4288 /// (`Transform | Observe` — both `(One, One)`) agree. The ephemeral
4289 /// resolver-hop surface inherits this distinctness verbatim: the
4290 /// absent-classification baseline (`gate_compute` → `point_type:
4291 /// Gate`) FLIPS between the two axes — `input_arity_is_one` is
4292 /// `false` on the baseline but `output_arity_is_one` is `true`.
4293 /// So `output_arity_is_one` is NOT a redundant restatement of
4294 /// `input_arity_is_one` even after both wrap through the SAME
4295 /// resolver.
4296 ///
4297 /// # Semantics — resolver hop + derived-nullary-boolean
4298 ///
4299 /// `output_arity_is_one()` returns `true` iff
4300 /// `self.resolved_classification().output_arity_is_one()`. The
4301 /// resolver returns the authored [`Classification`] when present
4302 /// and the substrate default [`Classification::gate_compute`] on
4303 /// absence. Because [`Classification::gate_compute`] carries
4304 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
4305 /// ephemeral spec with no `:classification` slot answers `true` —
4306 /// every unadorned `(defephemeral …)` lands in the single-output
4307 /// bucket under the substrate default (`Gate` gates a many-to-one
4308 /// bucket dispatch, so the multi-output bucket only applies to
4309 /// operator-authored specs on the `Fork | Broadcast` arms). A
4310 /// regression that dropped the resolver hop, probed the wrong
4311 /// closed-set arm, or crossed the wires with the sibling
4312 /// [`crate::classification::ConvergencePointType::input_arity`]
4313 /// projection (which disagrees on six of the eight variants) fails
4314 /// HERE at ONE narrow substrate site before drifting through every
4315 /// unadorned ephemeral spec's DAG-composition output-arity audit.
4316 ///
4317 /// # Compounding — opens the output-arity axis on the ephemeral surface
4318 ///
4319 /// The ephemeral require-tag classifier will compose this
4320 /// primitive as a fixed tag `single-output-arity` on
4321 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4322 /// surface's `single-output-arity` fixed tag on
4323 /// `POINT_FIXED_TAG_ARMS` via
4324 /// [`Classification::output_arity_is_one`] directly. The
4325 /// two-surface parity contract holds by construction: both
4326 /// surfaces route through the SAME
4327 /// [`Classification::output_arity_is_one`] primitive after the
4328 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
4329 /// peer ([`Self::output_arity_is_many`]) closes the binary XOR
4330 /// partition on this axis — mirror of the input-arity-axis
4331 /// (`input_arity_is_one ⊕ input_arity_is_many`), the calm-axis
4332 /// (`monotone-calm ⊕ coordination-required`), the data-axis
4333 /// (`public-data ⊕ data-restricted`), and the optimization-
4334 /// direction-axis (`prefers-lower-direction ⊕
4335 /// prefers-higher-direction`) closures on this surface,
4336 /// completing the DAG-composition arity PAIR on the ephemeral
4337 /// derived-typed-projection stratum.
4338 ///
4339 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4340 /// preserves proofs; the classification-`point_type`-derived
4341 /// output-arity-axis derived-nullary-boolean probe body composes
4342 /// ONE resolver primitive ([`Self::resolved_classification`])
4343 /// with ONE [`Classification`] primitive
4344 /// ([`Classification::output_arity_is_one`]) so every downstream
4345 /// (the future `single-output-arity` fixed tag on the ephemeral
4346 /// surface in tatara-check, future DAG-composition output-arity
4347 /// validators keying on the single-output framing, future variant
4348 /// additions on
4349 /// [`crate::classification::ConvergencePointType`]) binds through
4350 /// the SAME `output_arity_is_one()` shape rather than restating
4351 /// either the resolver walk or the two-hop closed-set projection
4352 /// composition at the callsite. THEORY.md §VI.1 — generation over
4353 /// composition; a future
4354 /// [`crate::classification::ConvergencePointType`] variant lands
4355 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
4356 /// and both surfaces pick it up mechanically.
4357 #[must_use]
4358 pub fn output_arity_is_one(&self) -> bool {
4359 self.resolved_classification().output_arity_is_one()
4360 }
4361
4362 /// ANTISYMMETRIC PEER of [`Self::output_arity_is_one`] — does
4363 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
4364 /// slot project to `Arity::Many` under
4365 /// [`crate::classification::ConvergencePointType::output_arity`]?
4366 /// Byte-for-byte peer of
4367 /// [`crate::classification::Classification::output_arity_is_many`]
4368 /// wrapped through the [`Self::resolved_classification`] resolver
4369 /// so an operator-omitted `:classification` slot on
4370 /// `(defephemeral …)` still answers via the substrate default. The
4371 /// ONE ephemeral-surface substrate primitive that owns the
4372 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4373 /// multi-output side of the DAG-composition output-arity projection.
4374 ///
4375 /// # Nineteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the output-arity axis
4376 ///
4377 /// Peer of the eighteen prior nullary-boolean substrate primitives
4378 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4379 /// [`Self::horizon_requires_metric_axes`],
4380 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4381 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4382 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4383 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4384 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4385 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4386 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
4387 /// [`Self::input_arity_is_many`], [`Self::output_arity_is_one`])
4388 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4389 /// bool) shape — the NINETEENTH peer overall and the SECOND peer
4390 /// threading the classification-`point_type`-derived OUTPUT-arity
4391 /// axis on this surface. CLOSES the EIGHTH classification axis
4392 /// into the FULL binary XOR partition contract
4393 /// `output_arity_is_one ⊕ output_arity_is_many` on the ephemeral
4394 /// surface — the resolver-hop peer of the parent-composed
4395 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`.
4396 /// The resolver-hop shape is byte-identical across all nineteen
4397 /// peers. Completes the DAG-composition arity PAIR on the
4398 /// ephemeral derived-typed-projection stratum
4399 /// (`input_arity_is_{one,many}` + `output_arity_is_{one,many}` on
4400 /// the SAME resolver walk through the SAME closed set).
4401 ///
4402 /// # Semantics — resolver hop + derived-nullary-boolean
4403 ///
4404 /// `output_arity_is_many()` returns `true` iff
4405 /// `self.resolved_classification().output_arity_is_many()`. The
4406 /// resolver returns the authored [`Classification`] when present
4407 /// and the substrate default [`Classification::gate_compute`] on
4408 /// absence. Because [`Classification::gate_compute`] carries
4409 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
4410 /// ephemeral spec with no `:classification` slot answers `false` —
4411 /// every unadorned `(defephemeral …)` lands in the single-output
4412 /// bucket under the substrate default. Direct antisymmetric
4413 /// mirror of [`Self::output_arity_is_one`] on the SAME resolver
4414 /// walk + SAME projection through the SAME closed set.
4415 ///
4416 /// # Compounding — CLOSES the output-arity axis on the ephemeral surface
4417 ///
4418 /// The ephemeral require-tag classifier will compose this
4419 /// primitive as a fixed tag `multi-output-arity` on
4420 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4421 /// surface's `multi-output-arity` fixed tag on
4422 /// `POINT_FIXED_TAG_ARMS` via
4423 /// [`Classification::output_arity_is_many`] directly. The
4424 /// two-surface parity contract holds by construction: both
4425 /// surfaces route through the SAME
4426 /// [`Classification::output_arity_is_many`] primitive after the
4427 /// ephemeral surface pays ONE resolver hop. SECOND output-arity-
4428 /// axis peer CLOSES the axis into the FULL binary XOR partition
4429 /// contract on this surface — the resolver-hop peer of the
4430 /// parent-composed
4431 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`,
4432 /// mirror of the input-arity-axis (`input_arity_is_one ⊕
4433 /// input_arity_is_many`), the calm-axis (`monotone-calm ⊕
4434 /// coordination-required`), the data-axis (`public-data ⊕
4435 /// data-restricted`), and the optimization-direction-axis
4436 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
4437 /// closures on this surface — the EIGHTH classification axis to
4438 /// reach the closed XOR partition landmark on the ephemeral
4439 /// resolver-hop surface, completing the DAG-composition arity
4440 /// PAIR on the derived-typed-projection stratum of this surface.
4441 ///
4442 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4443 /// preserves proofs; the classification-`point_type`-derived
4444 /// output-arity-axis derived-nullary-boolean probe body composes
4445 /// ONE resolver primitive ([`Self::resolved_classification`])
4446 /// with ONE [`Classification`] primitive
4447 /// ([`Classification::output_arity_is_many`]) so every downstream
4448 /// (the future `multi-output-arity` fixed tag on the ephemeral
4449 /// surface in tatara-check, future DAG-composition output-arity
4450 /// validators keying on the multi-output framing, future variant
4451 /// additions on
4452 /// [`crate::classification::ConvergencePointType`]) binds through
4453 /// the SAME `output_arity_is_many()` shape rather than restating
4454 /// either `!self.output_arity_is_one()` or the two-hop
4455 /// `self.resolved_classification().point_type.output_arity().is_many()`
4456 /// chain at each callsite. THEORY.md §VI.1 — generation over
4457 /// composition; a future
4458 /// [`crate::classification::ConvergencePointType`] variant lands
4459 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
4460 /// and both surfaces pick it up mechanically.
4461 #[must_use]
4462 pub fn output_arity_is_many(&self) -> bool {
4463 self.resolved_classification().output_arity_is_many()
4464 }
4465
4466 /// True iff this ephemeral spec's [`Self::routing`] slot is
4467 /// populated AND the inner [`RoutingSpec`]'s derived
4468 /// [`RoutingForm`] equals `kind` — the substrate primitive that
4469 /// owns the (`&EphemeralSpec`, [`RoutingForm`]) → `bool` presence-
4470 /// probe shape on the sugar-surface type.
4471 ///
4472 /// # Peer to [`crate::routing::RoutingSpec::has_form`]
4473 ///
4474 /// [`RoutingSpec::has_form`] carries the same `(&self, RoutingForm)
4475 /// -> bool` signature on the inner routing carrier reached through
4476 /// the Option gate; this peer composes byte-identical semantics on
4477 /// [`EphemeralSpec`]'s direct `routing: Option<RoutingSpec>` slot,
4478 /// so both surfaces' `routing-form-<kind>` require-tag families
4479 /// route through the SAME `RoutingSpec::has_form` primitive. A
4480 /// future normalization at the probe shape (a widened return
4481 /// carrying the derived [`RoutingForm`] variant, a debug-build
4482 /// assertion on operator-set vs defaulted overrides on the
4483 /// `stable_name_claim` bool, a fleet-wide warn on `Stable`
4484 /// combined with content-hashed hostnames) lands at ONE site per
4485 /// surface and every downstream `routing-form-<kind>` require-tag
4486 /// family + closed-set audit dispatcher picks it up mechanically.
4487 ///
4488 /// # Semantics — Option-gated derived-scalar match
4489 ///
4490 /// [`EphemeralSpec::routing`] is an `Option<RoutingSpec>`: `None`
4491 /// on an in-cluster-only ephemeral env (no per-instance edges
4492 /// declared), `Some(_)` when the operator authored the
4493 /// `:routing (…)` slot. `has_routing_form(kind)` returns `true`
4494 /// iff the slot is `Some(spec)` AND `spec.has_form(kind)` — the
4495 /// Option-parent gate short-circuits `false` on `None` regardless
4496 /// of `kind`, and the reachable arm reads the DERIVED
4497 /// [`RoutingForm`] through the ONE substrate composer
4498 /// [`RoutingForm::from_is_stable`] over the child
4499 /// `stable_name_claim` bool (a `false` default projects to
4500 /// [`RoutingForm::Instance`], a `true` operator override projects
4501 /// to [`RoutingForm::Stable`]).
4502 ///
4503 /// # Corner — (Option-parent × derived-scalar-child)
4504 ///
4505 /// SAME corner as the point surface's `routing-form-<kind>`
4506 /// family (via [`crate::routing::RoutingSpec::has_form`] reached
4507 /// through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`)
4508 /// — both surfaces' Option-parent hop threads through the SAME
4509 /// `Option<RoutingSpec>` field name on their respective sugar
4510 /// structs. The [`From<EphemeralSpec>`] lowering copies
4511 /// `e.routing → ProcessSpec::routing` byte-for-byte at the
4512 /// [`From`] impl in this module (see the `routing: e.routing`
4513 /// line), so the SAME `Option<RoutingSpec>` reaches both
4514 /// surfaces' `routing-form-<kind>` families through the SAME
4515 /// [`RoutingSpec::has_form`] walk. Distinct from
4516 /// [`Self::has_teardown_policy`] on this same surface, which
4517 /// walks a required-scalar-child through no Option-parent hop.
4518 ///
4519 /// # Compounding
4520 ///
4521 /// The ephemeral require-tag classifier composes this primitive
4522 /// with the closed-set `FromStr` autoderived on [`RoutingForm`]
4523 /// through the `strip_and_classify_prefixed_kind` substrate to
4524 /// publish a `routing-form-<kind>` prefix family byte-for-byte
4525 /// symmetrical with the point surface's family via
4526 /// [`crate::routing::RoutingSpec::has_form`]. A future third
4527 /// [`RoutingForm`] variant added to `ALL` (a hypothetical
4528 /// `Anchored` for "hold the claim only for a specific
4529 /// generation") reaches BOTH surfaces' `routing-form-<kind>`
4530 /// prefix families through the SAME closed-set walk with no
4531 /// per-caller edit — the two-surface symmetry means adding a
4532 /// variant on the closed set publishes it in lockstep across
4533 /// every downstream consumer.
4534 ///
4535 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
4536 /// preserves proofs — the Option-gated derived-scalar-carrier
4537 /// presence-probe body lives at ONE substrate site per surface
4538 /// so every downstream (`routing-form-<kind>` require-tag families
4539 /// on both surfaces in tatara-check, closed-set audit dispatchers,
4540 /// future variant additions on [`RoutingForm`]) binds through the
4541 /// SAME `has(kind)` shape rather than restating the
4542 /// `spec.routing.as_ref().is_some_and(|r| r.has_form(kind))`
4543 /// closure body at each call site). THEORY.md §VI.1 (generation
4544 /// over composition — a future variant lands at ONE `ALL` entry +
4545 /// one `as_str` arm on the closed set and the probe picks it up
4546 /// mechanically without further per-consumer edits).
4547 #[must_use]
4548 pub fn has_routing_form(&self, kind: RoutingForm) -> bool {
4549 self.routing.as_ref().is_some_and(|r| r.has_form(kind))
4550 }
4551
4552 /// True iff at least one declared export in `self.exports` would
4553 /// fire on the given terminal-reached [`ProcessPhase`] — the peer
4554 /// of [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4555 /// on the [`EphemeralSpec`] surface.
4556 ///
4557 /// # Semantics — byte-identical to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4558 ///
4559 /// Both surfaces walk the SAME slice-level substrate primitive
4560 /// [`ExportSpecSliceExt::has_applicable_at`] on their respective
4561 /// `Vec<ExportSpec>` slot: [`EphemeralSpec`]'s `exports` field is
4562 /// copied byte-for-byte into `EphemeralLifetime::exports` at the
4563 /// `From<EphemeralSpec>` lowering, so a `has_applicable_exports_at`
4564 /// query on the authored ephemeral spec answers identically to a
4565 /// `has_applicable_exports` query on the lowered `EphemeralLifetime`.
4566 /// A regression at the compound `(when, phase) → fires_on(phase)`
4567 /// walk fails at [`ExportSpecSliceExt::has_applicable_at`]'s tests
4568 /// rather than as silent drift at either surface's inherent method.
4569 ///
4570 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4571 ///
4572 /// Same shape, same axis, same body — the point-domain surface
4573 /// composes through `spec.lifetime.resolved_ephemeral().is_some_and(
4574 /// |e| e.exports.has_applicable_at(phase))`; the ephemeral sugar
4575 /// surface reads `self.exports.has_applicable_at(phase)` directly
4576 /// because `EphemeralSpec` stores `exports: Vec<ExportSpec>` as a
4577 /// top-level field. Both routes bind through THIS ONE slice-level
4578 /// primitive so a future normalization (widening the trigger from
4579 /// a stored discriminator to a computed predicate, adding a phase
4580 /// that composes across multiple trigger arms, threading a
4581 /// per-export justification back for editor tooltips) lands at ONE
4582 /// site and every downstream inherits the shift by construction.
4583 ///
4584 /// # Compounding
4585 ///
4586 /// The ephemeral require-tag classifier composes this primitive
4587 /// with the closed-set [`ProcessPhase`]'s autoderived `FromStr`
4588 /// through the `strip_and_classify_prefixed_kind` substrate to
4589 /// publish an `exports-fire-on-<phase>` closed-set prefix family
4590 /// byte-for-byte symmetrical with the point surface's family via
4591 /// `spec.lifetime.resolved_ephemeral().is_some_and(|e|
4592 /// e.exports.has_applicable_at(phase))`. A future twelfth
4593 /// [`ProcessPhase`] variant reaches BOTH surfaces' prefix families
4594 /// through the ONE [`crate::export::ExportTrigger::fires_on`]
4595 /// exhaustive match — either the new phase inherits a per-trigger
4596 /// fire rule at that single substrate site or it collapses to
4597 /// `false` for every trigger (the current non-terminal tail),
4598 /// without a per-caller edit anywhere else.
4599 ///
4600 /// A future normalization at the compound `(when, phase) →
4601 /// fires_on(phase)` walk (a widening that returns the applicable
4602 /// exports themselves rather than a bool, a debug-build assertion
4603 /// on redundant `Always`-triggered exports coexisting with an
4604 /// `OnAttested` peer, a fleet-wide warn on empty-export ephemerals
4605 /// declaring `OnAttested` postconditions) lands at the ONE
4606 /// slice-level substrate primitive [`ExportSpecSliceExt::has_applicable_at`]
4607 /// both this method and [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4608 /// compose against — so the two struct-level union methods stay
4609 /// symmetric by construction.
4610 ///
4611 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
4612 /// proofs — the walk composes the SAME slice-level substrate
4613 /// primitive on both this ephemeral surface and the
4614 /// [`crate::lifetime::EphemeralLifetime`] surface, so a regression
4615 /// at the compound `(when, phase) → fires_on(phase)` chain fails
4616 /// at ONE site rather than as silent drift between the two peers).
4617 /// THEORY.md §VI.1 (generation over composition — a future
4618 /// [`ProcessPhase`] variant or a future [`crate::export::ExportTrigger`]
4619 /// variant reaches both `exports-fire-on-<phase>` require-tag
4620 /// surfaces mechanically through the SAME closed-set walk).
4621 #[must_use]
4622 pub fn has_applicable_exports_at(&self, phase: ProcessPhase) -> bool {
4623 self.exports.has_applicable_at(phase)
4624 }
4625}
4626
4627impl From<EphemeralSpec> for ProcessSpec {
4628 fn from(e: EphemeralSpec) -> Self {
4629 let classification = e.classification.unwrap_or_else(default_ephemeral_class);
4630 let mut spec = Self {
4631 identity: crate::spec::IdentitySpec {
4632 parent: e.parent,
4633 name_override: None,
4634 },
4635 classification,
4636 intent: Intent {
4637 aplicacao: Some(e.aplicacao),
4638 ..Intent::default()
4639 },
4640 boundary: Boundary {
4641 preconditions: e.preconditions,
4642 postconditions: e.postconditions,
4643 timeout: e.verify_timeout,
4644 },
4645 compliance: Default::default(),
4646 depends_on: vec![],
4647 signals: Default::default(),
4648 // Routes through the ONE substrate composer
4649 // [`Lifetime::ephemeral`] — pre-lift this was one of
4650 // ELEVEN+ hand-authored `Lifetime { ephemeral: Some(<e>),
4651 // .. }` sites past the ★★ PRIME-DIRECTIVE ≥ 2 threshold.
4652 // See the composer's doc-comment for the full migration
4653 // rationale.
4654 lifetime: Lifetime::ephemeral(EphemeralLifetime {
4655 ttl: e.ttl,
4656 teardown_policy: e.teardown,
4657 max_concurrent: e.max_concurrent,
4658 exports: e.exports,
4659 }),
4660 // R5 — propagate routing template (None = no edges).
4661 routing: e.routing,
4662 // EncapsulatesSpec isn't exposed via EphemeralSpec sugar;
4663 // operators wanting Adopt/Observe author the full
4664 // (defpoint …) form. Sugar path stays greenfield-Manage.
4665 encapsulates: None,
4666 suspended: false,
4667 };
4668 // Belt-and-suspenders: make sure exactly-one Intent invariant holds.
4669 spec.intent.nix = None;
4670 spec.intent.flux = None;
4671 spec.intent.lisp = None;
4672 spec.intent.container = None;
4673 spec.intent.guest = None;
4674 spec
4675 }
4676}
4677
4678fn default_ephemeral_class() -> Classification {
4679 // Delegates through the substrate `(Gate, Compute)` baseline owner
4680 // so the shape lives at ONE workspace-wide site — see
4681 // [`Classification::gate_compute`] for the pre-lift ten-callsite
4682 // duplication history and the sibling-default correspondence
4683 // pinned there.
4684 Classification::gate_compute()
4685}
4686
4687/// Compile a `(defephemeral …)` Lisp source into named `EphemeralSpec` values.
4688pub fn compile_ephemeral_source(
4689 src: &str,
4690) -> tatara_lisp::Result<Vec<tatara_lisp::NamedDefinition<EphemeralSpec>>> {
4691 tatara_lisp::compile_named::<EphemeralSpec>(src)
4692}
4693
4694#[cfg(test)]
4695mod tests {
4696 use super::*;
4697 use crate::boundary::{assert_slice_refinement_composition_laws, ConditionKind};
4698 use crate::classification::{
4699 Arity, CalmClassification, ConvergencePointType, DataClassification, Horizon, HorizonKind,
4700 OptimizationDirection, SubstrateType,
4701 };
4702 use crate::intent::IntentVariant;
4703 use crate::lifetime::LifetimeVariant;
4704
4705 /// LANDMARK PIN — the (ephemeral-surface test-fixture ×
4706 /// [`Classification::gate_compute_with_axis`] on horizon-nested
4707 /// axes) sweep equivalence. Nine ephemeral-surface probe-sweep
4708 /// tests in this module (`has_horizon_kind_*`,
4709 /// `has_optimization_direction_*`, `horizon_terminates_*`,
4710 /// `horizon_requires_metric_axes_*`, `horizon_terminates_xor_*`)
4711 /// pre-sweep restated the SAME `let mut c =
4712 /// Classification::gate_compute(); c.horizon = Horizon { <slot>:
4713 /// populated, ..Horizon::default() }` five-line fixture at each
4714 /// callsite, mutating exactly ONE horizon-nested slot to
4715 /// `populated`; post-sweep each callsite reads
4716 /// [`Classification::gate_compute_with_axis(populated)`] — one
4717 /// line — and the four-baseline-slot restatement lives at ONE
4718 /// substrate primitive. This pin asserts byte-parity between the
4719 /// pre-sweep hand-authored `Horizon` struct-literal shape (both
4720 /// the [`HorizonKind::kind`] mutation shape AND the
4721 /// [`OptimizationDirection`]-into-`Some(_)` mutation shape) and
4722 /// the post-sweep composer output on every variant of each closed
4723 /// set, so a regression that either (a) changed
4724 /// [`ClassificationAxis for HorizonKind`] to stomp a non-`kind`
4725 /// sub-slot, (b) changed [`ClassificationAxis for OptimizationDirection`]
4726 /// to drop the `Some(...)` wrap, or (c) reintroduced a whole-
4727 /// `Horizon`-reset shape that dropped a sibling sub-slot would
4728 /// fail HERE at ONE landmark site before landing at the peer
4729 /// probe-sweep pins that use the composer.
4730 ///
4731 /// Byte-for-byte peer of the sibling landmark
4732 /// `with_axis_optimization_direction_overlay_wraps_variant_in_some`
4733 /// on the point-surface classification-module tests — this pin
4734 /// carries the same substrate contract through to the ephemeral-
4735 /// surface tests that consume the composer.
4736 #[test]
4737 fn gate_compute_with_axis_on_horizon_nested_axes_matches_hand_authored_shape() {
4738 for kind in HorizonKind::ALL {
4739 let via_composer = Classification::gate_compute_with_axis(kind);
4740 let mut via_hand_authored = Classification::gate_compute();
4741 via_hand_authored.horizon = Horizon {
4742 kind,
4743 ..Horizon::default()
4744 };
4745 assert_eq!(
4746 via_composer, via_hand_authored,
4747 "HorizonKind::{kind:?}: composer vs pre-sweep hand-authored struct-literal drift",
4748 );
4749 }
4750 for direction in OptimizationDirection::ALL {
4751 let via_composer = Classification::gate_compute_with_axis(direction);
4752 let mut via_hand_authored = Classification::gate_compute();
4753 via_hand_authored.horizon = Horizon {
4754 direction: Some(direction),
4755 ..Horizon::default()
4756 };
4757 assert_eq!(
4758 via_composer, via_hand_authored,
4759 "OptimizationDirection::{direction:?}: composer vs pre-sweep hand-authored struct-literal drift",
4760 );
4761 }
4762 }
4763
4764 /// Primitive-owner pin — `EphemeralSpec::with_classification_axis`
4765 /// on a `classification: None` carrier produces an ephemeral spec
4766 /// whose `classification` slot is
4767 /// `Some(Classification::gate_compute_with_axis(axis))` byte-for-
4768 /// byte on every axis-variant, and preserves every non-
4769 /// classification slot at its pre-call value. A regression that
4770 /// (a) failed to wrap the composed [`Classification`] in `Some(_)`
4771 /// on the `None`-arm, (b) mutated a sibling slot on `EphemeralSpec`
4772 /// through the axis overlay, or (c) picked a different `None`-arm
4773 /// fill-through than the sibling
4774 /// [`Self::resolved_classification`] resolver would fail HERE.
4775 #[test]
4776 fn with_classification_axis_on_none_arm_fills_through_gate_compute() {
4777 fn baseline() -> EphemeralSpec {
4778 EphemeralSpec {
4779 aplicacao: demo_overlay(),
4780 ttl: "2h".into(),
4781 teardown: TeardownPolicy::OnAttested,
4782 max_concurrent: 3,
4783 postconditions: vec![],
4784 preconditions: vec![],
4785 verify_timeout: Some("30m".into()),
4786 classification: None,
4787 parent: Some("seph.1".into()),
4788 exports: vec![],
4789 routing: None,
4790 }
4791 }
4792 // Direct-scalar axes: composer output matches
4793 // `Classification::gate_compute_with_axis(axis)` byte-for-byte,
4794 // wrapped in `Some(_)`.
4795 for kind in ConvergencePointType::ALL {
4796 let via_composer = baseline().with_classification_axis(kind);
4797 assert_eq!(
4798 via_composer.classification,
4799 Some(Classification::gate_compute_with_axis(kind)),
4800 "ConvergencePointType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4801 );
4802 }
4803 for kind in SubstrateType::ALL {
4804 let via_composer = baseline().with_classification_axis(kind);
4805 assert_eq!(
4806 via_composer.classification,
4807 Some(Classification::gate_compute_with_axis(kind)),
4808 "SubstrateType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4809 );
4810 }
4811 for kind in CalmClassification::ALL {
4812 let via_composer = baseline().with_classification_axis(kind);
4813 assert_eq!(
4814 via_composer.classification,
4815 Some(Classification::gate_compute_with_axis(kind)),
4816 "CalmClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4817 );
4818 }
4819 for kind in DataClassification::ALL {
4820 let via_composer = baseline().with_classification_axis(kind);
4821 assert_eq!(
4822 via_composer.classification,
4823 Some(Classification::gate_compute_with_axis(kind)),
4824 "DataClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4825 );
4826 }
4827 // Horizon-nested axes: same shape through the trait's
4828 // sub-slot overlay.
4829 for kind in HorizonKind::ALL {
4830 let via_composer = baseline().with_classification_axis(kind);
4831 assert_eq!(
4832 via_composer.classification,
4833 Some(Classification::gate_compute_with_axis(kind)),
4834 "HorizonKind::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4835 );
4836 }
4837 for direction in OptimizationDirection::ALL {
4838 let via_composer = baseline().with_classification_axis(direction);
4839 assert_eq!(
4840 via_composer.classification,
4841 Some(Classification::gate_compute_with_axis(direction)),
4842 "OptimizationDirection::{direction:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4843 );
4844 }
4845 // Non-classification slots: every one preserved byte-for-byte
4846 // across the overlay on every axis. Compare through JSON
4847 // round-trip since `AplicacaoIntent` / `ExportSpec` /
4848 // `RoutingSpec` do not carry `PartialEq`.
4849 for kind in ConvergencePointType::ALL {
4850 let via_composer = baseline().with_classification_axis(kind);
4851 let baseline_ref = baseline();
4852 assert_eq!(
4853 serde_json::to_string(&via_composer.aplicacao).unwrap(),
4854 serde_json::to_string(&baseline_ref.aplicacao).unwrap(),
4855 "aplicacao slot drifted under axis overlay for kind={kind:?}",
4856 );
4857 assert_eq!(via_composer.ttl, baseline_ref.ttl);
4858 assert_eq!(via_composer.teardown, baseline_ref.teardown);
4859 assert_eq!(via_composer.max_concurrent, baseline_ref.max_concurrent);
4860 assert_eq!(
4861 via_composer.postconditions.len(),
4862 baseline_ref.postconditions.len()
4863 );
4864 assert_eq!(
4865 via_composer.preconditions.len(),
4866 baseline_ref.preconditions.len()
4867 );
4868 assert_eq!(via_composer.verify_timeout, baseline_ref.verify_timeout);
4869 assert_eq!(via_composer.parent, baseline_ref.parent);
4870 assert_eq!(via_composer.exports.len(), baseline_ref.exports.len());
4871 assert!(via_composer.routing.is_none());
4872 }
4873 }
4874
4875 /// Primitive-owner pin —
4876 /// `EphemeralSpec::with_classification_axis` on a
4877 /// `classification: Some(prior)` carrier composes the axis
4878 /// overlay onto `prior` via [`ClassificationAxis::overlay`],
4879 /// preserving every OTHER axis slot on `prior`. Distinct from the
4880 /// `None`-arm pin above: the `Some(prior)` arm does NOT reset
4881 /// through [`Classification::gate_compute`], and consecutive
4882 /// `.with_classification_axis(...)` calls compose arbitrary
4883 /// N-axis conjunctions on the ephemeral surface with the same
4884 /// order-independence guarantee [`Classification::with_axis`]
4885 /// carries on distinct-slot axes.
4886 #[test]
4887 fn with_classification_axis_on_some_arm_chains_onto_prior() {
4888 fn baseline() -> EphemeralSpec {
4889 EphemeralSpec {
4890 aplicacao: demo_overlay(),
4891 ttl: "1h".into(),
4892 teardown: TeardownPolicy::Always,
4893 max_concurrent: 0,
4894 postconditions: vec![],
4895 preconditions: vec![],
4896 verify_timeout: None,
4897 classification: None,
4898 parent: None,
4899 exports: vec![],
4900 routing: None,
4901 }
4902 }
4903 // Prior authored point_type = Fork; overlay substrate = Storage
4904 // preserves the Fork point_type on the composed classification.
4905 let seeded = baseline().with_classification_axis(ConvergencePointType::Fork);
4906 let composed = seeded.with_classification_axis(SubstrateType::Storage);
4907 let classification = composed
4908 .classification
4909 .as_ref()
4910 .expect("with_classification_axis populates Some(_)");
4911 assert_eq!(classification.point_type, ConvergencePointType::Fork);
4912 assert_eq!(classification.substrate, SubstrateType::Storage);
4913 // Order independence on distinct-slot axes: swapping the axis
4914 // chain reads the SAME final classification.
4915 let forward = baseline()
4916 .with_classification_axis(ConvergencePointType::Fork)
4917 .with_classification_axis(SubstrateType::Storage)
4918 .with_classification_axis(CalmClassification::NonMonotone)
4919 .with_classification_axis(DataClassification::Pii)
4920 .classification
4921 .unwrap();
4922 let reverse = baseline()
4923 .with_classification_axis(DataClassification::Pii)
4924 .with_classification_axis(CalmClassification::NonMonotone)
4925 .with_classification_axis(SubstrateType::Storage)
4926 .with_classification_axis(ConvergencePointType::Fork)
4927 .classification
4928 .unwrap();
4929 assert_eq!(
4930 forward, reverse,
4931 "with_classification_axis chain must be order-independent on distinct-slot axes",
4932 );
4933 // Nested horizon-sub-slot overlays compose onto the same
4934 // carrier without stomping each other: the (kind, direction)
4935 // pair rides both chains.
4936 let paired = baseline()
4937 .with_classification_axis(HorizonKind::Asymptotic)
4938 .with_classification_axis(OptimizationDirection::Maximize)
4939 .classification
4940 .unwrap();
4941 assert_eq!(paired.horizon.kind, HorizonKind::Asymptotic);
4942 assert_eq!(
4943 paired.horizon.direction,
4944 Some(OptimizationDirection::Maximize)
4945 );
4946 }
4947
4948 /// Primitive-owner pin —
4949 /// `EphemeralSpec::with_classification_axis` composes byte-for-
4950 /// byte with the pre-sweep hand-authored two-shape callsite
4951 /// pattern that recurred at ~36 sites in
4952 /// `tatara-reconciler::bin::tatara-check`: either
4953 /// `let mut c = Classification::gate_compute(); c.<axis> =
4954 /// populated; EphemeralSpec { classification: Some(c), ..
4955 /// baseline }`, or the newer `let c =
4956 /// Classification::gate_compute_with_axis(populated); EphemeralSpec
4957 /// { classification: Some(c), ..baseline }`. Both restated
4958 /// pre-sweep shapes classify identically to
4959 /// `baseline.with_classification_axis(populated)` on every
4960 /// [`ClassificationAxis`] impl. A regression that drifted the
4961 /// composer body away from the pre-sweep shape (a stray reset of a
4962 /// non-classification slot, a stomping of a nested horizon sub-
4963 /// slot on the direct-scalar axes) fails HERE at ONE landmark site
4964 /// before drifting through the ~36 swept callsites in tatara-
4965 /// check.rs.
4966 #[test]
4967 fn with_classification_axis_matches_pre_sweep_hand_authored_shape() {
4968 fn baseline() -> EphemeralSpec {
4969 EphemeralSpec {
4970 aplicacao: demo_overlay(),
4971 ttl: "1h".into(),
4972 teardown: TeardownPolicy::Always,
4973 max_concurrent: 0,
4974 postconditions: vec![],
4975 preconditions: vec![],
4976 verify_timeout: None,
4977 classification: None,
4978 parent: None,
4979 exports: vec![],
4980 routing: None,
4981 }
4982 }
4983 // Direct-scalar axes: `<eph>.with_classification_axis(kind)`
4984 // matches the pre-sweep two-shape callsite pattern on every
4985 // ConvergencePointType variant.
4986 for kind in ConvergencePointType::ALL {
4987 let via_composer = baseline().with_classification_axis(kind);
4988 let mut hand_classification = Classification::gate_compute();
4989 hand_classification.point_type = kind;
4990 let via_hand = EphemeralSpec {
4991 classification: Some(hand_classification),
4992 ..baseline()
4993 };
4994 assert_eq!(
4995 via_composer.classification, via_hand.classification,
4996 "ConvergencePointType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
4997 );
4998 }
4999 for kind in SubstrateType::ALL {
5000 let via_composer = baseline().with_classification_axis(kind);
5001 let mut hand_classification = Classification::gate_compute();
5002 hand_classification.substrate = kind;
5003 let via_hand = EphemeralSpec {
5004 classification: Some(hand_classification),
5005 ..baseline()
5006 };
5007 assert_eq!(
5008 via_composer.classification, via_hand.classification,
5009 "SubstrateType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5010 );
5011 }
5012 for kind in CalmClassification::ALL {
5013 let via_composer = baseline().with_classification_axis(kind);
5014 let mut hand_classification = Classification::gate_compute();
5015 hand_classification.calm = kind;
5016 let via_hand = EphemeralSpec {
5017 classification: Some(hand_classification),
5018 ..baseline()
5019 };
5020 assert_eq!(
5021 via_composer.classification, via_hand.classification,
5022 "CalmClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5023 );
5024 }
5025 for kind in DataClassification::ALL {
5026 let via_composer = baseline().with_classification_axis(kind);
5027 let mut hand_classification = Classification::gate_compute();
5028 hand_classification.data_classification = kind;
5029 let via_hand = EphemeralSpec {
5030 classification: Some(hand_classification),
5031 ..baseline()
5032 };
5033 assert_eq!(
5034 via_composer.classification, via_hand.classification,
5035 "DataClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
5036 );
5037 }
5038 // Horizon-nested axes: composer matches the newer
5039 // `gate_compute_with_axis` shape used on the horizon-nested
5040 // sweep sites in tatara-check.rs.
5041 for kind in HorizonKind::ALL {
5042 let via_composer = baseline().with_classification_axis(kind);
5043 let via_hand = EphemeralSpec {
5044 classification: Some(Classification::gate_compute_with_axis(kind)),
5045 ..baseline()
5046 };
5047 assert_eq!(
5048 via_composer.classification, via_hand.classification,
5049 "HorizonKind::{kind:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
5050 );
5051 }
5052 for direction in OptimizationDirection::ALL {
5053 let via_composer = baseline().with_classification_axis(direction);
5054 let via_hand = EphemeralSpec {
5055 classification: Some(Classification::gate_compute_with_axis(direction)),
5056 ..baseline()
5057 };
5058 assert_eq!(
5059 via_composer.classification, via_hand.classification,
5060 "OptimizationDirection::{direction:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
5061 );
5062 }
5063 }
5064
5065 fn demo_overlay() -> AplicacaoIntent {
5066 AplicacaoIntent {
5067 chart_ref: "oci://ghcr.io/pleme-io/charts/lareira-demo-app".into(),
5068 version: "0.5.5".into(),
5069 profile: "all-in-one".into(),
5070 values_overlay: serde_json::json!({
5071 "cluster": { "name": "ephemeral-test-01", "namespace": "demo-test" },
5072 "data": { "mysql": { "persistence": { "enabled": false } } },
5073 "compliance": { "overlays": [] }
5074 }),
5075 release_name: Some("demo-app-consolidated".into()),
5076 target_namespace: Some("demo-test".into()),
5077 install_timeout: Some("25m".into()),
5078 }
5079 }
5080
5081 #[test]
5082 fn defaults_resolve_for_ephemeral_spec() {
5083 let e = EphemeralSpec {
5084 aplicacao: demo_overlay(),
5085 ttl: crate::lifetime::default_ephemeral_ttl(),
5086 teardown: TeardownPolicy::default(),
5087 max_concurrent: crate::lifetime::default_ephemeral_max_concurrent(),
5088 postconditions: vec![],
5089 preconditions: vec![],
5090 verify_timeout: None,
5091 classification: None,
5092 parent: None,
5093 exports: vec![],
5094 routing: None,
5095 };
5096 let ps: ProcessSpec = e.into();
5097 // Intent must resolve to Aplicacao.
5098 match ps.intent.variant().unwrap() {
5099 IntentVariant::Aplicacao(a) => {
5100 assert_eq!(a.profile, "all-in-one");
5101 assert_eq!(a.install_timeout.as_deref(), Some("25m"));
5102 }
5103 other => panic!("expected Aplicacao, got {other:?}"),
5104 }
5105 // Lifetime must resolve to Ephemeral with defaults.
5106 match ps.lifetime.variant().unwrap() {
5107 LifetimeVariant::Ephemeral(e) => {
5108 assert_eq!(e.ttl, "1h");
5109 assert_eq!(e.teardown_policy, TeardownPolicy::Always);
5110 }
5111 other => panic!("expected ephemeral, got {other:?}"),
5112 }
5113 // Default classification gates the Process at Compute/Internal.
5114 assert_eq!(ps.classification.point_type, ConvergencePointType::Gate);
5115 assert_eq!(ps.classification.substrate, SubstrateType::Compute);
5116 }
5117
5118 #[test]
5119 fn ephemeral_lisp_round_trip() {
5120 let src = r#"
5121 (defephemeral closed-loop-attest
5122 :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
5123 :version "0.5.5"
5124 :profile "all-in-one"
5125 :values-overlay (:cluster (:name "ephemeral-test-01")
5126 :data (:mysql (:persistence (:enabled #f)))
5127 :compliance (:overlays []))
5128 :release-name "demo-app-consolidated"
5129 :target-namespace "demo-test"
5130 :install-timeout "25m")
5131 :ttl "1h"
5132 :teardown OnAttested
5133 :max-concurrent 1
5134 :postconditions
5135 ((:kind HelmReleaseReleased
5136 :params (:name "demo-app-consolidated"
5137 :namespace "demo-test"))
5138 (:kind ClosedLoopAuth
5139 :params (:issuer (:service "demo-app-issuer" :port 8080)
5140 :consumer (:service "demo-app-gateway" :port 8000)
5141 :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
5142 "#;
5143 let defs = compile_ephemeral_source(src).expect("compile");
5144 assert_eq!(defs.len(), 1);
5145 let d = &defs[0];
5146 assert_eq!(d.name, "closed-loop-attest");
5147
5148 // Aplicacao body landed correctly.
5149 assert_eq!(
5150 d.spec.aplicacao.chart_ref,
5151 "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
5152 );
5153 assert_eq!(d.spec.aplicacao.profile, "all-in-one");
5154 assert_eq!(
5155 d.spec.aplicacao.target_namespace.as_deref(),
5156 Some("demo-test")
5157 );
5158 // values-overlay JSON is preserved.
5159 assert_eq!(
5160 d.spec.aplicacao.values_overlay["cluster"]["name"],
5161 "ephemeral-test-01"
5162 );
5163 // Boolean #f is preserved as a typed JSON bool (not the string "false").
5164 // tatara-lisp uses Scheme syntax for bools — `#t` / `#f`.
5165 assert_eq!(
5166 d.spec.aplicacao.values_overlay["data"]["mysql"]["persistence"]["enabled"],
5167 false
5168 );
5169
5170 // Lifetime knobs.
5171 assert_eq!(d.spec.ttl, "1h");
5172 assert_eq!(d.spec.teardown, TeardownPolicy::OnAttested);
5173 assert_eq!(d.spec.max_concurrent, 1);
5174
5175 // Two postconditions, both typed.
5176 assert_eq!(d.spec.postconditions.len(), 2);
5177 assert_eq!(
5178 d.spec.postconditions[0].kind,
5179 ConditionKind::HelmReleaseReleased
5180 );
5181 assert_eq!(d.spec.postconditions[1].kind, ConditionKind::ClosedLoopAuth);
5182
5183 // Lowers to ProcessSpec with the right shape.
5184 let ps: ProcessSpec = d.spec.clone().into();
5185 assert!(matches!(
5186 ps.intent.variant().unwrap(),
5187 IntentVariant::Aplicacao(_)
5188 ));
5189 assert!(matches!(
5190 ps.lifetime.variant().unwrap(),
5191 LifetimeVariant::Ephemeral(_)
5192 ));
5193 assert_eq!(ps.boundary.postconditions.len(), 2);
5194 }
5195
5196 /// End-to-end: the `:exports` slot on `(defephemeral …)` compiles
5197 /// into typed `ExportSpec` values via the Universal-Deserialize
5198 /// fallthrough — no per-domain keyword handlers needed.
5199 ///
5200 /// Receipts (empty-body source) is exercised via the Rust serde
5201 /// path only (see `export::tests::export_spec_serde_round_trip`).
5202 /// tatara-lisp's empty-kw-form `(:)` currently parses as a single-
5203 /// element array rather than a JSON `{}`; the same limitation
5204 /// affects `(:permanent)` on Lifetime. Tracked: extend the reader
5205 /// to accept `(:foo (:))` ⇒ `{"foo": {}}` as a typed-empty form,
5206 /// then re-enable Receipts here.
5207 #[test]
5208 fn exports_lisp_round_trip() {
5209 use crate::export::{ArtifactVariant, ChannelVariant, ExportTrigger, ReportFormat};
5210 let src = r#"
5211 (defephemeral closed-loop-attest
5212 :aplicacao (:chart-ref "oci://x"
5213 :version "1.0.0"
5214 :profile "minimal"
5215 :values-overlay ())
5216 :ttl "30m"
5217 :teardown OnAttested
5218 :exports
5219 ((:source (:test-report (:configmap "junit-results"
5220 :key "junit.xml"
5221 :format Junit))
5222 :channel (:nats-subject (:subject "pleme.pleme-dev.ephemeral.r1.test-report"
5223 :stream "EPHEMERAL_TEST_REPORTS"))
5224 :when OnAttested)
5225 (:source (:test-report (:configmap "junit-results"
5226 :key "junit.xml"
5227 :format Junit))
5228 :channel (:http-event (:signal-type "test-report"))
5229 :when Always)
5230 (:source (:run-marker (:labels (:run-id "r1" :phase "end")))
5231 :channel (:http-event (:signal-type "ephemeral-marker"))
5232 :when Always)))
5233 "#;
5234 let defs = compile_ephemeral_source(src).expect("compile");
5235 assert_eq!(defs.len(), 1);
5236 let d = &defs[0];
5237 assert_eq!(d.spec.exports.len(), 3);
5238
5239 // First export — TestReport → NATS subject + OnAttested
5240 let r = &d.spec.exports[0];
5241 match r.source.variant().unwrap() {
5242 ArtifactVariant::TestReport(tr) => {
5243 assert_eq!(tr.configmap, "junit-results");
5244 assert_eq!(tr.format, ReportFormat::Junit);
5245 }
5246 other => panic!("expected TestReport, got {other:?}"),
5247 }
5248 match r.channel.variant().unwrap() {
5249 ChannelVariant::NatsSubject(n) => {
5250 assert_eq!(n.subject, "pleme.pleme-dev.ephemeral.r1.test-report");
5251 assert_eq!(n.stream, "EPHEMERAL_TEST_REPORTS");
5252 }
5253 other => panic!("expected NatsSubject, got {other:?}"),
5254 }
5255 assert_eq!(r.when, ExportTrigger::OnAttested);
5256
5257 // Second export — TestReport → HTTP + Always
5258 let t = &d.spec.exports[1];
5259 match t.channel.variant().unwrap() {
5260 ChannelVariant::HttpEvent(h) => assert_eq!(h.signal_type, "test-report"),
5261 other => panic!("expected HttpEvent, got {other:?}"),
5262 }
5263 assert_eq!(t.when, ExportTrigger::Always);
5264
5265 // Third export — RunMarker (BTreeMap<String,String> round-trip).
5266 // tatara-lisp lowercases + normalizes keyword keys before
5267 // handing off to serde_json — kebab `:run-id` may land as
5268 // either `run-id` or `runId` depending on the reader path.
5269 // Accept either; the round-trip property under test is
5270 // "label survives compile" not "exact case-form".
5271 let m = &d.spec.exports[2];
5272 match m.source.variant().unwrap() {
5273 ArtifactVariant::RunMarker(rm) => {
5274 assert_eq!(rm.labels.len(), 2);
5275 let run_id = rm
5276 .labels
5277 .get("run-id")
5278 .or_else(|| rm.labels.get("runId"))
5279 .or_else(|| rm.labels.get("run_id"))
5280 .expect("run-id label present under some normalization");
5281 assert_eq!(run_id, "r1");
5282 assert_eq!(rm.labels.get("phase").map(String::as_str), Some("end"));
5283 }
5284 other => panic!("expected RunMarker, got {other:?}"),
5285 }
5286
5287 // Lowered ProcessSpec carries the exports through unchanged.
5288 let ps: ProcessSpec = d.spec.clone().into();
5289 assert_eq!(ps.lifetime.ephemeral.as_ref().unwrap().exports.len(), 3);
5290 }
5291
5292 // ── EphemeralSpec::has_condition_kind substrate pins ─────────────
5293 //
5294 // Fail-before-pass-after granularity:
5295 // `EphemeralSpec::has_condition_kind` did not exist before this
5296 // commit — the (preconditions ∪ postconditions .iter().any(|c|
5297 // c.kind == K)) union-probe shape lived at ONE struct-level site
5298 // (`Boundary::has_condition_kind` on the point surface's nested
5299 // [`Boundary`] slot). The lift adds the peer inherent method on the
5300 // [`EphemeralSpec`] sugar-surface so both struct-level union
5301 // callers compose against the SAME slice-level substrate primitive
5302 // [`ConditionSliceExt::has_kind`] in lockstep. A regression that
5303 // (a) hard-coded the arm to a single kind, (b) dropped the pre-
5304 // condition side of the OR (a re-inheritance of the pre-lift
5305 // ephemeral `closed-loop-auth` post-only shape at the union-tag
5306 // level), or (c) probed the wrong slot fails HERE at the substrate
5307 // primitive rather than as silent operator-facing drift at the
5308 // ephemeral `condition-<kind>` require-tag surface.
5309
5310 fn empty_ephemeral() -> EphemeralSpec {
5311 EphemeralSpec {
5312 aplicacao: AplicacaoIntent::chart_only("oci://ghcr.io/x", "1"),
5313 ttl: "1h".into(),
5314 teardown: TeardownPolicy::Always,
5315 max_concurrent: 0,
5316 postconditions: vec![],
5317 preconditions: vec![],
5318 verify_timeout: None,
5319 classification: None,
5320 parent: None,
5321 exports: vec![],
5322 routing: None,
5323 }
5324 }
5325
5326 fn cond(kind: ConditionKind) -> Condition {
5327 Condition {
5328 kind,
5329 params: serde_json::json!({}),
5330 }
5331 }
5332
5333 /// EMPTY-SPEC pin — a default [`EphemeralSpec`] (empty
5334 /// preconditions, empty postconditions) returns `false` for EVERY
5335 /// [`ConditionKind`]. Sweep `ConditionKind::ALL` so a new variant
5336 /// added without a matching arm in the presence probe surfaces at
5337 /// rustc's exhaustiveness gate on the ALL literal (arity forced by
5338 /// `[Self; 8]`) rather than as a silent false-positive at every
5339 /// downstream `condition-<kind>` ephemeral require-tag callsite.
5340 /// Byte-for-byte peer of
5341 /// `has_condition_kind_returns_false_on_empty_boundary_for_every_kind`
5342 /// on the [`Boundary`] surface.
5343 #[test]
5344 fn has_condition_kind_returns_false_on_empty_ephemeral_for_every_kind() {
5345 let spec = empty_ephemeral();
5346 for kind in ConditionKind::ALL {
5347 assert!(
5348 !spec.has_condition_kind(kind),
5349 "empty ephemeral spec must return false for {kind:?}",
5350 );
5351 }
5352 }
5353
5354 /// POSTCONDITION-only pin — an ephemeral spec that carries the
5355 /// kind on ONLY postconditions returns `true` for that kind,
5356 /// `false` for every other variant. Sweep the ALL × ALL cross so
5357 /// a regression that hard-coded the arm to a single kind or
5358 /// probed the wrong slot fails HERE at the substrate primitive.
5359 #[test]
5360 fn has_condition_kind_reads_ephemeral_postconditions_per_kind() {
5361 for populated in ConditionKind::ALL {
5362 let mut spec = empty_ephemeral();
5363 spec.postconditions.push(cond(populated));
5364 for query in ConditionKind::ALL {
5365 let expected = query == populated;
5366 assert_eq!(
5367 spec.has_condition_kind(query),
5368 expected,
5369 "ephemeral postcondition populated={populated:?}: \
5370 query {query:?} drifted",
5371 );
5372 }
5373 }
5374 }
5375
5376 /// PRECONDITION-only pin — mirrors the postcondition sweep on the
5377 /// other half of the union. Locks the union semantics on both
5378 /// halves separately so a regression that dropped the pre-
5379 /// condition side of the OR fails here even though the
5380 /// postcondition-side pin above passes.
5381 #[test]
5382 fn has_condition_kind_reads_ephemeral_preconditions_per_kind() {
5383 for populated in ConditionKind::ALL {
5384 let mut spec = empty_ephemeral();
5385 spec.preconditions.push(cond(populated));
5386 for query in ConditionKind::ALL {
5387 let expected = query == populated;
5388 assert_eq!(
5389 spec.has_condition_kind(query),
5390 expected,
5391 "ephemeral precondition populated={populated:?}: \
5392 query {query:?} drifted",
5393 );
5394 }
5395 }
5396 }
5397
5398 /// UNION pin — a kind that appears on preconditions returns
5399 /// `true` even when postconditions carries a DIFFERENT kind, and
5400 /// vice versa. Pins the OR-composition of the two halves so a
5401 /// regression that collapsed the union to an intersection (AND)
5402 /// silently reclassifies pre-only or post-only kinds as absent.
5403 /// Byte-for-byte peer of
5404 /// `has_condition_kind_unions_pre_and_post_condition_arms` on the
5405 /// [`Boundary`] surface.
5406 #[test]
5407 fn has_condition_kind_unions_pre_and_post_ephemeral_condition_arms() {
5408 let mut spec = empty_ephemeral();
5409 spec.preconditions
5410 .push(cond(ConditionKind::KustomizationHealthy));
5411 spec.postconditions
5412 .push(cond(ConditionKind::ClosedLoopAuth));
5413 assert!(
5414 spec.has_condition_kind(ConditionKind::KustomizationHealthy),
5415 "pre-only kind must resolve through the union",
5416 );
5417 assert!(
5418 spec.has_condition_kind(ConditionKind::ClosedLoopAuth),
5419 "post-only kind must resolve through the union",
5420 );
5421 assert!(
5422 !spec.has_condition_kind(ConditionKind::PromQL),
5423 "an absent kind must return false even with populated halves",
5424 );
5425 }
5426
5427 /// COMPOSITION pin — [`EphemeralSpec::has_condition_kind`] equals
5428 /// the OR of the two slice-level probes on the pre/post fields.
5429 /// The struct-level union body composes ONLY [`ConditionSliceExt::has_kind`]
5430 /// on each half; a regression that inlined a wide-net predicate
5431 /// (`.iter().any(|c| c.kind != kind).not()`, an `all` instead of
5432 /// `any`) drifts from the slice-level primitive here. Byte-for-
5433 /// byte peer of the
5434 /// `boundary_has_condition_kind_equals_or_of_half_slice_probes`
5435 /// composition pin on the [`Boundary`] surface.
5436 #[test]
5437 fn ephemeral_has_condition_kind_equals_or_of_half_slice_probes() {
5438 // Sweep every ConditionKind on both halves independently so the
5439 // cross of half-slice probes reaches the OR-composition body
5440 // exhaustively.
5441 for populated in ConditionKind::ALL {
5442 let mut spec = empty_ephemeral();
5443 spec.preconditions.push(cond(populated));
5444 spec.postconditions.push(cond(ConditionKind::PromQL));
5445 for query in ConditionKind::ALL {
5446 let via_or_of_halves =
5447 spec.preconditions.has_kind(query) || spec.postconditions.has_kind(query);
5448 assert_eq!(
5449 spec.has_condition_kind(query),
5450 via_or_of_halves,
5451 "populated={populated:?} query={query:?}: struct-level \
5452 union drifted from OR of slice-level probes",
5453 );
5454 }
5455 }
5456 }
5457
5458 // ── EphemeralSpec::has_(pre|post)condition_kind substrate pins ──
5459 //
5460 // Fail-before-pass-after granularity: the two half-slice arms did
5461 // not exist on the ephemeral surface before this commit — the
5462 // ephemeral require-tag classifier in `tatara-check` and the
5463 // `closed-loop-auth` fixed-tag arm reached
5464 // `spec.postconditions.has_kind(K)` through direct field access,
5465 // asymmetric with the union-arm [`EphemeralSpec::has_condition_kind`]
5466 // that already routed through the named struct method. The lift
5467 // closes the (precondition, postcondition, union) triad on the
5468 // ephemeral sugar surface so a future normalization at the
5469 // presence-probe shape lands at ONE site per surface for all
5470 // three arms.
5471
5472 /// EMPTY-SPEC pin — an ephemeral spec with no preconditions and
5473 /// no postconditions returns `false` for EVERY [`ConditionKind`]
5474 /// on both half-slice arms. Sweep `ConditionKind::ALL` so a new
5475 /// variant added without a matching arm surfaces at rustc's
5476 /// exhaustiveness gate on the ALL literal (arity forced by the
5477 /// closed-set array) rather than as a silent false-positive at
5478 /// every downstream require-tag callsite on the ephemeral
5479 /// surface.
5480 #[test]
5481 fn ephemeral_has_precondition_and_postcondition_kind_return_false_on_empty_spec() {
5482 let spec = empty_ephemeral();
5483 for kind in ConditionKind::ALL {
5484 assert!(
5485 !spec.has_precondition_kind(kind),
5486 "empty ephemeral must return false on precondition arm for {kind:?}",
5487 );
5488 assert!(
5489 !spec.has_postcondition_kind(kind),
5490 "empty ephemeral must return false on postcondition arm for {kind:?}",
5491 );
5492 }
5493 }
5494
5495 /// SLICE-SELECTIVITY pin (precondition arm) — an ephemeral spec
5496 /// with a kind on the precondition side ONLY resolves `true` at
5497 /// [`EphemeralSpec::has_precondition_kind`] and `false` at
5498 /// [`EphemeralSpec::has_postcondition_kind`]. Locks the (side-
5499 /// select, kind-select) partition so a regression that pointed
5500 /// the precondition arm at `self.postconditions` (a copy-paste
5501 /// from the sibling arm during the lift) surfaces HERE.
5502 #[test]
5503 fn ephemeral_has_precondition_kind_reads_preconditions_slice_only() {
5504 for populated in ConditionKind::ALL {
5505 let mut spec = empty_ephemeral();
5506 spec.preconditions.push(cond(populated));
5507 for query in ConditionKind::ALL {
5508 let expected_pre = query == populated;
5509 assert_eq!(
5510 spec.has_precondition_kind(query),
5511 expected_pre,
5512 "precondition-only populated={populated:?}: query {query:?} \
5513 drifted on ephemeral precondition arm",
5514 );
5515 assert!(
5516 !spec.has_postcondition_kind(query),
5517 "precondition-only populated={populated:?}: query {query:?} must \
5518 return false on ephemeral postcondition arm (postconditions is empty)",
5519 );
5520 }
5521 }
5522 }
5523
5524 /// SLICE-SELECTIVITY pin (postcondition arm) — mirror of the
5525 /// precondition-only sweep on the other half. Locks the
5526 /// postcondition arm's binding to `self.postconditions` so a
5527 /// regression that pointed it at `self.preconditions` fails HERE
5528 /// even though the precondition-arm pin above passes.
5529 #[test]
5530 fn ephemeral_has_postcondition_kind_reads_postconditions_slice_only() {
5531 for populated in ConditionKind::ALL {
5532 let mut spec = empty_ephemeral();
5533 spec.postconditions.push(cond(populated));
5534 for query in ConditionKind::ALL {
5535 let expected_post = query == populated;
5536 assert_eq!(
5537 spec.has_postcondition_kind(query),
5538 expected_post,
5539 "postcondition-only populated={populated:?}: query {query:?} \
5540 drifted on ephemeral postcondition arm",
5541 );
5542 assert!(
5543 !spec.has_precondition_kind(query),
5544 "postcondition-only populated={populated:?}: query {query:?} must \
5545 return false on ephemeral precondition arm (preconditions is empty)",
5546 );
5547 }
5548 }
5549 }
5550
5551 /// COMPOSITION-LAW pin — [`EphemeralSpec::has_condition_kind`]
5552 /// equals `has_precondition_kind(k) || has_postcondition_kind(k)`
5553 /// at EVERY (pre-populated, post-populated, query) triple on
5554 /// `ConditionKind::ALL`. Byte-for-byte peer of the
5555 /// `boundary_has_condition_kind_composes_precondition_and_postcondition_arms`
5556 /// composition-law pin on the [`Boundary`] surface — the
5557 /// two-surface parity contract binds the ephemeral sugar type
5558 /// and the point-domain boundary type through the SAME
5559 /// (`condition_kind = precondition_kind ∨ postcondition_kind`)
5560 /// composition, so every downstream `condition-<K>` require-tag
5561 /// classifier on either surface inherits the composition
5562 /// mechanically.
5563 #[test]
5564 fn ephemeral_has_condition_kind_composes_precondition_and_postcondition_arms() {
5565 for pre_kind in ConditionKind::ALL {
5566 for post_kind in ConditionKind::ALL {
5567 let mut spec = empty_ephemeral();
5568 spec.preconditions.push(cond(pre_kind));
5569 spec.postconditions.push(cond(post_kind));
5570 for query in ConditionKind::ALL {
5571 let via_arms =
5572 spec.has_precondition_kind(query) || spec.has_postcondition_kind(query);
5573 assert_eq!(
5574 spec.has_condition_kind(query),
5575 via_arms,
5576 "ephemeral union arm drifted from OR of half-slice arms: \
5577 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5578 );
5579 }
5580 }
5581 }
5582 }
5583
5584 /// SUBSTRATE-DELEGATION pin — the two half-slice arms on the
5585 /// ephemeral surface delegate verbatim to
5586 /// [`crate::boundary::ConditionSliceExt::has_kind`] on the
5587 /// underlying [`Vec<Condition>`] slice, no inline reimplementation.
5588 /// Sweep the full `ConditionKind::ALL` × `ConditionKind::ALL`
5589 /// cross so a regression that inlined a divergent walk at either
5590 /// arm surfaces HERE at the substrate boundary rather than as
5591 /// silent skew between the struct-level arm and the slice-level
5592 /// primitive.
5593 #[test]
5594 fn ephemeral_has_precondition_and_postcondition_kind_delegate_to_slice_has_kind() {
5595 for populated in ConditionKind::ALL {
5596 let mut spec = empty_ephemeral();
5597 spec.preconditions.push(cond(populated));
5598 spec.postconditions.push(cond(populated));
5599 for query in ConditionKind::ALL {
5600 assert_eq!(
5601 spec.has_precondition_kind(query),
5602 spec.preconditions.has_kind(query),
5603 "ephemeral precondition arm must delegate to preconditions.has_kind: \
5604 populated={populated:?} query={query:?}",
5605 );
5606 assert_eq!(
5607 spec.has_postcondition_kind(query),
5608 spec.postconditions.has_kind(query),
5609 "ephemeral postcondition arm must delegate to postconditions.has_kind: \
5610 populated={populated:?} query={query:?}",
5611 );
5612 }
5613 }
5614 }
5615
5616 // ── EphemeralSpec::find_(pre|post|)condition_kind widened triad ──
5617 //
5618 // Fail-before-pass-after granularity: the three widened
5619 // `find_*_kind` arms did not exist on the ephemeral surface before
5620 // this commit — the (widened `Option<&Condition>` return) axis
5621 // lived at ONE struct-level site (`Boundary::find_condition_kind`
5622 // on the point surface's nested [`Boundary`] slot). The lift adds
5623 // the peer inherent methods on the [`EphemeralSpec`] sugar-surface
5624 // so both struct-level widened callers compose against the SAME
5625 // slice-level substrate primitive
5626 // [`crate::boundary::ConditionSliceExt::find_kind`] in lockstep.
5627 // A regression that (a) hard-coded the arm to a single kind, (b)
5628 // reversed the walk order on the union (postcondition first), or
5629 // (c) collapsed `or_else` to `and_then` (silently narrowing the
5630 // union to an intersection) fails HERE at the substrate primitive
5631 // rather than as silent operator-facing drift at the ephemeral
5632 // require-tag surface.
5633
5634 /// EMPTY-SPEC pin (find-triad) — a default [`EphemeralSpec`]
5635 /// (empty preconditions, empty postconditions) returns `None`
5636 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
5637 /// `ConditionKind::ALL` × three-arm cross so a new variant added
5638 /// without a matching arm surfaces at rustc's exhaustiveness gate
5639 /// on the ALL literal (arity forced by the closed-set array)
5640 /// rather than as a silent false-`Some` at every downstream
5641 /// widened callsite on the ephemeral surface.
5642 #[test]
5643 fn ephemeral_find_condition_kind_triad_returns_none_on_empty_spec() {
5644 let spec = empty_ephemeral();
5645 for kind in ConditionKind::ALL {
5646 assert!(
5647 spec.find_precondition_kind(kind).is_none(),
5648 "empty ephemeral must return None on precondition find arm for {kind:?}",
5649 );
5650 assert!(
5651 spec.find_postcondition_kind(kind).is_none(),
5652 "empty ephemeral must return None on postcondition find arm for {kind:?}",
5653 );
5654 assert!(
5655 spec.find_condition_kind(kind).is_none(),
5656 "empty ephemeral must return None on union find arm for {kind:?}",
5657 );
5658 }
5659 }
5660
5661 /// SUBSTRATE-DELEGATION pin (ephemeral find-triad) — the three
5662 /// widened `find_*_kind` methods on [`EphemeralSpec`] delegate
5663 /// verbatim to [`crate::boundary::ConditionSliceExt::find_kind`]
5664 /// on the underlying [`Vec<Condition>`] slices, no inline
5665 /// reimplementation. The `find_condition_kind` union walks
5666 /// preconditions first then postconditions via `Option::or_else`.
5667 /// Sweep `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
5668 /// so a regression that (a) inlined a divergent walk at either
5669 /// half-slice arm, (b) reversed the union walk order on the
5670 /// ephemeral surface only (breaking two-surface parity with
5671 /// [`crate::boundary::Boundary::find_condition_kind`]), or (c)
5672 /// collapsed `or_else` to `and_then` surfaces HERE at the substrate
5673 /// boundary. Byte-for-byte peer of the point-domain
5674 /// `find_condition_kind_triad_delegates_to_slice_find_kind` pin.
5675 #[test]
5676 fn ephemeral_find_condition_kind_triad_delegates_to_slice_find_kind() {
5677 for pre_kind in ConditionKind::ALL {
5678 for post_kind in ConditionKind::ALL {
5679 let mut spec = empty_ephemeral();
5680 spec.preconditions.push(cond(pre_kind));
5681 spec.postconditions.push(cond(post_kind));
5682 for query in ConditionKind::ALL {
5683 let via_pre = spec.preconditions.find_kind(query);
5684 let via_post = spec.postconditions.find_kind(query);
5685 assert_eq!(
5686 spec.find_precondition_kind(query).map(|c| c.kind),
5687 via_pre.map(|c| c.kind),
5688 "ephemeral precondition find arm must delegate: \
5689 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5690 );
5691 assert_eq!(
5692 spec.find_postcondition_kind(query).map(|c| c.kind),
5693 via_post.map(|c| c.kind),
5694 "ephemeral postcondition find arm must delegate: \
5695 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5696 );
5697 let expected_union = via_pre.or(via_post).map(|c| c.kind);
5698 assert_eq!(
5699 spec.find_condition_kind(query).map(|c| c.kind),
5700 expected_union,
5701 "ephemeral union find arm must equal precondition.or_else(postcondition): \
5702 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5703 );
5704 }
5705 }
5706 }
5707 }
5708
5709 /// PRECONDITION-PRECEDENCE pin (ephemeral) — a kind authored on
5710 /// BOTH sides returns the precondition-side [`Condition`] from
5711 /// `find_condition_kind`. Byte-for-byte peer of the point-domain
5712 /// `find_condition_kind_returns_precondition_side_on_dual_populated`
5713 /// pin, so the two-surface parity contract binds the walk order
5714 /// on both surfaces through ONE composition law. Uses two params-
5715 /// distinguishable [`Condition`]s so a regression on the ephemeral
5716 /// surface only that reversed the walk order surfaces at the
5717 /// returned params payload rather than silently at the presence
5718 /// bit.
5719 #[test]
5720 fn ephemeral_find_condition_kind_returns_precondition_side_on_dual_populated() {
5721 let mut spec = empty_ephemeral();
5722 spec.preconditions.push(Condition {
5723 kind: ConditionKind::ClosedLoopAuth,
5724 params: serde_json::json!({ "side": "pre" }),
5725 });
5726 spec.postconditions.push(Condition {
5727 kind: ConditionKind::ClosedLoopAuth,
5728 params: serde_json::json!({ "side": "post" }),
5729 });
5730 let hit = spec
5731 .find_condition_kind(ConditionKind::ClosedLoopAuth)
5732 .expect("dual-populated ephemeral spec must resolve Some");
5733 assert_eq!(
5734 hit.params.get("side").and_then(serde_json::Value::as_str),
5735 Some("pre"),
5736 "ephemeral find_condition_kind must walk preconditions first",
5737 );
5738 }
5739
5740 /// STRUCT-LEVEL DELEGATION pin (ephemeral has ↔ find) — the three
5741 /// [`EphemeralSpec`] `has_*_kind` arms equal their widened peers'
5742 /// `.is_some()` projection at EVERY (pre-populated, post-populated,
5743 /// query) triple on `ConditionKind::ALL`. Byte-for-byte peer of
5744 /// the point-domain
5745 /// `boundary_has_triad_equals_find_triad_is_some_projection` pin,
5746 /// so both surfaces' has/find refinement bridge stays symmetric by
5747 /// construction — a future consumer that reads
5748 /// `spec.has_condition_kind(k)` as sugar for
5749 /// `spec.find_condition_kind(k).is_some()` on either surface stays
5750 /// typed against the SAME truth table across the two-surface
5751 /// parity contract.
5752 #[test]
5753 fn ephemeral_has_triad_equals_find_triad_is_some_projection() {
5754 for pre_kind in ConditionKind::ALL {
5755 for post_kind in ConditionKind::ALL {
5756 let mut spec = empty_ephemeral();
5757 spec.preconditions.push(cond(pre_kind));
5758 spec.postconditions.push(cond(post_kind));
5759 for query in ConditionKind::ALL {
5760 assert_eq!(
5761 spec.has_precondition_kind(query),
5762 spec.find_precondition_kind(query).is_some(),
5763 "ephemeral precondition has/find bridge drifted: \
5764 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5765 );
5766 assert_eq!(
5767 spec.has_postcondition_kind(query),
5768 spec.find_postcondition_kind(query).is_some(),
5769 "ephemeral postcondition has/find bridge drifted: \
5770 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5771 );
5772 assert_eq!(
5773 spec.has_condition_kind(query),
5774 spec.find_condition_kind(query).is_some(),
5775 "ephemeral union has/find bridge drifted: \
5776 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5777 );
5778 }
5779 }
5780 }
5781 }
5782
5783 // ── EphemeralSpec::iter_(pre|post|)condition_kind widened triad ──
5784 //
5785 // Fail-before-pass-after granularity: the three widened
5786 // `iter_*_kind` arms did not exist on the ephemeral surface before
5787 // this commit — the (widened `impl Iterator<Item = &Condition>`
5788 // stream) axis lived at ONE struct-level site
5789 // (`Boundary::iter_condition_kind` on the point surface's nested
5790 // [`Boundary`] slot). The lift adds the peer inherent methods on
5791 // the [`EphemeralSpec`] sugar-surface so both struct-level widened
5792 // callers compose against the SAME slice-level substrate primitive
5793 // [`crate::boundary::ConditionSliceExt::iter_kind`] in lockstep.
5794 // A regression that (a) hard-coded the arm to a single kind, (b)
5795 // reversed the chain order on the union (postcondition first), or
5796 // (c) collapsed the chain to a `.zip(...)` (silently narrowing the
5797 // union to an intersection-by-position) fails HERE at the
5798 // substrate primitive rather than as silent operator-facing drift
5799 // at the ephemeral require-tag surface.
5800
5801 /// EMPTY-SPEC pin (iter-triad) — a default [`EphemeralSpec`]
5802 /// (empty preconditions, empty postconditions) yields nothing
5803 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
5804 /// `ConditionKind::ALL` × three-arm cross so a new variant added
5805 /// without a matching arm surfaces at rustc's exhaustiveness gate
5806 /// on the ALL literal rather than as a silent phantom-yield at
5807 /// every downstream widened callsite on the ephemeral surface.
5808 #[test]
5809 fn ephemeral_iter_condition_kind_triad_yields_nothing_on_empty_spec() {
5810 let spec = empty_ephemeral();
5811 for kind in ConditionKind::ALL {
5812 assert_eq!(
5813 spec.iter_precondition_kind(kind).count(),
5814 0,
5815 "empty ephemeral must yield nothing on precondition iter arm for {kind:?}",
5816 );
5817 assert_eq!(
5818 spec.iter_postcondition_kind(kind).count(),
5819 0,
5820 "empty ephemeral must yield nothing on postcondition iter arm for {kind:?}",
5821 );
5822 assert_eq!(
5823 spec.iter_condition_kind(kind).count(),
5824 0,
5825 "empty ephemeral must yield nothing on union iter arm for {kind:?}",
5826 );
5827 }
5828 }
5829
5830 /// SUBSTRATE-DELEGATION pin (ephemeral iter-triad) — the three
5831 /// widened `iter_*_kind` methods on [`EphemeralSpec`] delegate
5832 /// verbatim to [`crate::boundary::ConditionSliceExt::iter_kind`]
5833 /// on the underlying [`Vec<Condition>`] slices, no inline
5834 /// reimplementation. The `iter_condition_kind` union chains
5835 /// preconditions first then postconditions via
5836 /// [`Iterator::chain`]. Sweep
5837 /// `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
5838 /// so a regression that (a) inlined a divergent walk at either
5839 /// half-slice arm, (b) reversed the chain order on the ephemeral
5840 /// surface only (breaking two-surface parity with
5841 /// [`crate::boundary::Boundary::iter_condition_kind`]), or (c)
5842 /// collapsed the chain to a `.zip(...)` surfaces HERE at the
5843 /// substrate boundary. Byte-for-byte peer of the point-domain
5844 /// `iter_condition_kind_triad_delegates_to_slice_iter_kind` pin.
5845 #[test]
5846 fn ephemeral_iter_condition_kind_triad_delegates_to_slice_iter_kind() {
5847 for pre_kind in ConditionKind::ALL {
5848 for post_kind in ConditionKind::ALL {
5849 let mut spec = empty_ephemeral();
5850 spec.preconditions.push(cond(pre_kind));
5851 spec.postconditions.push(cond(post_kind));
5852 for query in ConditionKind::ALL {
5853 let via_pre: Vec<_> = spec
5854 .preconditions
5855 .iter_kind(query)
5856 .map(|c| c.kind)
5857 .collect();
5858 let via_post: Vec<_> = spec
5859 .postconditions
5860 .iter_kind(query)
5861 .map(|c| c.kind)
5862 .collect();
5863 assert_eq!(
5864 spec.iter_precondition_kind(query)
5865 .map(|c| c.kind)
5866 .collect::<Vec<_>>(),
5867 via_pre,
5868 "ephemeral precondition iter arm must delegate: \
5869 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5870 );
5871 assert_eq!(
5872 spec.iter_postcondition_kind(query)
5873 .map(|c| c.kind)
5874 .collect::<Vec<_>>(),
5875 via_post,
5876 "ephemeral postcondition iter arm must delegate: \
5877 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5878 );
5879 let mut expected_union = via_pre.clone();
5880 expected_union.extend(via_post.iter().copied());
5881 assert_eq!(
5882 spec.iter_condition_kind(query)
5883 .map(|c| c.kind)
5884 .collect::<Vec<_>>(),
5885 expected_union,
5886 "ephemeral union iter arm must chain precondition ⨟ postcondition: \
5887 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5888 );
5889 }
5890 }
5891 }
5892 }
5893
5894 /// PRECONDITION-PRECEDENCE pin (ephemeral iter) — a kind
5895 /// authored on BOTH sides yields precondition-side matches
5896 /// FIRST in the union chain. Byte-for-byte peer of the
5897 /// point-domain
5898 /// `iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated`
5899 /// pin — the two-surface parity contract binds the chain order
5900 /// on both surfaces through ONE composition law. Uses two
5901 /// params-distinguishable [`Condition`]s so a regression on the
5902 /// ephemeral surface only that reversed the chain order surfaces
5903 /// at the returned params payload rather than silently at the
5904 /// count.
5905 #[test]
5906 fn ephemeral_iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated()
5907 {
5908 let mut spec = empty_ephemeral();
5909 spec.preconditions.push(Condition {
5910 kind: ConditionKind::ClosedLoopAuth,
5911 params: serde_json::json!({ "side": "pre-1" }),
5912 });
5913 spec.postconditions.push(Condition {
5914 kind: ConditionKind::ClosedLoopAuth,
5915 params: serde_json::json!({ "side": "post-1" }),
5916 });
5917 spec.postconditions.push(Condition {
5918 kind: ConditionKind::ClosedLoopAuth,
5919 params: serde_json::json!({ "side": "post-2" }),
5920 });
5921 let sides: Vec<_> = spec
5922 .iter_condition_kind(ConditionKind::ClosedLoopAuth)
5923 .map(|c| {
5924 c.params
5925 .get("side")
5926 .and_then(serde_json::Value::as_str)
5927 .unwrap_or_default()
5928 .to_owned()
5929 })
5930 .collect();
5931 assert_eq!(
5932 sides,
5933 vec!["pre-1".to_owned(), "post-1".to_owned(), "post-2".to_owned(),],
5934 "ephemeral iter_condition_kind must yield every precondition-side match before \
5935 any postcondition-side match (chain order pinned by two-surface parity)",
5936 );
5937 }
5938
5939 /// STRUCT-LEVEL DELEGATION pin (find ↔ iter on EphemeralSpec) —
5940 /// the three [`EphemeralSpec`] `find_*_kind` arms equal their
5941 /// widened peers' `.next()` projection at EVERY (pre-populated,
5942 /// post-populated, query) triple on `ConditionKind::ALL`.
5943 /// Byte-for-byte peer of the point-domain
5944 /// `boundary_find_triad_equals_iter_triad_next_projection` pin,
5945 /// so both surfaces' find/iter refinement bridge stays symmetric
5946 /// by construction across the two-surface parity contract.
5947 #[test]
5948 fn ephemeral_find_triad_equals_iter_triad_next_projection() {
5949 for pre_kind in ConditionKind::ALL {
5950 for post_kind in ConditionKind::ALL {
5951 let mut spec = empty_ephemeral();
5952 spec.preconditions.push(cond(pre_kind));
5953 spec.postconditions.push(cond(post_kind));
5954 for query in ConditionKind::ALL {
5955 assert_eq!(
5956 spec.find_precondition_kind(query).map(|c| c.kind),
5957 spec.iter_precondition_kind(query).next().map(|c| c.kind),
5958 "ephemeral precondition find/iter bridge drifted: \
5959 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5960 );
5961 assert_eq!(
5962 spec.find_postcondition_kind(query).map(|c| c.kind),
5963 spec.iter_postcondition_kind(query).next().map(|c| c.kind),
5964 "ephemeral postcondition find/iter bridge drifted: \
5965 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5966 );
5967 assert_eq!(
5968 spec.find_condition_kind(query).map(|c| c.kind),
5969 spec.iter_condition_kind(query).next().map(|c| c.kind),
5970 "ephemeral union find/iter bridge drifted: \
5971 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5972 );
5973 }
5974 }
5975 }
5976 }
5977
5978 // ── EphemeralSpec count triad — scalar cardinality peers ─────────
5979 //
5980 // Byte-for-byte peers of the point-domain `Boundary`
5981 // `count_(pre|post|)condition_kind` triad, tested at the ephemeral
5982 // sugar surface. Same SUM composition on the union arm, same
5983 // slice-level substrate delegation, same composition-law bridge
5984 // against the widened iter refinement.
5985
5986 /// EMPTY-SPEC pin (count-triad) — a default [`EphemeralSpec`]
5987 /// counts `0` from every arm of the count triad for EVERY
5988 /// [`ConditionKind`].
5989 #[test]
5990 fn ephemeral_count_condition_kind_triad_returns_zero_on_empty_spec() {
5991 let spec = empty_ephemeral();
5992 for kind in ConditionKind::ALL {
5993 assert_eq!(
5994 spec.count_precondition_kind(kind),
5995 0,
5996 "empty ephemeral must count 0 on precondition arm for {kind:?}",
5997 );
5998 assert_eq!(
5999 spec.count_postcondition_kind(kind),
6000 0,
6001 "empty ephemeral must count 0 on postcondition arm for {kind:?}",
6002 );
6003 assert_eq!(
6004 spec.count_condition_kind(kind),
6005 0,
6006 "empty ephemeral must count 0 on union arm for {kind:?}",
6007 );
6008 }
6009 }
6010
6011 /// SUBSTRATE-DELEGATION pin (ephemeral count-triad) — the three
6012 /// widened `count_*_kind` methods on [`EphemeralSpec`] delegate
6013 /// verbatim to [`crate::boundary::ConditionSliceExt::count_kind`]
6014 /// on the underlying [`Vec<Condition>`] slices. The
6015 /// `count_condition_kind` union SUMS preconditions and
6016 /// postconditions. Byte-for-byte peer of the point-domain
6017 /// `boundary_count_condition_kind_triad_delegates_and_sums_slice_count_kind`
6018 /// pin; a regression that (a) subtracted rather than summed, (b)
6019 /// collapsed the sum to [`std::cmp::max`], or (c) inlined a
6020 /// divergent count at either half-slice arm on the ephemeral
6021 /// surface only (breaking two-surface parity with [`Boundary`])
6022 /// surfaces HERE.
6023 #[test]
6024 fn ephemeral_count_condition_kind_triad_delegates_and_sums_slice_count_kind() {
6025 for pre_kind in ConditionKind::ALL {
6026 for post_kind in ConditionKind::ALL {
6027 let mut spec = empty_ephemeral();
6028 spec.preconditions.push(cond(pre_kind));
6029 spec.postconditions.push(cond(post_kind));
6030 for query in ConditionKind::ALL {
6031 let via_pre = spec.preconditions.count_kind(query);
6032 let via_post = spec.postconditions.count_kind(query);
6033 assert_eq!(
6034 spec.count_precondition_kind(query),
6035 via_pre,
6036 "ephemeral precondition count arm must delegate: \
6037 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6038 );
6039 assert_eq!(
6040 spec.count_postcondition_kind(query),
6041 via_post,
6042 "ephemeral postcondition count arm must delegate: \
6043 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6044 );
6045 assert_eq!(
6046 spec.count_condition_kind(query),
6047 via_pre + via_post,
6048 "ephemeral union count arm must SUM pre + post: \
6049 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6050 );
6051 }
6052 }
6053 }
6054 }
6055
6056 /// STRUCT-LEVEL DELEGATION pin (count ↔ iter on EphemeralSpec) —
6057 /// the three [`EphemeralSpec`] `count_*_kind` arms equal their
6058 /// widened peers' `.count()` projection at EVERY (pre-populated
6059 /// twice, post-populated, query) triple. Byte-for-byte peer of
6060 /// the point-domain
6061 /// `boundary_count_triad_equals_iter_triad_count_projection`
6062 /// pin. Uses two-preconditions authoring so the union arm's SUM
6063 /// composition witnesses a nontrivial cardinality (rather than
6064 /// coinciding with the presence bit).
6065 #[test]
6066 fn ephemeral_count_triad_equals_iter_triad_count_projection() {
6067 for pre_kind in ConditionKind::ALL {
6068 for post_kind in ConditionKind::ALL {
6069 let mut spec = empty_ephemeral();
6070 spec.preconditions.push(cond(pre_kind));
6071 spec.preconditions.push(cond(pre_kind));
6072 spec.postconditions.push(cond(post_kind));
6073 for query in ConditionKind::ALL {
6074 assert_eq!(
6075 spec.count_precondition_kind(query),
6076 spec.iter_precondition_kind(query).count(),
6077 "ephemeral precondition count/iter bridge drifted: \
6078 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6079 );
6080 assert_eq!(
6081 spec.count_postcondition_kind(query),
6082 spec.iter_postcondition_kind(query).count(),
6083 "ephemeral postcondition count/iter bridge drifted: \
6084 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6085 );
6086 assert_eq!(
6087 spec.count_condition_kind(query),
6088 spec.iter_condition_kind(query).count(),
6089 "ephemeral union count/iter bridge drifted: \
6090 pre={pre_kind:?} post={post_kind:?} query={query:?}",
6091 );
6092 }
6093 }
6094 }
6095 }
6096
6097 // ── EphemeralSpec distinct-set triad — substrate-delegation pin ──
6098 //
6099 // The (precondition, postcondition, condition-union) distinct-set
6100 // triad on [`EphemeralSpec`] delegates to the slice-level substrate
6101 // primitive [`crate::boundary::ConditionSliceExt::distinct_kinds`]
6102 // on each half-slice and composes the union via
6103 // [`Self::has_condition_kind`] over [`ConditionKind::ALL`] — byte-
6104 // for-byte peer of the point-surface distinct-set triad on
6105 // [`crate::boundary::Boundary`]. The two-surface parity contract
6106 // now covers FIVE refinements on the condition axis: the four
6107 // point-probe refinements (has / find / iter / count) AND the ONE
6108 // closed-set-inversion refinement (distinct-set) on both surfaces.
6109
6110 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-kind-count
6111 /// triad) — the three `distinct_*_kind_count` methods on
6112 /// [`EphemeralSpec`] delegate to the slice-level substrate
6113 /// primitive [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
6114 /// over the two `Vec<Condition>` slots and compose the union
6115 /// scalar via `ConditionKind::ALL.filter(|k|
6116 /// has_condition_kind(*k)).count()`. Byte-for-byte peer of the
6117 /// point-surface pin
6118 /// `distinct_condition_kind_count_triad_delegates_to_slice_distinct_kind_count`
6119 /// on [`crate::boundary::Boundary`] — the two-surface parity
6120 /// contract now binds every downstream scalar-cardinality consumer
6121 /// on either surface to the SAME closed-set walk through ONE
6122 /// substrate rather than through per-surface `.distinct_*_kinds().len()`
6123 /// re-materializations that pay for a heap allocation.
6124 #[test]
6125 fn ephemeral_distinct_condition_kind_count_triad_delegates_and_matches_distinct_kinds_len() {
6126 // Empty spec — every arm returns 0.
6127 let spec = empty_ephemeral();
6128 for kind in ConditionKind::ALL {
6129 assert_eq!(
6130 spec.distinct_precondition_kind_count(),
6131 0,
6132 "empty ephemeral spec must return 0 on distinct_precondition_kind_count, kind={kind:?}",
6133 );
6134 assert_eq!(
6135 spec.distinct_postcondition_kind_count(),
6136 0,
6137 "empty ephemeral spec must return 0 on distinct_postcondition_kind_count, kind={kind:?}",
6138 );
6139 assert_eq!(
6140 spec.distinct_condition_kind_count(),
6141 0,
6142 "empty ephemeral spec must return 0 on distinct_condition_kind_count, kind={kind:?}",
6143 );
6144 }
6145
6146 for pre_kind in ConditionKind::ALL {
6147 for post_kind in ConditionKind::ALL {
6148 let mut spec = empty_ephemeral();
6149 spec.preconditions.push(cond(pre_kind));
6150 spec.postconditions.push(cond(post_kind));
6151
6152 assert_eq!(
6153 spec.distinct_precondition_kind_count(),
6154 spec.preconditions.distinct_kind_count(),
6155 "EphemeralSpec::distinct_precondition_kind_count must delegate verbatim to \
6156 preconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6157 );
6158 assert_eq!(
6159 spec.distinct_precondition_kind_count(),
6160 spec.distinct_precondition_kinds().len(),
6161 "EphemeralSpec::distinct_precondition_kind_count must equal \
6162 distinct_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6163 );
6164 assert_eq!(
6165 spec.distinct_postcondition_kind_count(),
6166 spec.postconditions.distinct_kind_count(),
6167 "EphemeralSpec::distinct_postcondition_kind_count must delegate verbatim to \
6168 postconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6169 );
6170 assert_eq!(
6171 spec.distinct_postcondition_kind_count(),
6172 spec.distinct_postcondition_kinds().len(),
6173 "EphemeralSpec::distinct_postcondition_kind_count must equal \
6174 distinct_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6175 );
6176 let expected_union_count = if pre_kind == post_kind { 1 } else { 2 };
6177 assert_eq!(
6178 spec.distinct_condition_kind_count(),
6179 expected_union_count,
6180 "EphemeralSpec::distinct_condition_kind_count must count distinct union kinds \
6181 for pre={pre_kind:?} post={post_kind:?}",
6182 );
6183 assert_eq!(
6184 spec.distinct_condition_kind_count(),
6185 spec.distinct_condition_kinds().len(),
6186 "EphemeralSpec::distinct_condition_kind_count must equal \
6187 distinct_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6188 );
6189 }
6190 }
6191 }
6192
6193 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-set triad)
6194 /// — the three `distinct_*_kinds` methods on [`EphemeralSpec`]
6195 /// delegate to the slice-level substrate primitive over the two
6196 /// `Vec<Condition>` slots and compose the union via
6197 /// `ConditionKind::ALL.filter(|k| has_condition_kind(*k))`. Byte-
6198 /// for-byte peer of the point-surface pin
6199 /// `distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds`
6200 /// on [`crate::boundary::Boundary`] — the two-surface parity
6201 /// contract binds every downstream distinct-set consumer on either
6202 /// surface to the SAME closed-set-inversion primitive through ONE
6203 /// substrate rather than through per-surface re-authored sweeps.
6204 #[test]
6205 fn ephemeral_distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds() {
6206 for pre_kind in ConditionKind::ALL {
6207 for post_kind in ConditionKind::ALL {
6208 let mut spec = empty_ephemeral();
6209 spec.preconditions.push(cond(pre_kind));
6210 spec.postconditions.push(cond(post_kind));
6211
6212 assert_eq!(
6213 spec.distinct_precondition_kinds(),
6214 spec.preconditions.distinct_kinds(),
6215 "EphemeralSpec::distinct_precondition_kinds must delegate verbatim to \
6216 preconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
6217 );
6218 assert_eq!(
6219 spec.distinct_postcondition_kinds(),
6220 spec.postconditions.distinct_kinds(),
6221 "EphemeralSpec::distinct_postcondition_kinds must delegate verbatim to \
6222 postconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
6223 );
6224 let expected_union: Vec<_> = ConditionKind::ALL
6225 .into_iter()
6226 .filter(|k| pre_kind == *k || post_kind == *k)
6227 .collect();
6228 assert_eq!(
6229 spec.distinct_condition_kinds(),
6230 expected_union,
6231 "EphemeralSpec::distinct_condition_kinds must equal ConditionKind::ALL-ordered \
6232 set-union of the two half-slice distinct-sets for pre={pre_kind:?} post={post_kind:?}",
6233 );
6234 }
6235 }
6236 }
6237
6238 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set triad) —
6239 /// the three `missing_*_kinds` methods on [`EphemeralSpec`]
6240 /// delegate to the slice-level substrate primitive
6241 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over the
6242 /// two `Vec<Condition>` slots and compose the union via
6243 /// `ConditionKind::ALL.filter(|k| !has_condition_kind(*k))`. Sweep
6244 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
6245 /// `missing_condition_kinds_triad_delegates_to_slice_missing_kinds`
6246 /// on the point-domain [`crate::boundary::Boundary`] surface —
6247 /// both peers compose against the SAME slice-level substrate
6248 /// primitive so a regression at the per-slice complement walk
6249 /// fails at that primitive's tests rather than as silent drift at
6250 /// either struct-level arm.
6251 #[test]
6252 fn ephemeral_missing_condition_kinds_triad_delegates_to_slice_missing_kinds() {
6253 // Empty ephemeral spec — every arm returns ConditionKind::ALL.
6254 let empty = empty_ephemeral();
6255 let all_kinds = ConditionKind::ALL.to_vec();
6256 assert_eq!(
6257 empty.missing_precondition_kinds(),
6258 all_kinds,
6259 "empty ephemeral spec must return ConditionKind::ALL on missing_precondition_kinds",
6260 );
6261 assert_eq!(
6262 empty.missing_postcondition_kinds(),
6263 all_kinds,
6264 "empty ephemeral spec must return ConditionKind::ALL on missing_postcondition_kinds",
6265 );
6266 assert_eq!(
6267 empty.missing_condition_kinds(),
6268 all_kinds,
6269 "empty ephemeral spec must return ConditionKind::ALL on missing_condition_kinds",
6270 );
6271
6272 for pre_kind in ConditionKind::ALL {
6273 for post_kind in ConditionKind::ALL {
6274 let mut spec = empty_ephemeral();
6275 spec.preconditions.push(cond(pre_kind));
6276 spec.postconditions.push(cond(post_kind));
6277
6278 assert_eq!(
6279 spec.missing_precondition_kinds(),
6280 spec.preconditions.missing_kinds(),
6281 "EphemeralSpec::missing_precondition_kinds must delegate verbatim to \
6282 preconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
6283 );
6284 assert_eq!(
6285 spec.missing_postcondition_kinds(),
6286 spec.postconditions.missing_kinds(),
6287 "EphemeralSpec::missing_postcondition_kinds must delegate verbatim to \
6288 postconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
6289 );
6290 // Union: a kind is missing from the union iff it is
6291 // missing from BOTH half-slices (SET-INTERSECTION).
6292 let expected_union: Vec<_> = ConditionKind::ALL
6293 .into_iter()
6294 .filter(|k| pre_kind != *k && post_kind != *k)
6295 .collect();
6296 assert_eq!(
6297 spec.missing_condition_kinds(),
6298 expected_union,
6299 "EphemeralSpec::missing_condition_kinds must equal ConditionKind::ALL-ordered \
6300 set-INTERSECTION of the two half-slice missing-sets for pre={pre_kind:?} post={post_kind:?}",
6301 );
6302 // Partition invariant (distinct ∪ missing == ALL, disjoint).
6303 let distinct = spec.distinct_condition_kinds();
6304 let missing = spec.missing_condition_kinds();
6305 for kind in ConditionKind::ALL {
6306 assert!(
6307 distinct.contains(&kind) ^ missing.contains(&kind),
6308 "EphemeralSpec (distinct, missing) partition violated on {kind:?} for pre={pre_kind:?} post={post_kind:?}",
6309 );
6310 }
6311 assert_eq!(
6312 distinct.len() + missing.len(),
6313 ConditionKind::ALL.len(),
6314 "EphemeralSpec (distinct, missing) cardinality partition drift for pre={pre_kind:?} post={post_kind:?}",
6315 );
6316 }
6317 }
6318 }
6319
6320 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-kind-count triad)
6321 /// — the three `missing_*_kind_count` methods on [`EphemeralSpec`]
6322 /// delegate to the slice-level substrate primitive
6323 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
6324 /// the two `Vec<Condition>` slots and compose the union scalar via
6325 /// `ConditionKind::ALL.iter().filter(|k|
6326 /// !has_condition_kind(**k)).count()`. Sweep
6327 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
6328 /// `missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count`
6329 /// on the point-domain [`crate::boundary::Boundary`] surface —
6330 /// both peers compose against the SAME slice-level substrate
6331 /// primitive so a regression at the per-slice negated closed-set
6332 /// walk fails at that primitive's tests rather than as silent drift
6333 /// at either struct-level scalar-cardinality arm. Also pins the
6334 /// scalar-partition invariant `distinct_kind_count +
6335 /// missing_kind_count == ConditionKind::ALL.len()` per arrangement.
6336 #[test]
6337 fn ephemeral_missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count() {
6338 // Empty ephemeral spec — every arm returns ConditionKind::ALL.len().
6339 let empty = empty_ephemeral();
6340 let total = ConditionKind::ALL.len();
6341 assert_eq!(
6342 empty.missing_precondition_kind_count(),
6343 total,
6344 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_precondition_kind_count",
6345 );
6346 assert_eq!(
6347 empty.missing_postcondition_kind_count(),
6348 total,
6349 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_postcondition_kind_count",
6350 );
6351 assert_eq!(
6352 empty.missing_condition_kind_count(),
6353 total,
6354 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_condition_kind_count",
6355 );
6356
6357 for pre_kind in ConditionKind::ALL {
6358 for post_kind in ConditionKind::ALL {
6359 let mut spec = empty_ephemeral();
6360 spec.preconditions.push(cond(pre_kind));
6361 spec.postconditions.push(cond(post_kind));
6362
6363 // Half-slice arms delegate byte-for-byte to the slice
6364 // substrate primitive.
6365 assert_eq!(
6366 spec.missing_precondition_kind_count(),
6367 spec.preconditions.missing_kind_count(),
6368 "EphemeralSpec::missing_precondition_kind_count must delegate verbatim to \
6369 preconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6370 );
6371 assert_eq!(
6372 spec.missing_precondition_kind_count(),
6373 spec.missing_precondition_kinds().len(),
6374 "EphemeralSpec::missing_precondition_kind_count must equal \
6375 missing_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6376 );
6377 assert_eq!(
6378 spec.missing_postcondition_kind_count(),
6379 spec.postconditions.missing_kind_count(),
6380 "EphemeralSpec::missing_postcondition_kind_count must delegate verbatim to \
6381 postconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6382 );
6383 assert_eq!(
6384 spec.missing_postcondition_kind_count(),
6385 spec.missing_postcondition_kinds().len(),
6386 "EphemeralSpec::missing_postcondition_kind_count must equal \
6387 missing_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6388 );
6389 // Union arm equals missing_condition_kinds().len().
6390 assert_eq!(
6391 spec.missing_condition_kind_count(),
6392 spec.missing_condition_kinds().len(),
6393 "EphemeralSpec::missing_condition_kind_count must equal \
6394 missing_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6395 );
6396 // Scalar-partition invariant: distinct + missing == ALL.
6397 assert_eq!(
6398 spec.distinct_condition_kind_count() + spec.missing_condition_kind_count(),
6399 ConditionKind::ALL.len(),
6400 "EphemeralSpec (distinct, missing) scalar partition drift for pre={pre_kind:?} post={post_kind:?}",
6401 );
6402 }
6403 }
6404 }
6405
6406 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-distinct-kind
6407 /// triad) — the three `first_distinct_*_kind` methods on
6408 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
6409 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] over
6410 /// the two `Vec<Condition>` slots and compose the union via
6411 /// `ConditionKind::ALL.iter().copied().find(|k|
6412 /// has_condition_kind(*k))`. Byte-for-byte peer of
6413 /// `first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind`
6414 /// on the point-domain [`crate::boundary::Boundary`] surface — both
6415 /// peers compose against the SAME slice-level substrate primitive
6416 /// so a regression at the per-slice short-circuit walk fails at
6417 /// that primitive's tests rather than as silent drift at either
6418 /// struct-level earliest-element arm.
6419 #[test]
6420 fn ephemeral_first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind() {
6421 // Empty ephemeral spec — every arm returns None.
6422 let empty = empty_ephemeral();
6423 assert_eq!(
6424 empty.first_distinct_precondition_kind(),
6425 None,
6426 "empty ephemeral spec must return None on first_distinct_precondition_kind",
6427 );
6428 assert_eq!(
6429 empty.first_distinct_postcondition_kind(),
6430 None,
6431 "empty ephemeral spec must return None on first_distinct_postcondition_kind",
6432 );
6433 assert_eq!(
6434 empty.first_distinct_condition_kind(),
6435 None,
6436 "empty ephemeral spec must return None on first_distinct_condition_kind",
6437 );
6438
6439 for pre_kind in ConditionKind::ALL {
6440 for post_kind in ConditionKind::ALL {
6441 let mut spec = empty_ephemeral();
6442 spec.preconditions.push(cond(pre_kind));
6443 spec.postconditions.push(cond(post_kind));
6444
6445 assert_eq!(
6446 spec.first_distinct_precondition_kind(),
6447 spec.preconditions.first_distinct_kind(),
6448 "EphemeralSpec::first_distinct_precondition_kind must delegate verbatim to \
6449 preconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6450 );
6451 assert_eq!(
6452 spec.first_distinct_precondition_kind(),
6453 spec.distinct_precondition_kinds().first().copied(),
6454 "EphemeralSpec::first_distinct_precondition_kind must equal \
6455 distinct_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6456 );
6457 assert_eq!(
6458 spec.first_distinct_postcondition_kind(),
6459 spec.postconditions.first_distinct_kind(),
6460 "EphemeralSpec::first_distinct_postcondition_kind must delegate verbatim to \
6461 postconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6462 );
6463 assert_eq!(
6464 spec.first_distinct_postcondition_kind(),
6465 spec.distinct_postcondition_kinds().first().copied(),
6466 "EphemeralSpec::first_distinct_postcondition_kind must equal \
6467 distinct_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6468 );
6469 let expected_union = ConditionKind::ALL
6470 .into_iter()
6471 .find(|k| pre_kind == *k || post_kind == *k);
6472 assert_eq!(
6473 spec.first_distinct_condition_kind(),
6474 expected_union,
6475 "EphemeralSpec::first_distinct_condition_kind must equal earliest ALL entry \
6476 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6477 );
6478 assert_eq!(
6479 spec.first_distinct_condition_kind(),
6480 spec.distinct_condition_kinds().first().copied(),
6481 "EphemeralSpec::first_distinct_condition_kind must equal \
6482 distinct_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6483 );
6484 }
6485 }
6486 }
6487
6488 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-missing-kind triad)
6489 /// — the three `first_missing_*_kind` methods on [`EphemeralSpec`]
6490 /// delegate to the slice-level substrate primitive
6491 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`] over
6492 /// the two `Vec<Condition>` slots and compose the union via
6493 /// `ConditionKind::ALL.iter().copied().find(|k|
6494 /// !has_condition_kind(*k))`. Byte-for-byte peer of
6495 /// `first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind`
6496 /// on the point-domain [`crate::boundary::Boundary`] surface.
6497 #[test]
6498 fn ephemeral_first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind() {
6499 // Empty ephemeral spec — every arm returns Some(ConditionKind::ALL[0]).
6500 let empty = empty_ephemeral();
6501 let first = Some(ConditionKind::ALL[0]);
6502 assert_eq!(
6503 empty.first_missing_precondition_kind(),
6504 first,
6505 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_precondition_kind",
6506 );
6507 assert_eq!(
6508 empty.first_missing_postcondition_kind(),
6509 first,
6510 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_postcondition_kind",
6511 );
6512 assert_eq!(
6513 empty.first_missing_condition_kind(),
6514 first,
6515 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_condition_kind",
6516 );
6517
6518 for pre_kind in ConditionKind::ALL {
6519 for post_kind in ConditionKind::ALL {
6520 let mut spec = empty_ephemeral();
6521 spec.preconditions.push(cond(pre_kind));
6522 spec.postconditions.push(cond(post_kind));
6523
6524 assert_eq!(
6525 spec.first_missing_precondition_kind(),
6526 spec.preconditions.first_missing_kind(),
6527 "EphemeralSpec::first_missing_precondition_kind must delegate verbatim to \
6528 preconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6529 );
6530 assert_eq!(
6531 spec.first_missing_precondition_kind(),
6532 spec.missing_precondition_kinds().first().copied(),
6533 "EphemeralSpec::first_missing_precondition_kind must equal \
6534 missing_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6535 );
6536 assert_eq!(
6537 spec.first_missing_postcondition_kind(),
6538 spec.postconditions.first_missing_kind(),
6539 "EphemeralSpec::first_missing_postcondition_kind must delegate verbatim to \
6540 postconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6541 );
6542 assert_eq!(
6543 spec.first_missing_postcondition_kind(),
6544 spec.missing_postcondition_kinds().first().copied(),
6545 "EphemeralSpec::first_missing_postcondition_kind must equal \
6546 missing_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6547 );
6548 let expected_union = ConditionKind::ALL
6549 .into_iter()
6550 .find(|k| pre_kind != *k && post_kind != *k);
6551 assert_eq!(
6552 spec.first_missing_condition_kind(),
6553 expected_union,
6554 "EphemeralSpec::first_missing_condition_kind must equal earliest ALL entry \
6555 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6556 );
6557 assert_eq!(
6558 spec.first_missing_condition_kind(),
6559 spec.missing_condition_kinds().first().copied(),
6560 "EphemeralSpec::first_missing_condition_kind must equal \
6561 missing_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6562 );
6563 }
6564 }
6565 }
6566
6567 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-distinct-kind
6568 /// triad) — the three `last_distinct_*_kind` methods on
6569 /// [`EphemeralSpec`] delegate to the slice-level substrate
6570 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
6571 /// over the two `Vec<Condition>` slots and compose the union via
6572 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
6573 /// has_condition_kind(*k))`. Byte-for-byte peer of
6574 /// `last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind`
6575 /// on the point-domain [`crate::boundary::Boundary`] surface —
6576 /// both peers compose against the SAME slice-level substrate
6577 /// primitive so a regression at the per-slice REVERSED short-
6578 /// circuit walk fails at that primitive's tests rather than as
6579 /// silent drift at either struct-level latest-element arm.
6580 #[test]
6581 fn ephemeral_last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind() {
6582 // Empty ephemeral spec — every arm returns None.
6583 let empty = empty_ephemeral();
6584 assert_eq!(
6585 empty.last_distinct_precondition_kind(),
6586 None,
6587 "empty ephemeral spec must return None on last_distinct_precondition_kind",
6588 );
6589 assert_eq!(
6590 empty.last_distinct_postcondition_kind(),
6591 None,
6592 "empty ephemeral spec must return None on last_distinct_postcondition_kind",
6593 );
6594 assert_eq!(
6595 empty.last_distinct_condition_kind(),
6596 None,
6597 "empty ephemeral spec must return None on last_distinct_condition_kind",
6598 );
6599
6600 for pre_kind in ConditionKind::ALL {
6601 for post_kind in ConditionKind::ALL {
6602 let mut spec = empty_ephemeral();
6603 spec.preconditions.push(cond(pre_kind));
6604 spec.postconditions.push(cond(post_kind));
6605
6606 assert_eq!(
6607 spec.last_distinct_precondition_kind(),
6608 spec.preconditions.last_distinct_kind(),
6609 "EphemeralSpec::last_distinct_precondition_kind must delegate verbatim to \
6610 preconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6611 );
6612 assert_eq!(
6613 spec.last_distinct_precondition_kind(),
6614 spec.distinct_precondition_kinds().last().copied(),
6615 "EphemeralSpec::last_distinct_precondition_kind must equal \
6616 distinct_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6617 );
6618 assert_eq!(
6619 spec.last_distinct_postcondition_kind(),
6620 spec.postconditions.last_distinct_kind(),
6621 "EphemeralSpec::last_distinct_postcondition_kind must delegate verbatim to \
6622 postconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6623 );
6624 assert_eq!(
6625 spec.last_distinct_postcondition_kind(),
6626 spec.distinct_postcondition_kinds().last().copied(),
6627 "EphemeralSpec::last_distinct_postcondition_kind must equal \
6628 distinct_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6629 );
6630 let expected_union = ConditionKind::ALL
6631 .into_iter()
6632 .rev()
6633 .find(|k| pre_kind == *k || post_kind == *k);
6634 assert_eq!(
6635 spec.last_distinct_condition_kind(),
6636 expected_union,
6637 "EphemeralSpec::last_distinct_condition_kind must equal latest ALL entry \
6638 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6639 );
6640 assert_eq!(
6641 spec.last_distinct_condition_kind(),
6642 spec.distinct_condition_kinds().last().copied(),
6643 "EphemeralSpec::last_distinct_condition_kind must equal \
6644 distinct_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6645 );
6646 }
6647 }
6648 }
6649
6650 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-missing-kind triad)
6651 /// — the three `last_missing_*_kind` methods on [`EphemeralSpec`]
6652 /// delegate to the slice-level substrate primitive
6653 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] over
6654 /// the two `Vec<Condition>` slots and compose the union via
6655 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
6656 /// !has_condition_kind(*k))`. Byte-for-byte peer of
6657 /// `last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind`
6658 /// on the point-domain [`crate::boundary::Boundary`] surface.
6659 #[test]
6660 fn ephemeral_last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind() {
6661 // Empty ephemeral spec — every arm returns Some(*ConditionKind::ALL.last().unwrap()).
6662 let empty = empty_ephemeral();
6663 let last = ConditionKind::ALL.last().copied();
6664 assert_eq!(
6665 empty.last_missing_precondition_kind(),
6666 last,
6667 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_precondition_kind",
6668 );
6669 assert_eq!(
6670 empty.last_missing_postcondition_kind(),
6671 last,
6672 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_postcondition_kind",
6673 );
6674 assert_eq!(
6675 empty.last_missing_condition_kind(),
6676 last,
6677 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_condition_kind",
6678 );
6679
6680 for pre_kind in ConditionKind::ALL {
6681 for post_kind in ConditionKind::ALL {
6682 let mut spec = empty_ephemeral();
6683 spec.preconditions.push(cond(pre_kind));
6684 spec.postconditions.push(cond(post_kind));
6685
6686 assert_eq!(
6687 spec.last_missing_precondition_kind(),
6688 spec.preconditions.last_missing_kind(),
6689 "EphemeralSpec::last_missing_precondition_kind must delegate verbatim to \
6690 preconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6691 );
6692 assert_eq!(
6693 spec.last_missing_precondition_kind(),
6694 spec.missing_precondition_kinds().last().copied(),
6695 "EphemeralSpec::last_missing_precondition_kind must equal \
6696 missing_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6697 );
6698 assert_eq!(
6699 spec.last_missing_postcondition_kind(),
6700 spec.postconditions.last_missing_kind(),
6701 "EphemeralSpec::last_missing_postcondition_kind must delegate verbatim to \
6702 postconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6703 );
6704 assert_eq!(
6705 spec.last_missing_postcondition_kind(),
6706 spec.missing_postcondition_kinds().last().copied(),
6707 "EphemeralSpec::last_missing_postcondition_kind must equal \
6708 missing_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6709 );
6710 let expected_union = ConditionKind::ALL
6711 .into_iter()
6712 .rev()
6713 .find(|k| pre_kind != *k && post_kind != *k);
6714 assert_eq!(
6715 spec.last_missing_condition_kind(),
6716 expected_union,
6717 "EphemeralSpec::last_missing_condition_kind must equal latest ALL entry \
6718 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6719 );
6720 assert_eq!(
6721 spec.last_missing_condition_kind(),
6722 spec.missing_condition_kinds().last().copied(),
6723 "EphemeralSpec::last_missing_condition_kind must equal \
6724 missing_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6725 );
6726 }
6727 }
6728 }
6729
6730 // ── assert_slice_refinement_composition_laws — mirror invocations ──
6731 //
6732 // The substrate testkit primitive
6733 // [`crate::boundary::assert_slice_refinement_composition_laws`]
6734 // pins the FOUR composition laws that bind the
6735 // [`crate::boundary::ConditionSliceExt`] refinement algebra
6736 // (find ↔ iter, count ↔ iter, has ↔ find, has ↔ count) at ONE
6737 // call site per authored arrangement, sweeping
6738 // [`ConditionKind::ALL`]. The two ephemeral-surface tests below
6739 // dispatch the primitive against the two `Vec<Condition>` slots
6740 // ([`EphemeralSpec::preconditions`] +
6741 // [`EphemeralSpec::postconditions`]) authored through the
6742 // ephemeral-surface test-fixture — byte-for-byte peer of the
6743 // point-surface `slice_refinement_composition_laws_hold_across_authored_arrangements`
6744 // + `slice_refinement_composition_laws_hold_on_interleaved_duplicates`
6745 // pins on the [`crate::boundary::Boundary`] surface. Two-surface
6746 // parity contract: the substrate primitive holds on every slice
6747 // reachable through either the point-surface `.preconditions` /
6748 // `.postconditions` fields OR the ephemeral-surface's
6749 // eponymous field pair.
6750
6751 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate
6752 /// primitive [`assert_slice_refinement_composition_laws`] holds
6753 /// on both [`EphemeralSpec::preconditions`] and
6754 /// [`EphemeralSpec::postconditions`] slices for every populated-
6755 /// pair authored through the ephemeral-surface test-fixture.
6756 /// Byte-for-byte peer of
6757 /// `slice_refinement_composition_laws_hold_across_authored_arrangements`
6758 /// on the point surface.
6759 #[test]
6760 fn ephemeral_slice_refinement_composition_laws_hold_across_authored_arrangements() {
6761 let empty = empty_ephemeral();
6762 assert_slice_refinement_composition_laws(empty.preconditions.as_slice());
6763 assert_slice_refinement_composition_laws(empty.postconditions.as_slice());
6764
6765 for pre_kind in ConditionKind::ALL {
6766 for post_kind in ConditionKind::ALL {
6767 let mut spec = empty_ephemeral();
6768 spec.preconditions.push(cond(pre_kind));
6769 spec.postconditions.push(cond(post_kind));
6770 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
6771 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
6772 }
6773 }
6774
6775 for populated in ConditionKind::ALL {
6776 let mut spec = empty_ephemeral();
6777 spec.preconditions.push(cond(populated));
6778 spec.preconditions.push(cond(populated));
6779 spec.preconditions.push(cond(populated));
6780 spec.postconditions.push(cond(populated));
6781 spec.postconditions.push(cond(populated));
6782 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
6783 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
6784 }
6785 }
6786
6787 // ── assert_surface_union_composition_laws — ephemeral surface ────
6788 //
6789 // The substrate testkit macro
6790 // [`crate::assert_surface_union_composition_laws`] pins the FOUR
6791 // union composition laws (has: OR, find: or_else, iter: chain,
6792 // count: SUM) that bind the (pre, post, union) refinement triads
6793 // on the [`EphemeralSpec`] sugar-surface at ONE call site per
6794 // authored arrangement, sweeping [`ConditionKind::ALL`]. Byte-for-
6795 // byte peer of the point-surface
6796 // `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
6797 // / `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
6798 // pins on the [`crate::boundary::Boundary`] surface — the two-
6799 // surface parity contract binds every downstream `condition-<K>`
6800 // / `precondition-<K>` / `postcondition-<K>` require-tag classifier
6801 // on either surface to the SAME four union-composition operators
6802 // through ONE substrate primitive rather than through per-surface
6803 // author-time re-authored sweeps.
6804
6805 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate macro
6806 /// [`crate::assert_surface_union_composition_laws`] passes on
6807 /// [`EphemeralSpec`] for the four canonical authored arrangements
6808 /// (empty spec, precondition-only populated, postcondition-only
6809 /// populated, dual-populated sweep over `ALL × ALL`). Byte-for-byte
6810 /// peer of the point-surface
6811 /// `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
6812 /// pin — the two-surface parity contract binds every union
6813 /// composition law on both surfaces to the SAME substrate
6814 /// primitive.
6815 #[test]
6816 fn ephemeral_surface_union_composition_laws_hold_across_authored_arrangements() {
6817 let empty = empty_ephemeral();
6818 crate::assert_surface_union_composition_laws!(empty);
6819
6820 for populated in ConditionKind::ALL {
6821 let mut pre_only = empty_ephemeral();
6822 pre_only.preconditions.push(cond(populated));
6823 crate::assert_surface_union_composition_laws!(pre_only);
6824
6825 let mut post_only = empty_ephemeral();
6826 post_only.postconditions.push(cond(populated));
6827 crate::assert_surface_union_composition_laws!(post_only);
6828 }
6829
6830 for pre_kind in ConditionKind::ALL {
6831 for post_kind in ConditionKind::ALL {
6832 let mut dual = empty_ephemeral();
6833 dual.preconditions.push(cond(pre_kind));
6834 dual.postconditions.push(cond(post_kind));
6835 crate::assert_surface_union_composition_laws!(dual);
6836 }
6837 }
6838 }
6839
6840 /// SUBSTRATE PANEL pin (ephemeral surface, params-distinguishable
6841 /// duplicates) — the substrate macro holds on an [`EphemeralSpec`]
6842 /// whose two half-slices each carry duplicates of the same kind at
6843 /// multiple positions interleaved with a distinct kind. Byte-for-
6844 /// byte peer of the point-surface
6845 /// `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
6846 /// pin — the non-degenerate composition of every union arm on the
6847 /// sugar-surface binds against the SAME four monoid operators as
6848 /// the point-surface peer. A regression on the ephemeral surface
6849 /// only that (a) collapsed `find`'s `or_else` to `and_then`, (b)
6850 /// collapsed `iter`'s `chain` to `zip`, or (c) collapsed `count`'s
6851 /// SUM to `max` surfaces HERE, breaking two-surface parity.
6852 #[test]
6853 fn ephemeral_surface_union_composition_laws_hold_on_interleaved_duplicates() {
6854 let mut spec = empty_ephemeral();
6855 spec.preconditions.push(Condition {
6856 kind: ConditionKind::ClosedLoopAuth,
6857 params: serde_json::json!({ "side": "pre-1" }),
6858 });
6859 spec.preconditions.push(Condition {
6860 kind: ConditionKind::PromQL,
6861 params: serde_json::json!({ "query": "up" }),
6862 });
6863 spec.preconditions.push(Condition {
6864 kind: ConditionKind::ClosedLoopAuth,
6865 params: serde_json::json!({ "side": "pre-2" }),
6866 });
6867 spec.postconditions.push(Condition {
6868 kind: ConditionKind::PromQL,
6869 params: serde_json::json!({ "query": "healthy" }),
6870 });
6871 spec.postconditions.push(Condition {
6872 kind: ConditionKind::ClosedLoopAuth,
6873 params: serde_json::json!({ "side": "post-1" }),
6874 });
6875 crate::assert_surface_union_composition_laws!(spec);
6876 }
6877
6878 #[test]
6879 fn from_impl_clears_other_intent_variants() {
6880 // Even if someone constructs an EphemeralSpec by hand and the
6881 // resulting ProcessSpec is later mutated, the From bridge sets
6882 // every non-Aplicacao slot to None explicitly.
6883 let e = EphemeralSpec {
6884 aplicacao: demo_overlay(),
6885 ttl: "10m".into(),
6886 teardown: TeardownPolicy::Never,
6887 max_concurrent: 0,
6888 postconditions: vec![],
6889 preconditions: vec![],
6890 verify_timeout: None,
6891 classification: None,
6892 parent: Some("seph.1".into()),
6893 exports: vec![],
6894 routing: None,
6895 };
6896 let ps: ProcessSpec = e.into();
6897 assert!(ps.intent.nix.is_none());
6898 assert!(ps.intent.flux.is_none());
6899 assert!(ps.intent.lisp.is_none());
6900 assert!(ps.intent.container.is_none());
6901 assert!(ps.intent.guest.is_none());
6902 assert!(ps.intent.aplicacao.is_some());
6903 assert_eq!(ps.identity.parent.as_deref(), Some("seph.1"));
6904 }
6905
6906 // ── EphemeralSpec::has_teardown_policy substrate pins ────────────
6907 //
6908 // Fail-before-pass-after granularity:
6909 // `EphemeralSpec::has_teardown_policy` did not exist before this
6910 // commit — the (`self.teardown == kind`) scalar-carrier probe on
6911 // the sugar-surface [`EphemeralSpec`] lived only implicitly via
6912 // hand-authored comparisons at potential future call sites, with
6913 // no analogue to the peer
6914 // [`crate::lifetime::EphemeralLifetime::has_teardown_policy`] on
6915 // the point-surface carrier. The lift adds the peer inherent
6916 // method on the [`EphemeralSpec`] sugar-surface so both surfaces'
6917 // `teardown-policy-<kind>` require-tag families in
6918 // `tatara-reconciler::bin::tatara-check` compose against the SAME
6919 // scalar `==` shape in lockstep. A regression that (a) hard-coded
6920 // the arm to a single kind, (b) inverted the closed-set match
6921 // (silently returning `true` on non-matching variants), or (c)
6922 // probed the wrong slot (a stray comparison against `ttl` /
6923 // `max_concurrent`) fails HERE at the substrate primitive rather
6924 // than as silent operator-facing drift at the ephemeral
6925 // `teardown-policy-<kind>` require-tag surface.
6926
6927 /// STORED-slot pin — an ephemeral spec that carries a given
6928 /// [`TeardownPolicy`] returns `true` for that kind, `false` for
6929 /// every other variant. Sweep the [`TeardownPolicy::ALL`] × ALL
6930 /// cross so a regression that hard-coded the arm to a single kind
6931 /// or wired the closure to a fixed unrelated field fails HERE at
6932 /// the substrate primitive. Byte-for-byte peer of
6933 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_returns_true_iff_variant_matches`]
6934 /// on the point-surface [`crate::lifetime::EphemeralLifetime`]
6935 /// carrier — the two surfaces publish identical `==` scalar
6936 /// semantics on their respective `teardown` / `teardown_policy`
6937 /// slots.
6938 #[test]
6939 fn has_teardown_policy_returns_true_iff_ephemeral_teardown_matches_per_kind() {
6940 for populated in TeardownPolicy::ALL {
6941 let mut spec = empty_ephemeral();
6942 spec.teardown = populated;
6943 for query in TeardownPolicy::ALL {
6944 let expected = query == populated;
6945 assert_eq!(
6946 spec.has_teardown_policy(query),
6947 expected,
6948 "ephemeral teardown={populated:?}: query {query:?} drifted",
6949 );
6950 }
6951 }
6952 }
6953
6954 /// DEFAULT-SLOT pin — an [`EphemeralSpec`] whose `teardown` slot
6955 /// is [`TeardownPolicy::default`] (`Always`) returns `true` for
6956 /// `Always` and `false` for every other variant. The
6957 /// (required-scalar-child) corner has no absent state — a
6958 /// hand-authored spec that omits `:teardown` from the
6959 /// `(defephemeral …)` form IS configured for `Always`, and this
6960 /// pin locks the corner's default-arm short-circuit as identical
6961 /// to the (Option-parent × defaulted-scalar-child) corner's
6962 /// reachable arm on the point surface (both return `true` on
6963 /// `Always` only). Byte-for-byte peer of
6964 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_default_probes_always_only`]
6965 /// on the point-surface carrier.
6966 #[test]
6967 fn has_teardown_policy_default_probes_always_only_on_ephemeral() {
6968 let spec = EphemeralSpec {
6969 teardown: TeardownPolicy::default(),
6970 ..empty_ephemeral()
6971 };
6972 for kind in TeardownPolicy::ALL {
6973 let expected = kind == TeardownPolicy::Always;
6974 assert_eq!(
6975 spec.has_teardown_policy(kind),
6976 expected,
6977 "default ephemeral (teardown=Always) baseline: query {kind:?} must be {expected}",
6978 );
6979 }
6980 }
6981
6982 // ── derived-bool-predicate presence probe on EphemeralSpec ×
6983 // TeardownPolicy × ProcessPhase ──
6984 //
6985 // Fail-before-pass-after granularity:
6986 // [`EphemeralSpec::has_teardown_firing_on`] did not exist before
6987 // this commit — the ephemeral sugar surface's require-tag algebra
6988 // discriminated the teardown axis only by the RAW authored variant
6989 // (via `teardown-policy-<kind>`), never by the derived
6990 // [`ProcessPhase`] transition the stored policy fires on
6991 // ([`TeardownPolicy::should_teardown_on`]). Post-lift the shape
6992 // lives at ONE inherent method that byte-for-byte parallels
6993 // [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
6994 // on the point-surface carrier, and both surfaces' require-tag
6995 // classifiers publish a symmetric `teardown-fires-on-<phase>`
6996 // family through the SAME predicate.
6997
6998 /// TRUTH-TABLE DIAGONAL — for every [`TeardownPolicy`] variant,
6999 /// an [`EphemeralSpec`] whose `teardown` slot is set to that
7000 /// variant returns `has_teardown_firing_on(phase)` in agreement
7001 /// with [`TeardownPolicy::should_teardown_on`] for every
7002 /// [`ProcessPhase`] variant. Sweep [`TeardownPolicy::ALL`] ×
7003 /// [`ProcessPhase::ALL`] full cross so a regression that hard-
7004 /// coded the arm to a single policy, wired to the wrong field, or
7005 /// inverted the predicate direction fails HERE at the substrate
7006 /// primitive on the sugar surface (byte-for-byte peer of
7007 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase`]
7008 /// on the point carrier).
7009 #[test]
7010 fn has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase_on_ephemeral() {
7011 for populated in TeardownPolicy::ALL {
7012 let spec = EphemeralSpec {
7013 teardown: populated,
7014 ..empty_ephemeral()
7015 };
7016 for phase in ProcessPhase::ALL {
7017 assert_eq!(
7018 spec.has_teardown_firing_on(phase),
7019 populated.should_teardown_on(phase),
7020 "teardown={populated:?}, phase={phase:?}: predicate drift from \
7021 should_teardown_on projection",
7022 );
7023 }
7024 }
7025 }
7026
7027 /// TWO-SURFACE PARITY PIN — for every [`TeardownPolicy`] variant
7028 /// and every [`ProcessPhase`] variant, the sugar-surface probe
7029 /// and the lowered point-surface probe agree. The `EphemeralSpec
7030 /// → ProcessSpec` lowering routes the stored `teardown` slot
7031 /// through the SAME [`TeardownPolicy::should_teardown_on`]
7032 /// projection on both sides, so the sugar caller and the lowered
7033 /// caller can never disagree — a regression that (a) drifted
7034 /// [`Self::teardown`] between sugar and lowered, (b) rewired
7035 /// either probe body to bypass the shared substrate primitive, or
7036 /// (c) skewed the (policy, phase) truth table between the two
7037 /// surfaces fails HERE at the two-surface boundary rather than at
7038 /// the operator-facing require-tag classifier.
7039 #[test]
7040 fn has_teardown_firing_on_matches_point_peer_through_lowered_teardown_policy() {
7041 for populated in TeardownPolicy::ALL {
7042 let sugar = EphemeralSpec {
7043 teardown: populated,
7044 ..empty_ephemeral()
7045 };
7046 let lowered: ProcessSpec = sugar.clone().into();
7047 let lowered_eph = lowered
7048 .lifetime
7049 .resolved_ephemeral()
7050 .expect("lowered spec must be ephemeral");
7051 for phase in ProcessPhase::ALL {
7052 assert_eq!(
7053 sugar.has_teardown_firing_on(phase),
7054 lowered_eph.has_teardown_firing_on(phase),
7055 "sugar-vs-lowered predicate drift for teardown={populated:?}, phase={phase:?}",
7056 );
7057 }
7058 }
7059 }
7060
7061 // ── EphemeralSpec::resolved_classification + has_point_type pins ─────
7062 //
7063 // Fail-before-pass-after granularity: `resolved_classification` and
7064 // `has_point_type` did not exist pre-lift on `impl EphemeralSpec` — every
7065 // caller wanting the resolved [`Classification`] on the ephemeral
7066 // sugar-surface (currently zero; future ephemeral-surface classification-
7067 // axis require-tag families in `tatara-reconciler::bin::tatara-check`,
7068 // typed audit hooks, documentation generators listing the ephemeral
7069 // surface's known require-tag vocabulary) restated the two-line
7070 // `self.classification.as_ref().unwrap_or(&default_ephemeral_class())`
7071 // resolver body at their site. Post-lift both callers of the resolver
7072 // (`Self::has_point_type` and every future classification-axis peer)
7073 // route through ONE inherent method that shares the fill-through with
7074 // the sibling `From<EphemeralSpec> for ProcessSpec` lowering
7075 // byte-for-byte. A regression that (a) inverted the arm (`Some` filled
7076 // through the default), (b) drifted the default from the sibling
7077 // primitive `Classification::gate_compute()`, or (c) shifted the
7078 // `Cow<'_, Classification>` return shape (a stray `.clone()` on the
7079 // populated arm) fails HERE at the substrate primitive rather than as
7080 // silent operator-facing drift at a future
7081 // `point-type-<kind>` ephemeral require-tag surface.
7082
7083 /// AUTHORED-slot pin — an [`EphemeralSpec`] whose
7084 /// [`EphemeralSpec::classification`] slot names a concrete
7085 /// [`Classification`] returns [`Cow::Borrowed`] pointing at that
7086 /// authored value from [`Self::resolved_classification`]. Pins the
7087 /// populated-arm zero-allocation contract: a caller reading past
7088 /// the resolver sees the SAME byte address the operator authored,
7089 /// so the resolver does not silently clone the authored slot on
7090 /// the populated arm.
7091 #[test]
7092 fn resolved_classification_borrows_authored_slot() {
7093 let mut spec = empty_ephemeral();
7094 let mut authored = Classification::gate_compute();
7095 authored.point_type = ConvergencePointType::Fork;
7096 spec.classification = Some(authored.clone());
7097 let resolved = spec.resolved_classification();
7098 assert!(matches!(resolved, Cow::Borrowed(_)));
7099 assert_eq!(&*resolved, &authored);
7100 }
7101
7102 /// ABSENT-slot pin — an [`EphemeralSpec`] whose
7103 /// [`EphemeralSpec::classification`] slot is `None` returns
7104 /// [`Cow::Owned`] with the SAME value the sibling
7105 /// [`default_ephemeral_class`] baseline produces. Pins the
7106 /// two-surface parity contract with `From<EphemeralSpec> for
7107 /// ProcessSpec`: both sites fill through the SAME baseline on
7108 /// `None`, so the ephemeral require-tag surface's future
7109 /// `point-type-<kind>` family reads identically on the authored
7110 /// spec and on the mechanically lowered `ProcessSpec`.
7111 #[test]
7112 fn resolved_classification_fills_default_on_absent_slot() {
7113 let spec = empty_ephemeral();
7114 assert!(spec.classification.is_none());
7115 let resolved = spec.resolved_classification();
7116 assert!(matches!(resolved, Cow::Owned(_)));
7117 assert_eq!(&*resolved, &default_ephemeral_class());
7118 }
7119
7120 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7121 /// [`EphemeralSpec::classification`] slot names a concrete
7122 /// [`Classification`] returns `true` from
7123 /// [`Self::has_point_type`] on the authored
7124 /// [`ConvergencePointType`] slot and `false` for every other
7125 /// variant. Sweep the [`ConvergencePointType::ALL`] × ALL cross so
7126 /// a regression that hard-coded the arm to a single kind or wired
7127 /// the closure to a fixed unrelated slot fails HERE at the
7128 /// substrate primitive. Byte-for-byte peer of
7129 /// [`crate::classification::tests`]'s point-surface
7130 /// [`Classification::has_point_type`] populated-slot sweep on the
7131 /// SAME closed-set primitive.
7132 #[test]
7133 fn has_point_type_returns_true_iff_authored_classification_matches_per_kind() {
7134 for populated in ConvergencePointType::ALL {
7135 let mut classification = Classification::gate_compute();
7136 classification.point_type = populated;
7137 let mut spec = empty_ephemeral();
7138 spec.classification = Some(classification);
7139 for query in ConvergencePointType::ALL {
7140 let expected = query == populated;
7141 assert_eq!(
7142 spec.has_point_type(query),
7143 expected,
7144 "ephemeral classification.point_type={populated:?}: query {query:?} drifted",
7145 );
7146 }
7147 }
7148 }
7149
7150 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7151 /// [`EphemeralSpec::classification`] slot is `None` returns
7152 /// `true` from [`Self::has_point_type`] on
7153 /// [`ConvergencePointType::Gate`] (the `default_ephemeral_class`
7154 /// baseline's `point_type`) and `false` on every other variant.
7155 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
7156 /// default-arm short-circuit: on the ephemeral sugar surface the
7157 /// parent Option is filled through the workspace baseline rather
7158 /// than reading `false` on every variant like the encapsulation-
7159 /// mode / encapsulation-target / routing-form Option-parent
7160 /// corners.
7161 #[test]
7162 fn has_point_type_probes_gate_only_on_absent_classification() {
7163 let spec = empty_ephemeral();
7164 assert!(spec.classification.is_none());
7165 for kind in ConvergencePointType::ALL {
7166 let expected = kind == ConvergencePointType::Gate;
7167 assert_eq!(
7168 spec.has_point_type(kind),
7169 expected,
7170 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7171 );
7172 }
7173 }
7174
7175 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7176 /// identically through [`Self::has_point_type`] AND through
7177 /// `<eph.clone().into::<ProcessSpec>>()`
7178 /// `.classification.has_point_type(kind)` on the mechanically-
7179 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7180 /// classification on every [`ConvergencePointType::ALL`] variant)
7181 /// × ALL queries so a future regression on either side of the
7182 /// resolver (a shift in the ephemeral resolver's default, a
7183 /// shift in the `From<EphemeralSpec>` lowering's fill-through)
7184 /// fails HERE at the parity boundary.
7185 #[test]
7186 fn has_point_type_matches_point_peer_through_lowered_classification() {
7187 // Absent classification: both surfaces resolve through the SAME
7188 // default and agree on every variant.
7189 let eph = empty_ephemeral();
7190 let lowered: ProcessSpec = eph.clone().into();
7191 for query in ConvergencePointType::ALL {
7192 assert_eq!(
7193 eph.has_point_type(query),
7194 lowered.classification.has_point_type(query),
7195 "None-classification parity drift on query {query:?}",
7196 );
7197 }
7198 // Authored classification: both surfaces read the same authored
7199 // value verbatim.
7200 for populated in ConvergencePointType::ALL {
7201 let mut classification = Classification::gate_compute();
7202 classification.point_type = populated;
7203 let mut eph = empty_ephemeral();
7204 eph.classification = Some(classification);
7205 let lowered: ProcessSpec = eph.clone().into();
7206 for query in ConvergencePointType::ALL {
7207 assert_eq!(
7208 eph.has_point_type(query),
7209 lowered.classification.has_point_type(query),
7210 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
7211 );
7212 }
7213 }
7214 }
7215
7216 // ── EphemeralSpec::has_substrate pins ────────────────────────────
7217 //
7218 // Fail-before-pass-after granularity: [`Self::has_substrate`] did
7219 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
7220 // through `.resolved_classification().substrate == kind` or through
7221 // the lowered `ProcessSpec`'s `spec.classification.has_substrate`.
7222 // Post-lift the SECOND classification-axis peer on the ephemeral
7223 // sugar surface routes through the SAME
7224 // [`Self::resolved_classification`] resolver + the sibling closed-
7225 // set primitive [`Classification::has_substrate`], so a regression
7226 // that dropped the resolver hop, inverted the `Some`/`None`
7227 // fill-through, or wired the closure to a fixed unrelated slot
7228 // fails HERE.
7229
7230 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7231 /// [`EphemeralSpec::classification`] slot names a concrete
7232 /// [`Classification`] returns `true` from
7233 /// [`Self::has_substrate`] on the authored [`SubstrateType`] slot
7234 /// and `false` for every other variant. Sweep the
7235 /// [`SubstrateType::ALL`] × ALL cross so a regression that
7236 /// hard-coded the arm to a single kind or wired the closure to a
7237 /// fixed unrelated slot fails HERE at the substrate primitive.
7238 /// Byte-for-byte peer of the point-surface
7239 /// [`Classification::has_substrate`] populated-slot sweep on the
7240 /// SAME closed-set primitive.
7241 #[test]
7242 fn has_substrate_returns_true_iff_authored_classification_matches_per_kind() {
7243 for populated in SubstrateType::ALL {
7244 let mut classification = Classification::gate_compute();
7245 classification.substrate = populated;
7246 let mut spec = empty_ephemeral();
7247 spec.classification = Some(classification);
7248 for query in SubstrateType::ALL {
7249 let expected = query == populated;
7250 assert_eq!(
7251 spec.has_substrate(query),
7252 expected,
7253 "ephemeral classification.substrate={populated:?}: query {query:?} drifted",
7254 );
7255 }
7256 }
7257 }
7258
7259 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7260 /// [`EphemeralSpec::classification`] slot is `None` returns
7261 /// `true` from [`Self::has_substrate`] on
7262 /// [`SubstrateType::Compute`] (the `default_ephemeral_class`
7263 /// baseline's `substrate`) and `false` on every other variant.
7264 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
7265 /// default-arm short-circuit on the SECOND classification-axis
7266 /// peer: on the ephemeral sugar surface the parent Option is
7267 /// filled through the workspace baseline rather than reading
7268 /// `false` on every variant like the Option-parent encapsulates /
7269 /// routing corners.
7270 #[test]
7271 fn has_substrate_probes_compute_only_on_absent_classification() {
7272 let spec = empty_ephemeral();
7273 assert!(spec.classification.is_none());
7274 for kind in SubstrateType::ALL {
7275 let expected = kind == SubstrateType::Compute;
7276 assert_eq!(
7277 spec.has_substrate(kind),
7278 expected,
7279 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7280 );
7281 }
7282 }
7283
7284 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7285 /// identically through [`Self::has_substrate`] AND through
7286 /// `<eph.clone().into::<ProcessSpec>>()`
7287 /// `.classification.has_substrate(kind)` on the mechanically-
7288 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7289 /// classification on every [`SubstrateType::ALL`] variant) × ALL
7290 /// queries so a future regression on either side of the resolver
7291 /// (a shift in the ephemeral resolver's default, a shift in the
7292 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7293 /// the parity boundary. Byte-for-byte peer of the sibling
7294 /// [`Self::has_point_type`] two-surface parity pin on the SAME
7295 /// `Cow`-resolver carrier — the SECOND classification-axis
7296 /// two-surface parity contract on the ephemeral surface.
7297 #[test]
7298 fn has_substrate_matches_point_peer_through_lowered_classification() {
7299 // Absent classification: both surfaces resolve through the SAME
7300 // default and agree on every variant.
7301 let eph = empty_ephemeral();
7302 let lowered: ProcessSpec = eph.clone().into();
7303 for query in SubstrateType::ALL {
7304 assert_eq!(
7305 eph.has_substrate(query),
7306 lowered.classification.has_substrate(query),
7307 "None-classification parity drift on query {query:?}",
7308 );
7309 }
7310 // Authored classification: both surfaces read the same authored
7311 // value verbatim.
7312 for populated in SubstrateType::ALL {
7313 let mut classification = Classification::gate_compute();
7314 classification.substrate = populated;
7315 let mut eph = empty_ephemeral();
7316 eph.classification = Some(classification);
7317 let lowered: ProcessSpec = eph.clone().into();
7318 for query in SubstrateType::ALL {
7319 assert_eq!(
7320 eph.has_substrate(query),
7321 lowered.classification.has_substrate(query),
7322 "authored classification.substrate={populated:?}: parity drift on query {query:?}",
7323 );
7324 }
7325 }
7326 }
7327
7328 // ── EphemeralSpec::has_calm pins ─────────────────────────────────
7329 //
7330 // Fail-before-pass-after granularity: [`Self::has_calm`] did not
7331 // exist pre-lift on `impl EphemeralSpec` — every callsite went
7332 // through `.resolved_classification().calm == kind` or through the
7333 // lowered `ProcessSpec`'s `spec.classification.has_calm`. Post-
7334 // lift the THIRD classification-axis peer on the ephemeral sugar
7335 // surface routes through the SAME
7336 // [`Self::resolved_classification`] resolver + the sibling closed-
7337 // set primitive [`Classification::has_calm`], so a regression that
7338 // dropped the resolver hop, inverted the `Some`/`None` fill-
7339 // through, or wired the closure to a fixed unrelated slot fails
7340 // HERE. Distinct from the FIRST + SECOND peers on the (Option-
7341 // parent × NON-DEFAULT-scalar-child) corner: the (Option-parent ×
7342 // DEFAULTED-scalar-child) corner this peer opens has BOTH the
7343 // parent fill-through baseline (`default_ephemeral_class`) AND the
7344 // child's own `#[default]` land on the SAME variant
7345 // ([`CalmClassification::Monotone`]), a two-defaults composition
7346 // property the three pins below all exercise.
7347
7348 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7349 /// [`EphemeralSpec::classification`] slot names a concrete
7350 /// [`Classification`] returns `true` from [`Self::has_calm`] on
7351 /// the authored [`CalmClassification`] slot and `false` for every
7352 /// other variant. Sweep the [`CalmClassification::ALL`] × ALL
7353 /// cross so a regression that hard-coded the arm to a single
7354 /// kind or wired the closure to a fixed unrelated slot fails HERE
7355 /// at the substrate primitive. Byte-for-byte peer of the point-
7356 /// surface [`Classification::has_calm`] populated-slot sweep on
7357 /// the SAME closed-set primitive.
7358 #[test]
7359 fn has_calm_returns_true_iff_authored_classification_matches_per_kind() {
7360 for populated in CalmClassification::ALL {
7361 let mut classification = Classification::gate_compute();
7362 classification.calm = populated;
7363 let mut spec = empty_ephemeral();
7364 spec.classification = Some(classification);
7365 for query in CalmClassification::ALL {
7366 let expected = query == populated;
7367 assert_eq!(
7368 spec.has_calm(query),
7369 expected,
7370 "ephemeral classification.calm={populated:?}: query {query:?} drifted",
7371 );
7372 }
7373 }
7374 }
7375
7376 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7377 /// [`EphemeralSpec::classification`] slot is `None` returns
7378 /// `true` from [`Self::has_calm`] on
7379 /// [`CalmClassification::Monotone`] (the `default_ephemeral_class`
7380 /// baseline's `calm` axis AND the [`CalmClassification`] child's
7381 /// own `#[default]` variant) and `false` on every other variant.
7382 /// Pins the (Option-parent × DEFAULTED-scalar-child ×
7383 /// operator-resolvable-baseline) corner's default-arm short-
7384 /// circuit on the THIRD classification-axis peer — distinct from
7385 /// the FIRST + SECOND peers on the (Option-parent × NON-DEFAULT-
7386 /// scalar-child) corner which default through a specific chosen
7387 /// baseline ([`ConvergencePointType::Gate`],
7388 /// [`SubstrateType::Compute`]) rather than through the child's
7389 /// own `#[default]`. Two-defaults composition property: both the
7390 /// parent fill-through and the child's `#[default]` land on the
7391 /// SAME variant, so the ephemeral sugar surface's `calm-Monotone`
7392 /// require-tag reads `true` on every operator-authored spec that
7393 /// omits both the `:classification` slot AND the `:calm` sub-slot,
7394 /// pinning the workspace's monotone-by-default posture.
7395 #[test]
7396 fn has_calm_probes_monotone_only_on_absent_classification() {
7397 let spec = empty_ephemeral();
7398 assert!(spec.classification.is_none());
7399 for kind in CalmClassification::ALL {
7400 let expected = kind == CalmClassification::Monotone;
7401 assert_eq!(
7402 spec.has_calm(kind),
7403 expected,
7404 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7405 );
7406 }
7407 }
7408
7409 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7410 /// identically through [`Self::has_calm`] AND through
7411 /// `<eph.clone().into::<ProcessSpec>>()`
7412 /// `.classification.has_calm(kind)` on the mechanically-
7413 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7414 /// classification on every [`CalmClassification::ALL`] variant) ×
7415 /// ALL queries so a future regression on either side of the
7416 /// resolver (a shift in the ephemeral resolver's default, a shift
7417 /// in the `From<EphemeralSpec>` lowering's fill-through) fails
7418 /// HERE at the parity boundary. Byte-for-byte peer of the sibling
7419 /// [`Self::has_point_type`] + [`Self::has_substrate`] two-surface
7420 /// parity pins on the SAME `Cow`-resolver carrier — the THIRD
7421 /// classification-axis two-surface parity contract on the
7422 /// ephemeral surface, and the FIRST on the (Option-parent ×
7423 /// DEFAULTED-scalar-child) corner.
7424 #[test]
7425 fn has_calm_matches_point_peer_through_lowered_classification() {
7426 // Absent classification: both surfaces resolve through the SAME
7427 // default and agree on every variant.
7428 let eph = empty_ephemeral();
7429 let lowered: ProcessSpec = eph.clone().into();
7430 for query in CalmClassification::ALL {
7431 assert_eq!(
7432 eph.has_calm(query),
7433 lowered.classification.has_calm(query),
7434 "None-classification parity drift on query {query:?}",
7435 );
7436 }
7437 // Authored classification: both surfaces read the same authored
7438 // value verbatim.
7439 for populated in CalmClassification::ALL {
7440 let mut classification = Classification::gate_compute();
7441 classification.calm = populated;
7442 let mut eph = empty_ephemeral();
7443 eph.classification = Some(classification);
7444 let lowered: ProcessSpec = eph.clone().into();
7445 for query in CalmClassification::ALL {
7446 assert_eq!(
7447 eph.has_calm(query),
7448 lowered.classification.has_calm(query),
7449 "authored classification.calm={populated:?}: parity drift on query {query:?}",
7450 );
7451 }
7452 }
7453 }
7454
7455 // ── EphemeralSpec::has_data_classification pins ──────────────────
7456 //
7457 // Fail-before-pass-after granularity: [`Self::has_data_classification`]
7458 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
7459 // went through `.resolved_classification().data_classification ==
7460 // kind` or through the lowered `ProcessSpec`'s
7461 // `spec.classification.has_data_classification`. Post-lift the
7462 // FOURTH classification-axis peer on the ephemeral sugar surface
7463 // routes through the SAME [`Self::resolved_classification`]
7464 // resolver + the sibling closed-set primitive
7465 // [`crate::classification::Classification::has_data_classification`],
7466 // so a regression that dropped the resolver hop, inverted the
7467 // `Some`/`None` fill-through, or wired the closure to a fixed
7468 // unrelated slot fails HERE. SECOND occupant on the (Option-parent
7469 // × DEFAULTED-scalar-child × operator-resolvable-baseline) corner
7470 // alongside [`Self::has_calm`]: both the parent fill-through
7471 // baseline (`default_ephemeral_class`) AND the child's own
7472 // `#[default]` land on the SAME variant
7473 // ([`DataClassification::Internal`]), a two-defaults composition
7474 // property the three pins below all exercise.
7475
7476 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7477 /// [`EphemeralSpec::classification`] slot names a concrete
7478 /// [`Classification`] returns `true` from
7479 /// [`Self::has_data_classification`] on the authored
7480 /// [`DataClassification`] slot and `false` for every other
7481 /// variant. Sweep the [`DataClassification::ALL`] × ALL cross so
7482 /// a regression that hard-coded the arm to a single kind or
7483 /// wired the closure to a fixed unrelated slot fails HERE at the
7484 /// substrate primitive. Byte-for-byte peer of the point-surface
7485 /// [`Classification::has_data_classification`] populated-slot
7486 /// sweep on the SAME closed-set primitive.
7487 #[test]
7488 fn has_data_classification_returns_true_iff_authored_classification_matches_per_kind() {
7489 for populated in DataClassification::ALL {
7490 let mut classification = Classification::gate_compute();
7491 classification.data_classification = populated;
7492 let mut spec = empty_ephemeral();
7493 spec.classification = Some(classification);
7494 for query in DataClassification::ALL {
7495 let expected = query == populated;
7496 assert_eq!(
7497 spec.has_data_classification(query),
7498 expected,
7499 "ephemeral classification.data_classification={populated:?}: query {query:?} drifted",
7500 );
7501 }
7502 }
7503 }
7504
7505 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7506 /// [`EphemeralSpec::classification`] slot is `None` returns
7507 /// `true` from [`Self::has_data_classification`] on
7508 /// [`DataClassification::Internal`] (the `default_ephemeral_class`
7509 /// baseline's `data_classification` axis AND the
7510 /// [`DataClassification`] child's own `#[default]` variant) and
7511 /// `false` on every other variant. Pins the (Option-parent ×
7512 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner's
7513 /// default-arm short-circuit on the FOURTH classification-axis
7514 /// peer — SECOND occupant on that corner after [`Self::has_calm`]
7515 /// opened it. Two-defaults composition property: both the parent
7516 /// fill-through and the child's `#[default]` land on the SAME
7517 /// variant, so the ephemeral sugar surface's
7518 /// `data-classification-Internal` require-tag reads `true` on
7519 /// every operator-authored spec that omits both the
7520 /// `:classification` slot AND the `:data-classification` sub-slot,
7521 /// pinning the workspace's internal-by-default sensitivity posture.
7522 #[test]
7523 fn has_data_classification_probes_internal_only_on_absent_classification() {
7524 let spec = empty_ephemeral();
7525 assert!(spec.classification.is_none());
7526 for kind in DataClassification::ALL {
7527 let expected = kind == DataClassification::Internal;
7528 assert_eq!(
7529 spec.has_data_classification(kind),
7530 expected,
7531 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7532 );
7533 }
7534 }
7535
7536 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7537 /// identically through [`Self::has_data_classification`] AND
7538 /// through `<eph.clone().into::<ProcessSpec>>()`
7539 /// `.classification.has_data_classification(kind)` on the
7540 /// mechanically-lowered `ProcessSpec`. Sweeps (`None`
7541 /// classification, `Some(_)` classification on every
7542 /// [`DataClassification::ALL`] variant) × ALL queries so a
7543 /// future regression on either side of the resolver (a shift in
7544 /// the ephemeral resolver's default, a shift in the
7545 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7546 /// the parity boundary. Byte-for-byte peer of the sibling
7547 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
7548 /// [`Self::has_calm`] two-surface parity pins on the SAME
7549 /// `Cow`-resolver carrier — the FOURTH classification-axis
7550 /// two-surface parity contract on the ephemeral surface, and the
7551 /// SECOND on the (Option-parent × DEFAULTED-scalar-child) corner.
7552 #[test]
7553 fn has_data_classification_matches_point_peer_through_lowered_classification() {
7554 // Absent classification: both surfaces resolve through the SAME
7555 // default and agree on every variant.
7556 let eph = empty_ephemeral();
7557 let lowered: ProcessSpec = eph.clone().into();
7558 for query in DataClassification::ALL {
7559 assert_eq!(
7560 eph.has_data_classification(query),
7561 lowered.classification.has_data_classification(query),
7562 "None-classification parity drift on query {query:?}",
7563 );
7564 }
7565 // Authored classification: both surfaces read the same authored
7566 // value verbatim.
7567 for populated in DataClassification::ALL {
7568 let mut classification = Classification::gate_compute();
7569 classification.data_classification = populated;
7570 let mut eph = empty_ephemeral();
7571 eph.classification = Some(classification);
7572 let lowered: ProcessSpec = eph.clone().into();
7573 for query in DataClassification::ALL {
7574 assert_eq!(
7575 eph.has_data_classification(query),
7576 lowered.classification.has_data_classification(query),
7577 "authored classification.data_classification={populated:?}: parity drift on query {query:?}",
7578 );
7579 }
7580 }
7581 }
7582
7583 // ── EphemeralSpec::has_horizon_kind pins ─────────────────────────
7584 //
7585 // Fail-before-pass-after granularity: [`Self::has_horizon_kind`]
7586 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
7587 // went through `.resolved_classification().horizon.kind == kind`
7588 // or through the lowered `ProcessSpec`'s
7589 // `spec.classification.has_horizon_kind`. Post-lift the FIFTH
7590 // classification-axis peer on the ephemeral sugar surface routes
7591 // through the SAME [`Self::resolved_classification`] resolver +
7592 // the sibling closed-set primitive
7593 // [`crate::classification::Classification::has_horizon_kind`], so
7594 // a regression that dropped the resolver hop, inverted the
7595 // `Some`/`None` fill-through, or wired the closure to a fixed
7596 // unrelated slot fails HERE. OPENS a fresh (Option-parent ×
7597 // NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
7598 // corner on the ephemeral surface — distinct from the four prior
7599 // scalar-carrier peers on the (Option-parent × NON-DEFAULT-scalar-
7600 // child) and (Option-parent × DEFAULTED-scalar-child) corners, all
7601 // of which reach a discriminator DIRECTLY off a scalar
7602 // [`Classification`] slot. Both the parent Option's fill-through
7603 // baseline (`default_ephemeral_class`, which fills
7604 // `horizon: Horizon::default()`) AND the child's own `#[default]`
7605 // land on the SAME variant ([`HorizonKind::Bounded`]) — a two-
7606 // defaults composition property the three pins below all
7607 // exercise.
7608
7609 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7610 /// [`EphemeralSpec::classification`] slot names a concrete
7611 /// [`Classification`] returns `true` from
7612 /// [`Self::has_horizon_kind`] on the authored [`HorizonKind`] slot
7613 /// and `false` for every other variant. Sweep the
7614 /// [`HorizonKind::ALL`] × ALL cross so a regression that hard-
7615 /// coded the arm to a single kind or wired the closure to a
7616 /// fixed unrelated slot (e.g. reading `self.classification` as if
7617 /// it were a scalar rather than routing through
7618 /// `resolved_classification().horizon.kind`) fails HERE at the
7619 /// substrate primitive. Byte-for-byte peer of the point-surface
7620 /// [`Classification::has_horizon_kind`] populated-slot sweep on
7621 /// the SAME closed-set primitive.
7622 #[test]
7623 fn has_horizon_kind_returns_true_iff_authored_classification_matches_per_kind() {
7624 for populated in HorizonKind::ALL {
7625 let classification = Classification::gate_compute_with_axis(populated);
7626 let mut spec = empty_ephemeral();
7627 spec.classification = Some(classification);
7628 for query in HorizonKind::ALL {
7629 let expected = query == populated;
7630 assert_eq!(
7631 spec.has_horizon_kind(query),
7632 expected,
7633 "ephemeral classification.horizon.kind={populated:?}: query {query:?} drifted",
7634 );
7635 }
7636 }
7637 }
7638
7639 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7640 /// [`EphemeralSpec::classification`] slot is `None` returns
7641 /// `true` from [`Self::has_horizon_kind`] on
7642 /// [`HorizonKind::Bounded`] (the `default_ephemeral_class`
7643 /// baseline's `horizon.kind` axis AND the [`HorizonKind`] child's
7644 /// own `#[default]` variant) and `false` on every other variant.
7645 /// Pins the fresh (Option-parent × NESTED-STRUCT-scalar-child ×
7646 /// operator-resolvable-baseline) corner's default-arm short-
7647 /// circuit on the FIFTH classification-axis peer. Two-defaults
7648 /// composition property through a NESTED-STRUCT hop: both the
7649 /// parent Option's fill-through baseline
7650 /// (`default_ephemeral_class` fills `horizon: Horizon::default()`)
7651 /// AND the child's own `#[default]` (`HorizonKind::Bounded` via
7652 /// `#[default]` on the closed set) land on the SAME variant, so
7653 /// the ephemeral sugar surface's `horizon-Bounded` require-tag
7654 /// reads `true` on every operator-authored spec that omits both
7655 /// the `:classification` slot AND the `:horizon` sub-slot,
7656 /// pinning the workspace's bounded-by-default lifetime posture.
7657 #[test]
7658 fn has_horizon_kind_probes_bounded_only_on_absent_classification() {
7659 let spec = empty_ephemeral();
7660 assert!(spec.classification.is_none());
7661 for kind in HorizonKind::ALL {
7662 let expected = kind == HorizonKind::Bounded;
7663 assert_eq!(
7664 spec.has_horizon_kind(kind),
7665 expected,
7666 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7667 );
7668 }
7669 }
7670
7671 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7672 /// identically through [`Self::has_horizon_kind`] AND through
7673 /// `<eph.clone().into::<ProcessSpec>>()`
7674 /// `.classification.has_horizon_kind(kind)` on the mechanically-
7675 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7676 /// classification on every [`HorizonKind::ALL`] variant) × ALL
7677 /// queries so a future regression on either side of the resolver
7678 /// (a shift in the ephemeral resolver's default, a shift in the
7679 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7680 /// the parity boundary. Byte-for-byte peer of the sibling
7681 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
7682 /// [`Self::has_calm`] + [`Self::has_data_classification`] two-
7683 /// surface parity pins on the SAME `Cow`-resolver carrier — the
7684 /// FIFTH classification-axis two-surface parity contract on the
7685 /// ephemeral surface, and the FIRST on the (Option-parent ×
7686 /// NESTED-STRUCT-scalar-child) corner.
7687 #[test]
7688 fn has_horizon_kind_matches_point_peer_through_lowered_classification() {
7689 // Absent classification: both surfaces resolve through the SAME
7690 // default and agree on every variant.
7691 let eph = empty_ephemeral();
7692 let lowered: ProcessSpec = eph.clone().into();
7693 for query in HorizonKind::ALL {
7694 assert_eq!(
7695 eph.has_horizon_kind(query),
7696 lowered.classification.has_horizon_kind(query),
7697 "None-classification parity drift on query {query:?}",
7698 );
7699 }
7700 // Authored classification: both surfaces read the same authored
7701 // value verbatim.
7702 for populated in HorizonKind::ALL {
7703 let classification = Classification::gate_compute_with_axis(populated);
7704 let mut eph = empty_ephemeral();
7705 eph.classification = Some(classification);
7706 let lowered: ProcessSpec = eph.clone().into();
7707 for query in HorizonKind::ALL {
7708 assert_eq!(
7709 eph.has_horizon_kind(query),
7710 lowered.classification.has_horizon_kind(query),
7711 "authored classification.horizon.kind={populated:?}: parity drift on query {query:?}",
7712 );
7713 }
7714 }
7715 }
7716
7717 // ── EphemeralSpec::has_optimization_direction pins ───────────────
7718 //
7719 // Fail-before-pass-after granularity:
7720 // [`Self::has_optimization_direction`] did not exist pre-lift on
7721 // `impl EphemeralSpec` — every callsite went through
7722 // `.resolved_classification().horizon.direction.unwrap_or_default() == kind`
7723 // or through the lowered `ProcessSpec`'s
7724 // `spec.classification.has_optimization_direction`. Post-lift the
7725 // SIXTH classification-axis peer on the ephemeral sugar surface
7726 // routes through the SAME [`Self::resolved_classification`]
7727 // resolver + the sibling closed-set primitive
7728 // [`crate::classification::Classification::has_optimization_direction`],
7729 // so a regression that dropped the resolver hop, inverted the
7730 // `Some`/`None` fill-through, wired the closure to a fixed
7731 // unrelated slot, or flipped [`OptimizationDirection`]'s
7732 // `#[default]` off `Minimize` fails HERE. SECOND occupant on the
7733 // (Option-parent × NESTED-STRUCT-scalar-child × operator-
7734 // resolvable-baseline) corner alongside
7735 // [`Self::has_horizon_kind`] — pinning the corner as a proven-
7736 // repeatable primitive shape on the ephemeral surface with a
7737 // second nested-struct-child probe, and DEMONSTRATING that the
7738 // corner admits both direct-scalar and Option-scalar traversals
7739 // through the SAME nested [`Horizon`] intermediary via the closed
7740 // set's `Default` on the inner `Option<OptimizationDirection>`
7741 // slot.
7742
7743 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7744 /// [`EphemeralSpec::classification`] slot names a concrete
7745 /// [`Classification`] whose [`crate::classification::Horizon::direction`]
7746 /// slot carries `Some(<direction>)` returns `true` from
7747 /// [`Self::has_optimization_direction`] on the authored
7748 /// [`OptimizationDirection`] variant and `false` for every other
7749 /// variant. Sweep the [`OptimizationDirection::ALL`] × ALL cross
7750 /// so a regression that hard-coded the arm to a single kind, or
7751 /// dropped the `Option::unwrap_or_default` collapse, or wired the
7752 /// closure to a fixed unrelated slot (e.g. reading `self.horizon.kind`)
7753 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
7754 /// point-surface
7755 /// [`Classification::has_optimization_direction`] populated-slot
7756 /// sweep on the SAME closed-set primitive.
7757 #[test]
7758 fn has_optimization_direction_returns_true_iff_authored_direction_matches_per_kind() {
7759 for populated in OptimizationDirection::ALL {
7760 let classification = Classification::gate_compute_with_axis(populated);
7761 let mut spec = empty_ephemeral();
7762 spec.classification = Some(classification);
7763 for query in OptimizationDirection::ALL {
7764 let expected = query == populated;
7765 assert_eq!(
7766 spec.has_optimization_direction(query),
7767 expected,
7768 "ephemeral classification.horizon.direction=Some({populated:?}): query {query:?} drifted",
7769 );
7770 }
7771 }
7772 }
7773
7774 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7775 /// [`EphemeralSpec::classification`] slot is `None` returns
7776 /// `true` from [`Self::has_optimization_direction`] on
7777 /// [`OptimizationDirection::Minimize`] (the `default_ephemeral_class`
7778 /// baseline fills `horizon: Horizon::default()`, which in turn
7779 /// leaves `direction: None`, and the substrate's
7780 /// `Option::unwrap_or_default` collapse then reads
7781 /// [`OptimizationDirection::Minimize`] via the closed set's
7782 /// `#[default]`) and `false` on every other variant. Pins the
7783 /// (Option-parent × NESTED-STRUCT-scalar-child × operator-
7784 /// resolvable-baseline) corner's default-arm short-circuit on the
7785 /// SIXTH classification-axis peer through TWO Option-hops: parent
7786 /// `EphemeralSpec::classification` and inner `Horizon::direction`
7787 /// both `None`, both collapsing to the closed set's `#[default]`
7788 /// [`OptimizationDirection::Minimize`]. A regression that promoted
7789 /// [`OptimizationDirection::Maximize`] to `#[default]` (silently
7790 /// inverting every unadorned Process's rate-window evaluator
7791 /// polarity), dropped `Option::unwrap_or_default`, or wired the arm
7792 /// to a fixed variant answer fails HERE.
7793 #[test]
7794 fn has_optimization_direction_probes_minimize_only_on_absent_classification() {
7795 let spec = empty_ephemeral();
7796 assert!(spec.classification.is_none());
7797 for kind in OptimizationDirection::ALL {
7798 let expected = kind == OptimizationDirection::Minimize;
7799 assert_eq!(
7800 spec.has_optimization_direction(kind),
7801 expected,
7802 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7803 );
7804 }
7805 }
7806
7807 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7808 /// identically through [`Self::has_optimization_direction`] AND
7809 /// through
7810 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
7811 /// on the mechanically-lowered `ProcessSpec`. Sweeps three arms —
7812 /// (`None` classification), (`Some(_)` classification with
7813 /// `direction: None`), and (`Some(_)` classification on every
7814 /// [`OptimizationDirection::ALL`] variant) — × ALL queries so a
7815 /// future regression on either side of the resolver (an ephemeral-
7816 /// side fill-through drift, a lowering-side `From<EphemeralSpec>`
7817 /// `unwrap_or_else(default_ephemeral_class)` drift, an inner
7818 /// `Option::unwrap_or_default` collapse drift on either side)
7819 /// fails HERE at the parity boundary. Byte-for-byte peer of the
7820 /// sibling [`Self::has_point_type`] + [`Self::has_substrate`] +
7821 /// [`Self::has_calm`] + [`Self::has_data_classification`] +
7822 /// [`Self::has_horizon_kind`] two-surface parity pins on the SAME
7823 /// `Cow`-resolver carrier — the SIXTH classification-axis two-
7824 /// surface parity contract on the ephemeral surface, and the
7825 /// SECOND on the (Option-parent × NESTED-STRUCT-scalar-child)
7826 /// corner.
7827 #[test]
7828 fn has_optimization_direction_matches_point_peer_through_lowered_classification() {
7829 // Absent classification: both surfaces resolve through the SAME
7830 // default and agree on every variant.
7831 let eph = empty_ephemeral();
7832 let lowered: ProcessSpec = eph.clone().into();
7833 for query in OptimizationDirection::ALL {
7834 assert_eq!(
7835 eph.has_optimization_direction(query),
7836 lowered.classification.has_optimization_direction(query),
7837 "None-classification parity drift on query {query:?}",
7838 );
7839 }
7840 // Authored classification with `direction: None` — the inner
7841 // Option collapses through `unwrap_or_default` on both sides,
7842 // reading `Minimize`.
7843 let mut classification = Classification::gate_compute();
7844 classification.horizon = Horizon::default();
7845 let mut eph = empty_ephemeral();
7846 eph.classification = Some(classification);
7847 let lowered: ProcessSpec = eph.clone().into();
7848 for query in OptimizationDirection::ALL {
7849 assert_eq!(
7850 eph.has_optimization_direction(query),
7851 lowered.classification.has_optimization_direction(query),
7852 "authored classification with horizon.direction=None: parity drift on query {query:?}",
7853 );
7854 }
7855 // Authored classification with `direction: Some(_)` — both
7856 // surfaces read the same authored value verbatim.
7857 for populated in OptimizationDirection::ALL {
7858 let classification = Classification::gate_compute_with_axis(populated);
7859 let mut eph = empty_ephemeral();
7860 eph.classification = Some(classification);
7861 let lowered: ProcessSpec = eph.clone().into();
7862 for query in OptimizationDirection::ALL {
7863 assert_eq!(
7864 eph.has_optimization_direction(query),
7865 lowered.classification.has_optimization_direction(query),
7866 "authored classification.horizon.direction=Some({populated:?}): parity drift on query {query:?}",
7867 );
7868 }
7869 }
7870 }
7871
7872 // ── EphemeralSpec::has_input_arity pins ──────────────────────────
7873 //
7874 // Fail-before-pass-after granularity: [`Self::has_input_arity`] did
7875 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
7876 // through `.resolved_classification().point_type.input_arity() ==
7877 // kind` or through the lowered `ProcessSpec`'s
7878 // `spec.classification.has_input_arity`. Post-lift the SEVENTH
7879 // classification-axis peer on the ephemeral sugar surface routes
7880 // through the SAME [`Self::resolved_classification`] resolver + the
7881 // sibling closed-set primitive
7882 // [`crate::classification::Classification::has_input_arity`], so a
7883 // regression that dropped the resolver hop, dropped the
7884 // `.input_arity()` projection call, inverted the projection (`One
7885 // ↔ Many`), or crossed the wires with the sibling
7886 // [`ConvergencePointType::output_arity`] projection fails HERE.
7887 // OPENS the (Option-parent × NESTED-STRUCT-scalar-child ×
7888 // derived-typed-projection) corner on the ephemeral surface —
7889 // distinct from the two prior nested-scalar peers on the corner
7890 // (`has_horizon_kind` reads `horizon.kind` directly;
7891 // `has_optimization_direction` reads `horizon.direction` through an
7892 // Option collapse), both of which reach a discriminator DIRECTLY off
7893 // a scalar. This peer instead threads through a many-to-one closed-
7894 // set typed projection so the child's closed set is REACHED THROUGH
7895 // a projection layer, pinning the corner as admitting three
7896 // ephemeral-surface traversal shapes (direct-scalar, Option-scalar-
7897 // with-default, derived-typed-projection) through the SAME resolver
7898 // walk.
7899
7900 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
7901 /// [`EphemeralSpec::classification`] slot names a concrete
7902 /// [`Classification`] with an authored [`ConvergencePointType`]
7903 /// returns `true` from [`Self::has_input_arity`] on the [`Arity`]
7904 /// value the projection [`ConvergencePointType::input_arity`] maps
7905 /// the authored point-type to and `false` for every other variant.
7906 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
7907 /// a regression that (a) dropped the projection call, (b) inverted
7908 /// the projection, (c) probed [`ConvergencePointType`] directly, or
7909 /// (d) crossed wires with [`ConvergencePointType::output_arity`]
7910 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
7911 /// point-surface [`Classification::has_input_arity`] populated-slot
7912 /// sweep on the SAME closed-set primitive routed through the SAME
7913 /// projection.
7914 #[test]
7915 fn has_input_arity_returns_true_iff_authored_point_type_projects_per_kind() {
7916 for populated in ConvergencePointType::ALL {
7917 let mut classification = Classification::gate_compute();
7918 classification.point_type = populated;
7919 let mut spec = empty_ephemeral();
7920 spec.classification = Some(classification);
7921 let projected = populated.input_arity();
7922 for query in Arity::ALL {
7923 let expected = query == projected;
7924 assert_eq!(
7925 spec.has_input_arity(query),
7926 expected,
7927 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
7928 );
7929 }
7930 }
7931 }
7932
7933 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
7934 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
7935 /// from [`Self::has_input_arity`] on [`Arity::Many`] (the
7936 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
7937 /// and [`ConvergencePointType::input_arity`] projects
7938 /// `Gate → Arity::Many`) and `false` on [`Arity::One`]. Pins the
7939 /// (Option-parent × NESTED-STRUCT-scalar-child × derived-typed-
7940 /// projection) corner's baseline projection on the SEVENTH
7941 /// classification-axis peer through a chain of TWO fill-throughs
7942 /// composed with ONE projection: the parent Option's
7943 /// `unwrap_or_else(default_ephemeral_class)` picks the substrate
7944 /// baseline, and the projection then collapses the baseline's
7945 /// point-type through the closed-set-driven many-to-one bucket
7946 /// walk. [`Arity`] carries no `#[default]`, so there is NO default-
7947 /// arm short-circuit shortcut here — the answer flows entirely
7948 /// through the projection's bucket-membership decision. A
7949 /// regression that promoted the baseline's `point_type` off `Gate`
7950 /// (silently flipping every unadorned Process's convergent-by-
7951 /// default input-side posture to endomorphic or diffusive), dropped
7952 /// the projection call, inverted the projection, or crossed wires
7953 /// with [`ConvergencePointType::output_arity`] (which would flip
7954 /// the baseline answer from `Many` to `One` for `Gate`) fails HERE.
7955 #[test]
7956 fn has_input_arity_probes_many_only_on_absent_classification() {
7957 let spec = empty_ephemeral();
7958 assert!(spec.classification.is_none());
7959 for kind in Arity::ALL {
7960 let expected = kind == Arity::Many;
7961 assert_eq!(
7962 spec.has_input_arity(kind),
7963 expected,
7964 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many): query {kind:?} must be {expected}",
7965 );
7966 }
7967 }
7968
7969 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7970 /// identically through [`Self::has_input_arity`] AND through
7971 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
7972 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
7973 /// classification, `Some(_)` classification on every
7974 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
7975 /// so a future regression on either side of the resolver (a shift
7976 /// in the ephemeral resolver's default, a shift in the
7977 /// `From<EphemeralSpec>` lowering's fill-through, a projection
7978 /// drift on either side) fails HERE at the parity boundary. Byte-
7979 /// for-byte peer of the sibling [`Self::has_point_type`] +
7980 /// [`Self::has_substrate`] + [`Self::has_calm`] +
7981 /// [`Self::has_data_classification`] + [`Self::has_horizon_kind`] +
7982 /// [`Self::has_optimization_direction`] two-surface parity pins on
7983 /// the SAME `Cow`-resolver carrier — the SEVENTH classification-
7984 /// axis two-surface parity contract on the ephemeral surface, and
7985 /// the FIRST on the (Option-parent × NESTED-STRUCT-scalar-child ×
7986 /// derived-typed-projection) corner.
7987 #[test]
7988 fn has_input_arity_matches_point_peer_through_lowered_classification() {
7989 // Absent classification: both surfaces resolve through the SAME
7990 // default and agree on every variant.
7991 let eph = empty_ephemeral();
7992 let lowered: ProcessSpec = eph.clone().into();
7993 for query in Arity::ALL {
7994 assert_eq!(
7995 eph.has_input_arity(query),
7996 lowered.classification.has_input_arity(query),
7997 "None-classification parity drift on query {query:?}",
7998 );
7999 }
8000 // Authored classification: both surfaces read the same authored
8001 // point_type and route through the same projection.
8002 for populated in ConvergencePointType::ALL {
8003 let mut classification = Classification::gate_compute();
8004 classification.point_type = populated;
8005 let mut eph = empty_ephemeral();
8006 eph.classification = Some(classification);
8007 let lowered: ProcessSpec = eph.clone().into();
8008 for query in Arity::ALL {
8009 assert_eq!(
8010 eph.has_input_arity(query),
8011 lowered.classification.has_input_arity(query),
8012 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8013 );
8014 }
8015 }
8016 }
8017
8018 // ── EphemeralSpec::has_output_arity pins ─────────────────────────
8019 //
8020 // Fail-before-pass-after granularity: [`Self::has_output_arity`] did
8021 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8022 // through `.resolved_classification().point_type.output_arity() ==
8023 // kind` or through the lowered `ProcessSpec`'s
8024 // `spec.classification.has_output_arity`. Post-lift the EIGHTH
8025 // classification-axis peer on the ephemeral sugar surface routes
8026 // through the SAME [`Self::resolved_classification`] resolver + the
8027 // sibling closed-set primitive
8028 // [`crate::classification::Classification::has_output_arity`], so a
8029 // regression that dropped the resolver hop, dropped the
8030 // `.output_arity()` projection call, inverted the projection (`One
8031 // ↔ Many`), or crossed the wires with the sibling
8032 // [`ConvergencePointType::input_arity`] projection fails HERE.
8033 // CLOSES the (Option-parent × NESTED-STRUCT-scalar-child ×
8034 // derived-typed-projection) corner on the ephemeral surface as the
8035 // SECOND occupant — co-tenant with [`Self::has_input_arity`] on the
8036 // SAME `point_type` scalar carrier through the SAME [`Arity`] closed
8037 // set but through the sibling many-to-one projection, closing the
8038 // DAG-composition arity pair on the ephemeral side.
8039
8040 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
8041 /// [`EphemeralSpec::classification`] slot names a concrete
8042 /// [`Classification`] with an authored [`ConvergencePointType`]
8043 /// returns `true` from [`Self::has_output_arity`] on the [`Arity`]
8044 /// value the projection [`ConvergencePointType::output_arity`] maps
8045 /// the authored point-type to and `false` for every other variant.
8046 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
8047 /// a regression that (a) dropped the projection call, (b) inverted
8048 /// the projection, (c) probed [`ConvergencePointType`] directly, or
8049 /// (d) crossed wires with [`ConvergencePointType::input_arity`]
8050 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
8051 /// point-surface [`Classification::has_output_arity`] populated-slot
8052 /// sweep on the SAME closed-set primitive routed through the SAME
8053 /// projection.
8054 #[test]
8055 fn has_output_arity_returns_true_iff_authored_point_type_projects_per_kind() {
8056 for populated in ConvergencePointType::ALL {
8057 let mut classification = Classification::gate_compute();
8058 classification.point_type = populated;
8059 let mut spec = empty_ephemeral();
8060 spec.classification = Some(classification);
8061 let projected = populated.output_arity();
8062 for query in Arity::ALL {
8063 let expected = query == projected;
8064 assert_eq!(
8065 spec.has_output_arity(query),
8066 expected,
8067 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
8068 );
8069 }
8070 }
8071 }
8072
8073 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
8074 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
8075 /// from [`Self::has_output_arity`] on [`Arity::One`] (the
8076 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
8077 /// and [`ConvergencePointType::output_arity`] projects
8078 /// `Gate → Arity::One`) and `false` on [`Arity::Many`]. MIRROR of
8079 /// the [`Self::has_input_arity`] baseline (`Gate → input_arity =
8080 /// Many`) — the DAG-composition arity pair projects the same `Gate`
8081 /// baseline through the two projections to opposite [`Arity`] arms,
8082 /// so this pin locks the output-side half of that pair against a
8083 /// regression that (a) promoted the baseline's `point_type` off
8084 /// `Gate` (silently flipping every unadorned Process's convergent-
8085 /// by-default output-side posture to diffusive), (b) dropped the
8086 /// projection call, (c) inverted the projection, or (d) crossed
8087 /// wires with [`ConvergencePointType::input_arity`] (which would
8088 /// flip the baseline answer from `One` to `Many` for `Gate`).
8089 #[test]
8090 fn has_output_arity_probes_one_only_on_absent_classification() {
8091 let spec = empty_ephemeral();
8092 assert!(spec.classification.is_none());
8093 for kind in Arity::ALL {
8094 let expected = kind == Arity::One;
8095 assert_eq!(
8096 spec.has_output_arity(kind),
8097 expected,
8098 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One): query {kind:?} must be {expected}",
8099 );
8100 }
8101 }
8102
8103 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8104 /// identically through [`Self::has_output_arity`] AND through
8105 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
8106 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8107 /// classification, `Some(_)` classification on every
8108 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
8109 /// so a future regression on either side of the resolver fails HERE
8110 /// at the parity boundary. Byte-for-byte peer of the seven sibling
8111 /// two-surface parity pins on the SAME `Cow`-resolver carrier — the
8112 /// EIGHTH classification-axis two-surface parity contract on the
8113 /// ephemeral surface, closing the SECOND occupant of the (Option-
8114 /// parent × NESTED-STRUCT-scalar-child × derived-typed-projection)
8115 /// corner.
8116 #[test]
8117 fn has_output_arity_matches_point_peer_through_lowered_classification() {
8118 // Absent classification: both surfaces resolve through the SAME
8119 // default and agree on every variant.
8120 let eph = empty_ephemeral();
8121 let lowered: ProcessSpec = eph.clone().into();
8122 for query in Arity::ALL {
8123 assert_eq!(
8124 eph.has_output_arity(query),
8125 lowered.classification.has_output_arity(query),
8126 "None-classification parity drift on query {query:?}",
8127 );
8128 }
8129 // Authored classification: both surfaces read the same authored
8130 // point_type and route through the same projection.
8131 for populated in ConvergencePointType::ALL {
8132 let mut classification = Classification::gate_compute();
8133 classification.point_type = populated;
8134 let mut eph = empty_ephemeral();
8135 eph.classification = Some(classification);
8136 let lowered: ProcessSpec = eph.clone().into();
8137 for query in Arity::ALL {
8138 assert_eq!(
8139 eph.has_output_arity(query),
8140 lowered.classification.has_output_arity(query),
8141 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8142 );
8143 }
8144 }
8145 }
8146
8147 /// DAG-COMPOSITION ARITY-PAIR pin — the SEVENTH
8148 /// ([`Self::has_input_arity`]) and EIGHTH
8149 /// ([`Self::has_output_arity`]) classification-axis peers on the
8150 /// ephemeral surface walk the SAME `point_type` scalar carrier
8151 /// (routed through the SAME [`Self::resolved_classification`]
8152 /// resolver) through the SAME [`Arity`] closed set but through
8153 /// DIFFERENT typed projections
8154 /// ([`ConvergencePointType::input_arity`] vs.
8155 /// [`ConvergencePointType::output_arity`]). An [`EphemeralSpec`]
8156 /// with `classification.point_type = Fork` (the diffusive `(One,
8157 /// Many)` cell) MUST simultaneously answer `has_input_arity(One)`
8158 /// true AND `has_output_arity(Many)` true AND
8159 /// `has_input_arity(Many)` false AND `has_output_arity(One)` false.
8160 /// An [`EphemeralSpec`] with `point_type = Transform` (endomorphic
8161 /// `(One, One)`) MUST answer BOTH `has_input_arity(One)` and
8162 /// `has_output_arity(One)` true — the two projections AGREE in the
8163 /// endomorphic bucket. The absent-classification baseline (Gate,
8164 /// convergent `(Many, One)`) MUST answer
8165 /// `has_input_arity(Many)` true AND `has_output_arity(One)` true —
8166 /// the mirror of the Fork case. A regression that (a) collapsed
8167 /// `has_output_arity` onto `has_input_arity`, (b) swapped the
8168 /// projection direction, or (c) drifted the topology-bucket
8169 /// contract fails HERE at ONE narrow ephemeral-surface site,
8170 /// symmetric with the point-surface DAG-composition arity-pair pin.
8171 #[test]
8172 fn has_input_arity_and_has_output_arity_pin_dag_composition_pair() {
8173 // Diffusive cell: Fork carries (input, output) = (One, Many)
8174 let mut classification = Classification::gate_compute();
8175 classification.point_type = ConvergencePointType::Fork;
8176 let mut fork = empty_ephemeral();
8177 fork.classification = Some(classification);
8178 assert!(fork.has_input_arity(Arity::One));
8179 assert!(fork.has_output_arity(Arity::Many));
8180 assert!(!fork.has_input_arity(Arity::Many));
8181 assert!(!fork.has_output_arity(Arity::One));
8182
8183 // Endomorphic cell: Transform carries (input, output) = (One, One)
8184 let mut classification = Classification::gate_compute();
8185 classification.point_type = ConvergencePointType::Transform;
8186 let mut transform = empty_ephemeral();
8187 transform.classification = Some(classification);
8188 assert!(transform.has_input_arity(Arity::One));
8189 assert!(transform.has_output_arity(Arity::One));
8190 assert!(!transform.has_input_arity(Arity::Many));
8191 assert!(!transform.has_output_arity(Arity::Many));
8192
8193 // Convergent cell: absent classification defaults to Gate,
8194 // which carries (input, output) = (Many, One).
8195 let gate = empty_ephemeral();
8196 assert!(gate.classification.is_none());
8197 assert!(gate.has_input_arity(Arity::Many));
8198 assert!(gate.has_output_arity(Arity::One));
8199 assert!(!gate.has_input_arity(Arity::One));
8200 assert!(!gate.has_output_arity(Arity::Many));
8201 }
8202
8203 // ── EphemeralSpec::horizon_terminates pins ───────────────────────
8204 //
8205 // Fail-before-pass-after granularity: `horizon_terminates` did not
8206 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8207 // the "does this ephemeral spec's horizon terminate?" question
8208 // went through `.resolved_classification().horizon.kind.terminates()`
8209 // or through the lowered `ProcessSpec`'s
8210 // `spec.classification.horizon.kind.terminates()`. Post-lift the
8211 // NINTH classification-axis peer on the ephemeral surface routes
8212 // through the SAME [`Self::resolved_classification`] resolver +
8213 // the sibling substrate primitive
8214 // [`crate::classification::Classification::horizon_terminates`],
8215 // so the two-surface parity contract holds by construction — a
8216 // regression on either side of the resolver fails at these pins
8217 // before landing at the operator-facing `terminating-horizon`
8218 // fixed tag in `tatara-check`.
8219
8220 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8221 /// [`Classification`] carries a specific [`HorizonKind`] variant
8222 /// answers [`Self::horizon_terminates`] matching the closed
8223 /// set's own [`HorizonKind::terminates`] truth table. Sweep
8224 /// [`HorizonKind::ALL`] so a regression that (a) hard-coded the
8225 /// body to a fixed answer, (b) inverted the projection, or (c)
8226 /// crossed the wires with the antisymmetric partner
8227 /// [`HorizonKind::requires_metric_axes`] fails HERE at the
8228 /// substrate primitive before drifting through the
8229 /// `terminating-horizon` fixed tag or the peer point surface.
8230 #[test]
8231 fn horizon_terminates_returns_horizon_kind_projection_per_kind() {
8232 for populated in HorizonKind::ALL {
8233 let classification = Classification::gate_compute_with_axis(populated);
8234 let mut spec = empty_ephemeral();
8235 spec.classification = Some(classification);
8236 assert_eq!(
8237 spec.horizon_terminates(),
8238 populated.terminates(),
8239 "authored horizon.kind={populated:?}: horizon_terminates() drift",
8240 );
8241 }
8242 }
8243
8244 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8245 /// with `classification: None` routes through the
8246 /// [`Self::resolved_classification`] resolver's substrate default
8247 /// [`Classification::gate_compute`], which uses
8248 /// [`crate::classification::Horizon::default`] whose `kind`
8249 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
8250 /// [`HorizonKind::Bounded::terminates`] projects `true`, so
8251 /// [`Self::horizon_terminates`] returns `true`. Pins the default-
8252 /// arm short-circuit through THREE layers of `Default`
8253 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
8254 /// [`HorizonKind::default`]) reaching this derived-nullary
8255 /// predicate — a regression that dropped the resolver hop
8256 /// (silently answering `false` on an absent classification, as
8257 /// if the operator's absence meant "no horizon at all") fails
8258 /// HERE at ONE narrow ephemeral-surface site.
8259 #[test]
8260 fn horizon_terminates_probes_true_on_absent_classification() {
8261 let spec = empty_ephemeral();
8262 assert!(spec.classification.is_none());
8263 assert!(
8264 spec.horizon_terminates(),
8265 "absent classification (defaults to gate_compute, horizon.kind=Bounded → terminates=true)",
8266 );
8267 }
8268
8269 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8270 /// identically through [`Self::horizon_terminates`] AND through
8271 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_terminates()`
8272 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8273 /// classification, `Some(_)` classification on every
8274 /// [`HorizonKind::ALL`] variant) so a future regression on
8275 /// either side of the resolver fails HERE at the parity
8276 /// boundary. Byte-for-byte peer of the eight sibling two-surface
8277 /// parity pins on the SAME `Cow`-resolver carrier — the NINTH
8278 /// classification-axis two-surface parity contract on the
8279 /// ephemeral surface, and the FIRST via a derived-nullary-
8280 /// boolean predicate rather than a variant-equality probe.
8281 #[test]
8282 fn horizon_terminates_matches_point_peer_through_lowered_classification() {
8283 // Absent classification: both surfaces resolve through the SAME
8284 // default and agree.
8285 let eph = empty_ephemeral();
8286 let lowered: ProcessSpec = eph.clone().into();
8287 assert_eq!(
8288 eph.horizon_terminates(),
8289 lowered.classification.horizon_terminates(),
8290 "None-classification parity drift",
8291 );
8292 // Authored classification: both surfaces read the same authored
8293 // horizon.kind and route through the same projection.
8294 for populated in HorizonKind::ALL {
8295 let classification = Classification::gate_compute_with_axis(populated);
8296 let mut eph = empty_ephemeral();
8297 eph.classification = Some(classification);
8298 let lowered: ProcessSpec = eph.clone().into();
8299 assert_eq!(
8300 eph.horizon_terminates(),
8301 lowered.classification.horizon_terminates(),
8302 "authored horizon.kind={populated:?}: parity drift",
8303 );
8304 }
8305 }
8306
8307 // ── EphemeralSpec::horizon_requires_metric_axes pins ─────────────
8308 //
8309 // Fail-before-pass-after granularity: `horizon_requires_metric_axes`
8310 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
8311 // walking the "does this ephemeral spec's horizon require metric
8312 // axes?" question went through
8313 // `.resolved_classification().horizon.kind.requires_metric_axes()`
8314 // or through the lowered `ProcessSpec`'s
8315 // `spec.classification.horizon.kind.requires_metric_axes()`. Post-
8316 // lift the antisymmetric peer of `horizon_terminates` routes
8317 // through the SAME [`Self::resolved_classification`] resolver +
8318 // the sibling substrate primitive
8319 // [`crate::classification::Classification::horizon_requires_metric_axes`],
8320 // so the two-surface parity contract holds by construction — a
8321 // regression on either side of the resolver fails at these pins
8322 // before landing at the operator-facing `metric-axes-required`
8323 // fixed tag in `tatara-check`.
8324
8325 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8326 /// [`Classification`] carries a specific [`HorizonKind`] variant
8327 /// answers [`Self::horizon_requires_metric_axes`] matching the
8328 /// closed set's own [`HorizonKind::requires_metric_axes`] truth
8329 /// table. Sweep [`HorizonKind::ALL`] so a regression that (a)
8330 /// hard-coded the body to a fixed answer, (b) inverted the
8331 /// projection, or (c) crossed the wires with the antisymmetric
8332 /// partner [`HorizonKind::terminates`] fails HERE at the
8333 /// substrate primitive before drifting through the
8334 /// `metric-axes-required` fixed tag or the peer point surface.
8335 #[test]
8336 fn horizon_requires_metric_axes_returns_horizon_kind_projection_per_kind() {
8337 for populated in HorizonKind::ALL {
8338 let classification = Classification::gate_compute_with_axis(populated);
8339 let mut spec = empty_ephemeral();
8340 spec.classification = Some(classification);
8341 assert_eq!(
8342 spec.horizon_requires_metric_axes(),
8343 populated.requires_metric_axes(),
8344 "authored horizon.kind={populated:?}: horizon_requires_metric_axes() drift",
8345 );
8346 }
8347 }
8348
8349 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8350 /// with `classification: None` routes through the
8351 /// [`Self::resolved_classification`] resolver's substrate default
8352 /// [`Classification::gate_compute`], which uses
8353 /// [`crate::classification::Horizon::default`] whose `kind`
8354 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
8355 /// [`HorizonKind::Bounded::requires_metric_axes`] projects
8356 /// `false`, so [`Self::horizon_requires_metric_axes`] returns
8357 /// `false`. Pins the default-arm short-circuit through THREE
8358 /// layers of `Default` ([`Classification::gate_compute`] →
8359 /// [`Horizon::default`] → [`HorizonKind::default`]) reaching this
8360 /// derived-nullary predicate — mirror image of
8361 /// `horizon_terminates_probes_true_on_absent_classification`.
8362 #[test]
8363 fn horizon_requires_metric_axes_probes_false_on_absent_classification() {
8364 let spec = empty_ephemeral();
8365 assert!(spec.classification.is_none());
8366 assert!(
8367 !spec.horizon_requires_metric_axes(),
8368 "absent classification (defaults to gate_compute, horizon.kind=Bounded → requires_metric_axes=false)",
8369 );
8370 }
8371
8372 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8373 /// identically through [`Self::horizon_requires_metric_axes`]
8374 /// AND through
8375 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_requires_metric_axes()`
8376 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8377 /// classification, `Some(_)` classification on every
8378 /// [`HorizonKind::ALL`] variant) so a future regression on
8379 /// either side of the resolver fails HERE at the parity
8380 /// boundary. Byte-for-byte peer of the sibling
8381 /// `horizon_terminates_matches_point_peer_through_lowered_classification`.
8382 #[test]
8383 fn horizon_requires_metric_axes_matches_point_peer_through_lowered_classification() {
8384 // Absent classification.
8385 let eph = empty_ephemeral();
8386 let lowered: ProcessSpec = eph.clone().into();
8387 assert_eq!(
8388 eph.horizon_requires_metric_axes(),
8389 lowered.classification.horizon_requires_metric_axes(),
8390 "None-classification parity drift",
8391 );
8392 // Authored classification.
8393 for populated in HorizonKind::ALL {
8394 let classification = Classification::gate_compute_with_axis(populated);
8395 let mut eph = empty_ephemeral();
8396 eph.classification = Some(classification);
8397 let lowered: ProcessSpec = eph.clone().into();
8398 assert_eq!(
8399 eph.horizon_requires_metric_axes(),
8400 lowered.classification.horizon_requires_metric_axes(),
8401 "authored horizon.kind={populated:?}: parity drift",
8402 );
8403 }
8404 }
8405
8406 // ── EphemeralSpec::calm_requires_coordination pins ───────────────
8407 //
8408 // Fail-before-pass-after granularity: `calm_requires_coordination`
8409 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
8410 // walking the "does this ephemeral spec require coordination?"
8411 // question went through
8412 // `.resolved_classification().calm.requires_coordination()` or
8413 // through the lowered `ProcessSpec`'s
8414 // `spec.classification.calm.requires_coordination()`. Post-lift the
8415 // THIRD derived-nullary-boolean peer on the ephemeral surface
8416 // (first on the calm axis, after the two horizon-axis peers)
8417 // routes through the SAME [`Self::resolved_classification`]
8418 // resolver + the sibling substrate primitive
8419 // [`crate::classification::Classification::calm_requires_coordination`],
8420 // so the two-surface parity contract holds by construction — a
8421 // regression on either side of the resolver fails at these pins
8422 // before landing at the operator-facing `coordination-required`
8423 // fixed tag in `tatara-check`.
8424
8425 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8426 /// [`Classification`] carries a specific [`CalmClassification`]
8427 /// variant answers [`Self::calm_requires_coordination`] matching
8428 /// the closed set's own
8429 /// [`CalmClassification::requires_coordination`] truth table.
8430 /// Sweep [`CalmClassification::ALL`] so a regression that (a)
8431 /// hard-coded the body to a fixed answer, (b) inverted the
8432 /// projection, or (c) crossed the wires with a sibling
8433 /// classification-axis probe fails HERE at the substrate primitive
8434 /// before drifting through the `coordination-required` fixed tag
8435 /// or the peer point surface.
8436 #[test]
8437 fn calm_requires_coordination_returns_calm_projection_per_kind() {
8438 for populated in CalmClassification::ALL {
8439 let mut classification = Classification::gate_compute();
8440 classification.calm = populated;
8441 let mut spec = empty_ephemeral();
8442 spec.classification = Some(classification);
8443 assert_eq!(
8444 spec.calm_requires_coordination(),
8445 populated.requires_coordination(),
8446 "authored calm={populated:?}: calm_requires_coordination() drift",
8447 );
8448 }
8449 }
8450
8451 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8452 /// with `classification: None` routes through the
8453 /// [`Self::resolved_classification`] resolver's substrate default
8454 /// [`Classification::gate_compute`], which carries
8455 /// [`CalmClassification::default = Monotone`], and
8456 /// [`CalmClassification::Monotone::requires_coordination`] projects
8457 /// `false`, so [`Self::calm_requires_coordination`] returns
8458 /// `false`. Pins the default-arm short-circuit through TWO layers
8459 /// of `Default` ([`Classification::gate_compute`] →
8460 /// [`CalmClassification::default`]) reaching this derived-nullary
8461 /// predicate — distinct from the sibling `horizon_*` absent-
8462 /// classification pins by ONE structural degree (those walk THREE
8463 /// layers of `Default` because horizon has a nested-struct wrapper;
8464 /// this walks TWO because `calm` is a direct scalar). A regression
8465 /// that dropped the resolver hop (silently answering `true` on an
8466 /// absent classification, as if the operator's absence meant
8467 /// "requires coordination") fails HERE at ONE narrow ephemeral-
8468 /// surface site.
8469 #[test]
8470 fn calm_requires_coordination_probes_false_on_absent_classification() {
8471 let spec = empty_ephemeral();
8472 assert!(spec.classification.is_none());
8473 assert!(
8474 !spec.calm_requires_coordination(),
8475 "absent classification (defaults to gate_compute, calm=Monotone → requires_coordination=false)",
8476 );
8477 }
8478
8479 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8480 /// identically through [`Self::calm_requires_coordination`] AND
8481 /// through
8482 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_requires_coordination()`
8483 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8484 /// classification, `Some(_)` classification on every
8485 /// [`CalmClassification::ALL`] variant) so a future regression on
8486 /// either side of the resolver fails HERE at the parity boundary.
8487 /// Byte-for-byte peer of the sibling
8488 /// `horizon_terminates_matches_point_peer_through_lowered_classification`
8489 /// on the calm axis.
8490 #[test]
8491 fn calm_requires_coordination_matches_point_peer_through_lowered_classification() {
8492 // Absent classification.
8493 let eph = empty_ephemeral();
8494 let lowered: ProcessSpec = eph.clone().into();
8495 assert_eq!(
8496 eph.calm_requires_coordination(),
8497 lowered.classification.calm_requires_coordination(),
8498 "None-classification parity drift",
8499 );
8500 // Authored classification.
8501 for populated in CalmClassification::ALL {
8502 let mut classification = Classification::gate_compute();
8503 classification.calm = populated;
8504 let mut eph = empty_ephemeral();
8505 eph.classification = Some(classification);
8506 let lowered: ProcessSpec = eph.clone().into();
8507 assert_eq!(
8508 eph.calm_requires_coordination(),
8509 lowered.classification.calm_requires_coordination(),
8510 "authored calm={populated:?}: parity drift",
8511 );
8512 }
8513 }
8514
8515 // ── EphemeralSpec::data_is_regulated pins ────────────────────────
8516 //
8517 // Fail-before-pass-after granularity: `data_is_regulated` did not
8518 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8519 // the "does this ephemeral spec carry regulated data?" question
8520 // went through
8521 // `.resolved_classification().data_classification.is_regulated()`
8522 // or through the lowered `ProcessSpec`'s
8523 // `spec.classification.data_classification.is_regulated()`. Post-
8524 // lift the FOURTH derived-nullary-boolean peer on the ephemeral
8525 // surface (first on the data axis, after two horizon-axis peers
8526 // and one calm-axis peer) routes through the SAME
8527 // [`Self::resolved_classification`] resolver + the sibling
8528 // substrate primitive
8529 // [`crate::classification::Classification::data_is_regulated`],
8530 // so the two-surface parity contract holds by construction — a
8531 // regression on either side of the resolver fails at these pins
8532 // before landing at the operator-facing `data-regulated` fixed
8533 // tag in `tatara-check`.
8534
8535 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8536 /// [`Classification`] carries a specific [`DataClassification`]
8537 /// variant answers [`Self::data_is_regulated`] matching the
8538 /// closed set's own [`DataClassification::is_regulated`] truth
8539 /// table. Sweep [`DataClassification::ALL`] so a regression that
8540 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8541 /// projection, or (c) crossed the wires with a sibling
8542 /// classification-axis probe fails HERE at the substrate
8543 /// primitive before drifting through the `data-regulated` fixed
8544 /// tag or the peer point surface.
8545 #[test]
8546 fn data_is_regulated_returns_data_classification_projection_per_kind() {
8547 for populated in DataClassification::ALL {
8548 let mut classification = Classification::gate_compute();
8549 classification.data_classification = populated;
8550 let mut spec = empty_ephemeral();
8551 spec.classification = Some(classification);
8552 assert_eq!(
8553 spec.data_is_regulated(),
8554 populated.is_regulated(),
8555 "authored data_classification={populated:?}: data_is_regulated() drift",
8556 );
8557 }
8558 }
8559
8560 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8561 /// with `classification: None` routes through the
8562 /// [`Self::resolved_classification`] resolver's substrate default
8563 /// [`Classification::gate_compute`], which carries
8564 /// [`DataClassification::default = Internal`], and
8565 /// [`DataClassification::Internal::is_regulated`] projects
8566 /// `false`, so [`Self::data_is_regulated`] returns `false`. Pins
8567 /// the default-arm short-circuit through TWO layers of `Default`
8568 /// ([`Classification::gate_compute`] →
8569 /// [`DataClassification::default`]) reaching this derived-nullary
8570 /// predicate — byte-for-byte structural peer of the sibling
8571 /// `calm_requires_coordination_probes_false_on_absent_classification`
8572 /// on the classification-data axis, distinct from the two
8573 /// `horizon_*` absent-classification pins by ONE structural
8574 /// degree (those walk THREE layers because horizon has a nested-
8575 /// struct wrapper; this walks TWO because `data_classification`
8576 /// is a direct scalar). A regression that dropped the resolver
8577 /// hop (silently answering `true` on an absent classification,
8578 /// as if the operator's absence meant "regulated data") fails
8579 /// HERE at ONE narrow ephemeral-surface site.
8580 #[test]
8581 fn data_is_regulated_probes_false_on_absent_classification() {
8582 let spec = empty_ephemeral();
8583 assert!(spec.classification.is_none());
8584 assert!(
8585 !spec.data_is_regulated(),
8586 "absent classification (defaults to gate_compute, data_classification=Internal → is_regulated=false)",
8587 );
8588 }
8589
8590 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8591 /// identically through [`Self::data_is_regulated`] AND through
8592 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_regulated()`
8593 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8594 /// classification, `Some(_)` classification on every
8595 /// [`DataClassification::ALL`] variant) so a future regression on
8596 /// either side of the resolver fails HERE at the parity boundary.
8597 /// Byte-for-byte peer of the sibling
8598 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
8599 /// on the data axis.
8600 #[test]
8601 fn data_is_regulated_matches_point_peer_through_lowered_classification() {
8602 // Absent classification.
8603 let eph = empty_ephemeral();
8604 let lowered: ProcessSpec = eph.clone().into();
8605 assert_eq!(
8606 eph.data_is_regulated(),
8607 lowered.classification.data_is_regulated(),
8608 "None-classification parity drift",
8609 );
8610 // Authored classification.
8611 for populated in DataClassification::ALL {
8612 let mut classification = Classification::gate_compute();
8613 classification.data_classification = populated;
8614 let mut eph = empty_ephemeral();
8615 eph.classification = Some(classification);
8616 let lowered: ProcessSpec = eph.clone().into();
8617 assert_eq!(
8618 eph.data_is_regulated(),
8619 lowered.classification.data_is_regulated(),
8620 "authored data_classification={populated:?}: parity drift",
8621 );
8622 }
8623 }
8624
8625 // ── EphemeralSpec::data_is_restricted pins ───────────────────────
8626 //
8627 // Fail-before-pass-after granularity: `data_is_restricted` did not
8628 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8629 // the "does this ephemeral spec require access controls?" question
8630 // went through
8631 // `.resolved_classification().data_classification.is_restricted()`
8632 // or through the lowered `ProcessSpec`'s
8633 // `spec.classification.data_classification.is_restricted()`. Post-
8634 // lift the FIFTH derived-nullary-boolean peer on the ephemeral
8635 // surface (second on the data axis, after
8636 // [`Self::data_is_regulated`] opened the axis) routes through the
8637 // SAME [`Self::resolved_classification`] resolver + the sibling
8638 // substrate primitive
8639 // [`crate::classification::Classification::data_is_restricted`],
8640 // so the two-surface parity contract holds by construction — a
8641 // regression on either side of the resolver fails at these pins
8642 // before landing at the operator-facing `data-restricted` fixed
8643 // tag in `tatara-check`. FIRST direct-scalar ephemeral-surface
8644 // peer whose absent-classification baseline projects to `true`
8645 // rather than `false`.
8646
8647 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8648 /// [`Classification`] carries a specific [`DataClassification`]
8649 /// variant answers [`Self::data_is_restricted`] matching the
8650 /// closed set's own [`DataClassification::is_restricted`] truth
8651 /// table. Sweep [`DataClassification::ALL`] so a regression that
8652 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8653 /// projection, or (c) crossed the wires with the sibling
8654 /// [`DataClassification::is_regulated`] projection fails HERE at
8655 /// the substrate primitive before drifting through the
8656 /// `data-restricted` fixed tag or the peer point surface.
8657 #[test]
8658 fn data_is_restricted_returns_data_classification_projection_per_kind() {
8659 for populated in DataClassification::ALL {
8660 let mut classification = Classification::gate_compute();
8661 classification.data_classification = populated;
8662 let mut spec = empty_ephemeral();
8663 spec.classification = Some(classification);
8664 assert_eq!(
8665 spec.data_is_restricted(),
8666 populated.is_restricted(),
8667 "authored data_classification={populated:?}: data_is_restricted() drift",
8668 );
8669 }
8670 }
8671
8672 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8673 /// with `classification: None` routes through the
8674 /// [`Self::resolved_classification`] resolver's substrate default
8675 /// [`Classification::gate_compute`], which carries
8676 /// [`DataClassification::default = Internal`], and
8677 /// [`DataClassification::Internal::is_restricted`] projects
8678 /// `true`, so [`Self::data_is_restricted`] returns `true`. Pins
8679 /// the default-arm short-circuit through TWO layers of `Default`
8680 /// ([`Classification::gate_compute`] →
8681 /// [`DataClassification::default`]) reaching this derived-nullary
8682 /// predicate. FIRST direct-scalar ephemeral-surface peer whose
8683 /// absent-classification baseline answers `true`, not `false`
8684 /// (the four earlier direct-scalar peers on this surface —
8685 /// `data_is_regulated`, `calm_requires_coordination`, plus the
8686 /// nested-struct `horizon_requires_metric_axes` — all project
8687 /// `false` on the same absent classification, and only the
8688 /// sibling nested-struct `horizon_terminates` projects `true`).
8689 /// A regression that dropped the resolver hop (silently answering
8690 /// `false` on an absent classification, as if the operator's
8691 /// absence meant "freely distributable"), or that inverted the
8692 /// projection while the closed-set primitive stayed intact,
8693 /// fails HERE at ONE narrow ephemeral-surface site.
8694 #[test]
8695 fn data_is_restricted_probes_true_on_absent_classification() {
8696 let spec = empty_ephemeral();
8697 assert!(spec.classification.is_none());
8698 assert!(
8699 spec.data_is_restricted(),
8700 "absent classification (defaults to gate_compute, data_classification=Internal → is_restricted=true)",
8701 );
8702 }
8703
8704 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8705 /// identically through [`Self::data_is_restricted`] AND through
8706 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_restricted()`
8707 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8708 /// classification, `Some(_)` classification on every
8709 /// [`DataClassification::ALL`] variant) so a future regression on
8710 /// either side of the resolver fails HERE at the parity boundary.
8711 /// Byte-for-byte peer of the sibling
8712 /// `data_is_regulated_matches_point_peer_through_lowered_classification`
8713 /// on the same classification-data axis, published a second time
8714 /// through the antisymmetric closed-set projection.
8715 #[test]
8716 fn data_is_restricted_matches_point_peer_through_lowered_classification() {
8717 // Absent classification.
8718 let eph = empty_ephemeral();
8719 let lowered: ProcessSpec = eph.clone().into();
8720 assert_eq!(
8721 eph.data_is_restricted(),
8722 lowered.classification.data_is_restricted(),
8723 "None-classification parity drift",
8724 );
8725 // Authored classification.
8726 for populated in DataClassification::ALL {
8727 let mut classification = Classification::gate_compute();
8728 classification.data_classification = populated;
8729 let mut eph = empty_ephemeral();
8730 eph.classification = Some(classification);
8731 let lowered: ProcessSpec = eph.clone().into();
8732 assert_eq!(
8733 eph.data_is_restricted(),
8734 lowered.classification.data_is_restricted(),
8735 "authored data_classification={populated:?}: parity drift",
8736 );
8737 }
8738 }
8739
8740 /// COMPOSED IMPLICATION pin — the ephemeral-surface counterpart of
8741 /// the closed-set-internal
8742 /// `data_classification_regulated_implies_restricted` and its
8743 /// parent-composed peer
8744 /// `classification_data_is_regulated_implies_data_is_restricted_over_all`:
8745 /// for every ([`EphemeralSpec`] with authored classification
8746 /// carrying every [`DataClassification`] variant, plus the
8747 /// absent-classification case), the resolver-hop probe pair
8748 /// satisfies `data_is_regulated() ⇒ data_is_restricted()`. Pins
8749 /// the implication contract at the ephemeral-surface site so a
8750 /// regression that (a) inverted the ephemeral
8751 /// [`Self::data_is_regulated`] resolver hop, (b) inverted the
8752 /// ephemeral [`Self::data_is_restricted`] resolver hop, or (c)
8753 /// crossed their wires while the underlying substrate primitives
8754 /// stayed intact fails HERE. FIRST ephemeral-surface corner-peer
8755 /// pair whose two projections carry a non-trivial closed-set-
8756 /// internal implication relationship.
8757 #[test]
8758 fn ephemeral_data_is_regulated_implies_data_is_restricted_over_all() {
8759 // Absent classification.
8760 let eph = empty_ephemeral();
8761 assert!(
8762 !eph.data_is_regulated() || eph.data_is_restricted(),
8763 "None-classification: data_is_regulated ⇒ data_is_restricted violated",
8764 );
8765 // Authored classification.
8766 for populated in DataClassification::ALL {
8767 let mut classification = Classification::gate_compute();
8768 classification.data_classification = populated;
8769 let mut eph = empty_ephemeral();
8770 eph.classification = Some(classification);
8771 assert!(
8772 !eph.data_is_regulated() || eph.data_is_restricted(),
8773 "authored data_classification={populated:?}: data_is_regulated ⇒ data_is_restricted violated",
8774 );
8775 }
8776 }
8777
8778 // ── EphemeralSpec::point_is_endomorphic pins ─────────────────────
8779 //
8780 // Fail-before-pass-after granularity: `point_is_endomorphic` did
8781 // not exist pre-lift on `impl EphemeralSpec` — every consumer
8782 // walking the "does this ephemeral spec's point-type project to
8783 // the 1→1 endomorphic bucket?" question went through
8784 // `.resolved_classification().point_type.is_endomorphic()` or the
8785 // lowered `ProcessSpec`'s
8786 // `spec.classification.point_type.is_endomorphic()`. Post-lift the
8787 // SIXTH derived-nullary-boolean peer on the ephemeral surface
8788 // (first on the `point_type` axis) routes through the SAME
8789 // [`Self::resolved_classification`] resolver + the sibling
8790 // substrate primitive
8791 // [`crate::classification::Classification::point_is_endomorphic`],
8792 // so the two-surface parity contract holds by construction — a
8793 // regression on either side of the resolver fails at these pins
8794 // before landing at the operator-facing `endomorphic-point` fixed
8795 // tag in `tatara-check`.
8796
8797 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8798 /// [`Classification`] carries a specific [`ConvergencePointType`]
8799 /// variant answers [`Self::point_is_endomorphic`] matching the
8800 /// closed set's own [`ConvergencePointType::is_endomorphic`] truth
8801 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
8802 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8803 /// projection, or (c) crossed the wires with the sibling
8804 /// [`ConvergencePointType::is_diffusive`] /
8805 /// [`ConvergencePointType::is_convergent`] projections fails
8806 /// HERE at the substrate primitive before drifting through the
8807 /// `endomorphic-point` fixed tag or the peer point surface.
8808 #[test]
8809 fn point_is_endomorphic_returns_point_type_projection_per_kind() {
8810 for populated in ConvergencePointType::ALL {
8811 let mut classification = Classification::gate_compute();
8812 classification.point_type = populated;
8813 let mut spec = empty_ephemeral();
8814 spec.classification = Some(classification);
8815 assert_eq!(
8816 spec.point_is_endomorphic(),
8817 populated.is_endomorphic(),
8818 "authored point_type={populated:?}: point_is_endomorphic() drift",
8819 );
8820 }
8821 }
8822
8823 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8824 /// with `classification: None` routes through the
8825 /// [`Self::resolved_classification`] resolver's substrate default
8826 /// [`Classification::gate_compute`], which carries
8827 /// [`ConvergencePointType::Gate`] (a convergent barrier, not an
8828 /// endomorphism), and
8829 /// [`ConvergencePointType::Gate::is_endomorphic`] projects `false`,
8830 /// so [`Self::point_is_endomorphic`] returns `false`. Pins the
8831 /// resolver's chosen-field baseline at ONE narrow site — a
8832 /// regression that dropped the resolver hop, or that promoted
8833 /// [`ConvergencePointType::Transform`] to the gate-compute
8834 /// baseline (silently retargeting every unadorned ephemeral
8835 /// spec's topology bucket), fails HERE at ONE narrow ephemeral-
8836 /// surface site. FIRST direct-scalar ephemeral-surface peer whose
8837 /// absent-classification baseline is a chosen-field answer on the
8838 /// resolver's [`Classification::gate_compute`] default rather
8839 /// than a substrate-`#[default]` short-circuit on the closed-set
8840 /// side ([`ConvergencePointType`] has no `impl Default`).
8841 #[test]
8842 fn point_is_endomorphic_probes_false_on_absent_classification() {
8843 let spec = empty_ephemeral();
8844 assert!(spec.classification.is_none());
8845 assert!(
8846 !spec.point_is_endomorphic(),
8847 "absent classification (defaults to gate_compute, point_type=Gate → is_endomorphic=false)",
8848 );
8849 }
8850
8851 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8852 /// identically through [`Self::point_is_endomorphic`] AND through
8853 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_endomorphic()`
8854 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8855 /// classification, `Some(_)` classification on every
8856 /// [`ConvergencePointType::ALL`] variant) so a future regression
8857 /// on either side of the resolver fails HERE at the parity
8858 /// boundary. Byte-for-byte peer of the sibling
8859 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
8860 /// on a DIFFERENT closed-set axis, published a first time through
8861 /// the `point_type` closed-set projection.
8862 #[test]
8863 fn point_is_endomorphic_matches_point_peer_through_lowered_classification() {
8864 // Absent classification.
8865 let eph = empty_ephemeral();
8866 let lowered: ProcessSpec = eph.clone().into();
8867 assert_eq!(
8868 eph.point_is_endomorphic(),
8869 lowered.classification.point_is_endomorphic(),
8870 "None-classification parity drift",
8871 );
8872 // Authored classification.
8873 for populated in ConvergencePointType::ALL {
8874 let mut classification = Classification::gate_compute();
8875 classification.point_type = populated;
8876 let mut eph = empty_ephemeral();
8877 eph.classification = Some(classification);
8878 let lowered: ProcessSpec = eph.clone().into();
8879 assert_eq!(
8880 eph.point_is_endomorphic(),
8881 lowered.classification.point_is_endomorphic(),
8882 "authored point_type={populated:?}: parity drift",
8883 );
8884 }
8885 }
8886
8887 // ── EphemeralSpec::point_is_diffusive pins ───────────────────────
8888 //
8889 // Fail-before-pass-after granularity: `point_is_diffusive` did not
8890 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8891 // the "does this ephemeral spec's point-type project to the 1→N
8892 // diffusive fan-out bucket?" question went through
8893 // `.resolved_classification().point_type.is_diffusive()` or the
8894 // lowered `ProcessSpec`'s
8895 // `spec.classification.point_type.is_diffusive()`. Post-lift the
8896 // SEVENTH derived-nullary-boolean peer on the ephemeral surface
8897 // (SECOND on the `point_type` axis) routes through the SAME
8898 // [`Self::resolved_classification`] resolver + the sibling
8899 // substrate primitive
8900 // [`crate::classification::Classification::point_is_diffusive`],
8901 // so the two-surface parity contract holds by construction.
8902
8903 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8904 /// [`Classification`] carries a specific [`ConvergencePointType`]
8905 /// variant answers [`Self::point_is_diffusive`] matching the
8906 /// closed set's own [`ConvergencePointType::is_diffusive`] truth
8907 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
8908 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8909 /// projection, or (c) crossed the wires with the sibling
8910 /// [`ConvergencePointType::is_endomorphic`] /
8911 /// [`ConvergencePointType::is_convergent`] projections fails HERE
8912 /// at the substrate primitive before drifting through the
8913 /// `diffusive-point` fixed tag or the peer point surface.
8914 #[test]
8915 fn point_is_diffusive_returns_point_type_projection_per_kind() {
8916 for populated in ConvergencePointType::ALL {
8917 let mut classification = Classification::gate_compute();
8918 classification.point_type = populated;
8919 let mut spec = empty_ephemeral();
8920 spec.classification = Some(classification);
8921 assert_eq!(
8922 spec.point_is_diffusive(),
8923 populated.is_diffusive(),
8924 "authored point_type={populated:?}: point_is_diffusive() drift",
8925 );
8926 }
8927 }
8928
8929 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8930 /// with `classification: None` routes through the
8931 /// [`Self::resolved_classification`] resolver's substrate default
8932 /// [`Classification::gate_compute`], which carries
8933 /// [`ConvergencePointType::Gate`] (a convergent barrier, not a
8934 /// diffusive fan-out), and
8935 /// [`ConvergencePointType::Gate::is_diffusive`] projects `false`,
8936 /// so [`Self::point_is_diffusive`] returns `false`. Pins the
8937 /// resolver's chosen-field baseline at ONE narrow site.
8938 #[test]
8939 fn point_is_diffusive_probes_false_on_absent_classification() {
8940 let spec = empty_ephemeral();
8941 assert!(spec.classification.is_none());
8942 assert!(
8943 !spec.point_is_diffusive(),
8944 "absent classification (defaults to gate_compute, point_type=Gate → is_diffusive=false)",
8945 );
8946 }
8947
8948 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8949 /// identically through [`Self::point_is_diffusive`] AND through
8950 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_diffusive()`
8951 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8952 /// classification, `Some(_)` classification on every
8953 /// [`ConvergencePointType::ALL`] variant) so a future regression
8954 /// on either side of the resolver fails HERE at the parity
8955 /// boundary. Byte-for-byte peer of
8956 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
8957 /// on the SAME closed-set axis via a sibling projection.
8958 #[test]
8959 fn point_is_diffusive_matches_point_peer_through_lowered_classification() {
8960 // Absent classification.
8961 let eph = empty_ephemeral();
8962 let lowered: ProcessSpec = eph.clone().into();
8963 assert_eq!(
8964 eph.point_is_diffusive(),
8965 lowered.classification.point_is_diffusive(),
8966 "None-classification parity drift",
8967 );
8968 // Authored classification.
8969 for populated in ConvergencePointType::ALL {
8970 let mut classification = Classification::gate_compute();
8971 classification.point_type = populated;
8972 let mut eph = empty_ephemeral();
8973 eph.classification = Some(classification);
8974 let lowered: ProcessSpec = eph.clone().into();
8975 assert_eq!(
8976 eph.point_is_diffusive(),
8977 lowered.classification.point_is_diffusive(),
8978 "authored point_type={populated:?}: parity drift",
8979 );
8980 }
8981 }
8982
8983 /// MUTEX pin — [`Self::point_is_endomorphic`] AND
8984 /// [`Self::point_is_diffusive`] are NEVER simultaneously true for
8985 /// ANY [`EphemeralSpec`] (authored or defaulted), since the
8986 /// underlying [`ConvergencePointType`] closed set carves its
8987 /// eight variants into THREE disjoint buckets. Sweep the absent-
8988 /// classification case + every [`ConvergencePointType::ALL`]
8989 /// variant so a regression that crossed the wires between the
8990 /// two ephemeral-surface corner peers (one probe silently
8991 /// composing the wrong closed-set arm at the resolver-hop layer)
8992 /// fails HERE rather than at every downstream consumer that
8993 /// trusts the two probes partition the resolver's output into
8994 /// disjoint buckets. FIRST ephemeral-surface corner-peer pair on
8995 /// the `point_type` axis whose two projections carry a non-
8996 /// trivial closed-set-internal MUTEX relationship (distinct from
8997 /// the sibling `data`-axis pair whose two projections carry a
8998 /// non-trivial IMPLICATION relationship, sealed by
8999 /// `ephemeral_data_is_regulated_implies_data_is_restricted_over_all`).
9000 #[test]
9001 fn ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all() {
9002 // Absent classification.
9003 let eph = empty_ephemeral();
9004 assert!(
9005 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
9006 "None-classification: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
9007 );
9008 // Authored classification.
9009 for populated in ConvergencePointType::ALL {
9010 let mut classification = Classification::gate_compute();
9011 classification.point_type = populated;
9012 let mut eph = empty_ephemeral();
9013 eph.classification = Some(classification);
9014 assert!(
9015 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
9016 "authored point_type={populated:?}: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
9017 );
9018 }
9019 }
9020
9021 // ── EphemeralSpec::point_is_convergent pins ──────────────────────
9022 //
9023 // Fail-before-pass-after granularity: `point_is_convergent` did
9024 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9025 // walking the "does this ephemeral spec's point-type project to
9026 // the N→1 convergent fan-in bucket?" question went through
9027 // `.resolved_classification().point_type.is_convergent()` or the
9028 // lowered `ProcessSpec`'s
9029 // `spec.classification.point_type.is_convergent()`. Post-lift the
9030 // EIGHTH derived-nullary-boolean peer on the ephemeral surface
9031 // (THIRD on the `point_type` axis) routes through the SAME
9032 // [`Self::resolved_classification`] resolver + the sibling
9033 // substrate primitive
9034 // [`crate::classification::Classification::point_is_convergent`],
9035 // so the two-surface parity contract holds by construction, AND
9036 // the THREE `point_type`-axis peers on this surface close into
9037 // the FULL three-way XOR partition contract.
9038
9039 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9040 /// [`Classification`] carries a specific [`ConvergencePointType`]
9041 /// variant answers [`Self::point_is_convergent`] matching the
9042 /// closed set's own [`ConvergencePointType::is_convergent`] truth
9043 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
9044 /// (a) hard-coded the body to a fixed answer, (b) inverted the
9045 /// projection, or (c) crossed the wires with the sibling
9046 /// [`ConvergencePointType::is_endomorphic`] /
9047 /// [`ConvergencePointType::is_diffusive`] projections fails HERE
9048 /// at the substrate primitive before drifting through the
9049 /// `convergent-point` fixed tag or the peer point surface.
9050 #[test]
9051 fn point_is_convergent_returns_point_type_projection_per_kind() {
9052 for populated in ConvergencePointType::ALL {
9053 let mut classification = Classification::gate_compute();
9054 classification.point_type = populated;
9055 let mut spec = empty_ephemeral();
9056 spec.classification = Some(classification);
9057 assert_eq!(
9058 spec.point_is_convergent(),
9059 populated.is_convergent(),
9060 "authored point_type={populated:?}: point_is_convergent() drift",
9061 );
9062 }
9063 }
9064
9065 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9066 /// with `classification: None` routes through the
9067 /// [`Self::resolved_classification`] resolver's substrate default
9068 /// [`Classification::gate_compute`], which carries
9069 /// [`ConvergencePointType::Gate`] (the canonical convergent
9070 /// barrier), and [`ConvergencePointType::Gate::is_convergent`]
9071 /// projects `true`, so [`Self::point_is_convergent`] returns
9072 /// `true`. Pins the resolver's chosen-field baseline at ONE
9073 /// narrow site — FIRST direct-scalar ephemeral-surface peer whose
9074 /// absent-classification baseline projects `true` through the
9075 /// resolver's chosen-field answer, mirror-inverted from the two
9076 /// sibling `point_is_endomorphic` / `point_is_diffusive`
9077 /// ephemeral-surface baselines which both project `false`.
9078 #[test]
9079 fn point_is_convergent_probes_true_on_absent_classification() {
9080 let spec = empty_ephemeral();
9081 assert!(spec.classification.is_none());
9082 assert!(
9083 spec.point_is_convergent(),
9084 "absent classification (defaults to gate_compute, point_type=Gate → is_convergent=true)",
9085 );
9086 }
9087
9088 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9089 /// identically through [`Self::point_is_convergent`] AND through
9090 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_convergent()`
9091 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9092 /// classification, `Some(_)` classification on every
9093 /// [`ConvergencePointType::ALL`] variant) so a future regression
9094 /// on either side of the resolver fails HERE at the parity
9095 /// boundary. Byte-for-byte peer of
9096 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
9097 /// and
9098 /// `point_is_diffusive_matches_point_peer_through_lowered_classification`
9099 /// on the SAME closed-set axis via a sibling projection.
9100 #[test]
9101 fn point_is_convergent_matches_point_peer_through_lowered_classification() {
9102 // Absent classification.
9103 let eph = empty_ephemeral();
9104 let lowered: ProcessSpec = eph.clone().into();
9105 assert_eq!(
9106 eph.point_is_convergent(),
9107 lowered.classification.point_is_convergent(),
9108 "None-classification parity drift",
9109 );
9110 // Authored classification.
9111 for populated in ConvergencePointType::ALL {
9112 let mut classification = Classification::gate_compute();
9113 classification.point_type = populated;
9114 let mut eph = empty_ephemeral();
9115 eph.classification = Some(classification);
9116 let lowered: ProcessSpec = eph.clone().into();
9117 assert_eq!(
9118 eph.point_is_convergent(),
9119 lowered.classification.point_is_convergent(),
9120 "authored point_type={populated:?}: parity drift",
9121 );
9122 }
9123 }
9124
9125 /// THREE-WAY XOR PARTITION pin — for the absent-classification
9126 /// baseline AND every [`ConvergencePointType::ALL`] variant,
9127 /// EXACTLY ONE of [`Self::point_is_endomorphic`],
9128 /// [`Self::point_is_diffusive`], and [`Self::point_is_convergent`]
9129 /// returns `true`. Closes the mutex pair
9130 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`
9131 /// into the FULL ternary XOR partition contract on the ephemeral
9132 /// surface — the resolver-hop peer of the parent-composed
9133 /// `classification_point_type_probes_form_three_way_xor_partition_over_all`
9134 /// test. Guarantees the absent-classification case lands in the
9135 /// convergent bucket (`gate_compute` → Gate → is_convergent =
9136 /// true), so every unadorned `(defephemeral …)` audits under a
9137 /// definite non-empty topology bucket.
9138 #[test]
9139 fn ephemeral_point_type_probes_form_three_way_xor_partition_over_all() {
9140 // Absent classification.
9141 let eph = empty_ephemeral();
9142 let buckets = [
9143 eph.point_is_endomorphic(),
9144 eph.point_is_diffusive(),
9145 eph.point_is_convergent(),
9146 ];
9147 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9148 assert_eq!(
9149 hits, 1,
9150 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9151 );
9152 // Authored classification.
9153 for populated in ConvergencePointType::ALL {
9154 let mut classification = Classification::gate_compute();
9155 classification.point_type = populated;
9156 let mut eph = empty_ephemeral();
9157 eph.classification = Some(classification);
9158 let buckets = [
9159 eph.point_is_endomorphic(),
9160 eph.point_is_diffusive(),
9161 eph.point_is_convergent(),
9162 ];
9163 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9164 assert_eq!(
9165 hits, 1,
9166 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9167 );
9168 }
9169 }
9170
9171 // ── EphemeralSpec::substrate_is_resource pins ────────────────────
9172 //
9173 // Fail-before-pass-after granularity: `substrate_is_resource` did
9174 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9175 // walking the "does this ephemeral spec's substrate project to
9176 // the resource plane?" question went through
9177 // `.resolved_classification().substrate.is_resource()` or the
9178 // lowered `ProcessSpec`'s
9179 // `spec.classification.substrate.is_resource()`. Post-lift the
9180 // NINTH derived-nullary-boolean peer on the ephemeral surface
9181 // (FIRST on the `substrate` axis) routes through the SAME
9182 // [`Self::resolved_classification`] resolver + the sibling
9183 // substrate primitive
9184 // [`crate::classification::Classification::substrate_is_resource`],
9185 // so the two-surface parity contract holds by construction.
9186
9187 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9188 /// [`Classification`] carries a specific
9189 /// [`crate::classification::SubstrateType`] variant answers
9190 /// [`Self::substrate_is_resource`] matching the closed set's own
9191 /// [`crate::classification::SubstrateType::is_resource`] truth
9192 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
9193 /// so a regression that (a) hard-coded the body to a fixed
9194 /// answer, (b) inverted the projection, or (c) crossed the wires
9195 /// with the sibling
9196 /// [`crate::classification::SubstrateType::is_policy`] /
9197 /// [`crate::classification::SubstrateType::is_telemetry`]
9198 /// projections fails HERE at the substrate primitive before
9199 /// drifting through the `resource-substrate` fixed tag or the
9200 /// peer point surface.
9201 #[test]
9202 fn substrate_is_resource_returns_substrate_projection_per_kind() {
9203 for populated in SubstrateType::ALL {
9204 let mut classification = Classification::gate_compute();
9205 classification.substrate = populated;
9206 let mut spec = empty_ephemeral();
9207 spec.classification = Some(classification);
9208 assert_eq!(
9209 spec.substrate_is_resource(),
9210 populated.is_resource(),
9211 "authored substrate={populated:?}: substrate_is_resource() drift",
9212 );
9213 }
9214 }
9215
9216 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9217 /// with `classification: None` routes through the
9218 /// [`Self::resolved_classification`] resolver's substrate default
9219 /// [`Classification::gate_compute`], which carries
9220 /// [`crate::classification::SubstrateType::Compute`] (the
9221 /// canonical resource-plane substrate), and
9222 /// [`crate::classification::SubstrateType::Compute::is_resource`]
9223 /// projects `true`, so [`Self::substrate_is_resource`] returns
9224 /// `true`. Pins the resolver's chosen-field baseline at ONE
9225 /// narrow site — mirror-aligned with the sibling
9226 /// `point_is_convergent_probes_true_on_absent_classification`
9227 /// baseline (both projections on `gate_compute` chosen fields
9228 /// answer `true`).
9229 #[test]
9230 fn substrate_is_resource_probes_true_on_absent_classification() {
9231 let spec = empty_ephemeral();
9232 assert!(spec.classification.is_none());
9233 assert!(
9234 spec.substrate_is_resource(),
9235 "absent classification (defaults to gate_compute, substrate=Compute → is_resource=true)",
9236 );
9237 }
9238
9239 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9240 /// identically through [`Self::substrate_is_resource`] AND through
9241 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_resource()`
9242 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9243 /// classification, `Some(_)` classification on every
9244 /// [`crate::classification::SubstrateType::ALL`] variant) so a
9245 /// future regression on either side of the resolver fails HERE
9246 /// at the parity boundary. Byte-for-byte peer of
9247 /// `point_is_convergent_matches_point_peer_through_lowered_classification`
9248 /// on a sibling classification axis.
9249 #[test]
9250 fn substrate_is_resource_matches_point_peer_through_lowered_classification() {
9251 // Absent classification.
9252 let eph = empty_ephemeral();
9253 let lowered: ProcessSpec = eph.clone().into();
9254 assert_eq!(
9255 eph.substrate_is_resource(),
9256 lowered.classification.substrate_is_resource(),
9257 "None-classification parity drift",
9258 );
9259 // Authored classification.
9260 for populated in SubstrateType::ALL {
9261 let mut classification = Classification::gate_compute();
9262 classification.substrate = populated;
9263 let mut eph = empty_ephemeral();
9264 eph.classification = Some(classification);
9265 let lowered: ProcessSpec = eph.clone().into();
9266 assert_eq!(
9267 eph.substrate_is_resource(),
9268 lowered.classification.substrate_is_resource(),
9269 "authored substrate={populated:?}: parity drift",
9270 );
9271 }
9272 }
9273
9274 // ── EphemeralSpec::substrate_is_policy pins ──────────────────────
9275 //
9276 // Fail-before-pass-after granularity: `substrate_is_policy` did
9277 // not exist pre-lift on `impl EphemeralSpec` — every consumer
9278 // walking the "does this ephemeral spec's substrate project to
9279 // the policy plane?" question went through
9280 // `.resolved_classification().substrate.is_policy()` or the
9281 // lowered `ProcessSpec`'s
9282 // `spec.classification.substrate.is_policy()`. Post-lift the
9283 // TENTH derived-nullary-boolean peer on the ephemeral surface
9284 // (SECOND on the `substrate` axis) routes through the SAME
9285 // [`Self::resolved_classification`] resolver + the sibling
9286 // substrate primitive
9287 // [`crate::classification::Classification::substrate_is_policy`],
9288 // so the two-surface parity contract holds by construction, AND
9289 // the two `substrate`-axis peers on this surface open the
9290 // MUTEX pair on the axis via
9291 // `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`.
9292
9293 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9294 /// [`Classification`] carries a specific
9295 /// [`crate::classification::SubstrateType`] variant answers
9296 /// [`Self::substrate_is_policy`] matching the closed set's own
9297 /// [`crate::classification::SubstrateType::is_policy`] truth
9298 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
9299 /// so a regression that (a) hard-coded the body to a fixed
9300 /// answer, (b) inverted the projection, or (c) crossed the wires
9301 /// with the sibling
9302 /// [`crate::classification::SubstrateType::is_resource`] /
9303 /// [`crate::classification::SubstrateType::is_telemetry`]
9304 /// projections fails HERE at the substrate primitive before
9305 /// drifting through the `policy-substrate` fixed tag or the
9306 /// peer point surface.
9307 #[test]
9308 fn substrate_is_policy_returns_substrate_projection_per_kind() {
9309 for populated in SubstrateType::ALL {
9310 let mut classification = Classification::gate_compute();
9311 classification.substrate = populated;
9312 let mut spec = empty_ephemeral();
9313 spec.classification = Some(classification);
9314 assert_eq!(
9315 spec.substrate_is_policy(),
9316 populated.is_policy(),
9317 "authored substrate={populated:?}: substrate_is_policy() drift",
9318 );
9319 }
9320 }
9321
9322 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9323 /// with `classification: None` routes through the
9324 /// [`Self::resolved_classification`] resolver's substrate default
9325 /// [`Classification::gate_compute`], which carries
9326 /// [`crate::classification::SubstrateType::Compute`] (the
9327 /// canonical resource-plane substrate, NOT a policy plane), and
9328 /// [`crate::classification::SubstrateType::Compute::is_policy`]
9329 /// projects `false`, so [`Self::substrate_is_policy`] returns
9330 /// `false`. Pins the resolver's chosen-field baseline at ONE
9331 /// narrow site — mirror-inverted from the sibling
9332 /// `substrate_is_resource_probes_true_on_absent_classification`
9333 /// (both projections on `gate_compute`'s chosen `substrate`
9334 /// field, but the sibling answers `true` where this one
9335 /// answers `false` — the closed set's disjoint plane partition
9336 /// forbids both being true).
9337 #[test]
9338 fn substrate_is_policy_probes_false_on_absent_classification() {
9339 let spec = empty_ephemeral();
9340 assert!(spec.classification.is_none());
9341 assert!(
9342 !spec.substrate_is_policy(),
9343 "absent classification (defaults to gate_compute, substrate=Compute → is_policy=false)",
9344 );
9345 }
9346
9347 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9348 /// identically through [`Self::substrate_is_policy`] AND through
9349 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_policy()`
9350 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9351 /// classification, `Some(_)` classification on every
9352 /// [`crate::classification::SubstrateType::ALL`] variant) so a
9353 /// future regression on either side of the resolver fails HERE
9354 /// at the parity boundary. Byte-for-byte peer of
9355 /// `substrate_is_resource_matches_point_peer_through_lowered_classification`
9356 /// on the SAME closed-set axis via a sibling projection.
9357 #[test]
9358 fn substrate_is_policy_matches_point_peer_through_lowered_classification() {
9359 // Absent classification.
9360 let eph = empty_ephemeral();
9361 let lowered: ProcessSpec = eph.clone().into();
9362 assert_eq!(
9363 eph.substrate_is_policy(),
9364 lowered.classification.substrate_is_policy(),
9365 "None-classification parity drift",
9366 );
9367 // Authored classification.
9368 for populated in SubstrateType::ALL {
9369 let mut classification = Classification::gate_compute();
9370 classification.substrate = populated;
9371 let mut eph = empty_ephemeral();
9372 eph.classification = Some(classification);
9373 let lowered: ProcessSpec = eph.clone().into();
9374 assert_eq!(
9375 eph.substrate_is_policy(),
9376 lowered.classification.substrate_is_policy(),
9377 "authored substrate={populated:?}: parity drift",
9378 );
9379 }
9380 }
9381
9382 /// MUTEX pin — [`Self::substrate_is_resource`] AND
9383 /// [`Self::substrate_is_policy`] are NEVER simultaneously true
9384 /// for ANY [`EphemeralSpec`] (authored or defaulted), since the
9385 /// underlying [`crate::classification::SubstrateType`] closed set
9386 /// carves its eight variants into THREE disjoint buckets. Sweep
9387 /// the absent-classification case + every
9388 /// [`crate::classification::SubstrateType::ALL`] variant so a
9389 /// regression that crossed the wires between the two ephemeral-
9390 /// surface corner peers (one probe silently composing the wrong
9391 /// closed-set arm at the resolver-hop layer) fails HERE rather
9392 /// than at every downstream consumer that trusts the two probes
9393 /// partition the resolver's output into disjoint buckets.
9394 /// FIRST ephemeral-surface `substrate`-axis corner-peer pair
9395 /// carrying a non-trivial MUTEX relationship — structural twin
9396 /// of the sibling `point_type`-axis MUTEX pair sealed on this
9397 /// surface by
9398 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
9399 #[test]
9400 fn ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all() {
9401 // Absent classification.
9402 let eph = empty_ephemeral();
9403 assert!(
9404 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
9405 "None-classification: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
9406 );
9407 // Authored classification.
9408 for populated in SubstrateType::ALL {
9409 let mut classification = Classification::gate_compute();
9410 classification.substrate = populated;
9411 let mut eph = empty_ephemeral();
9412 eph.classification = Some(classification);
9413 assert!(
9414 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
9415 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
9416 );
9417 }
9418 }
9419
9420 // ── EphemeralSpec::substrate_is_telemetry pins ───────────────────
9421 //
9422 // Fail-before-pass-after granularity: `substrate_is_telemetry`
9423 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9424 // walking the "does this ephemeral spec's substrate project to
9425 // the telemetry plane?" question went through
9426 // `.resolved_classification().substrate.is_telemetry()` or the
9427 // lowered `ProcessSpec`'s
9428 // `spec.classification.substrate.is_telemetry()`. Post-lift the
9429 // ELEVENTH derived-nullary-boolean peer on the ephemeral surface
9430 // (THIRD on the `substrate` axis) routes through the SAME
9431 // [`Self::resolved_classification`] resolver + the sibling
9432 // substrate primitive
9433 // [`crate::classification::Classification::substrate_is_telemetry`],
9434 // so the two-surface parity contract holds by construction, AND
9435 // the three `substrate`-axis peers on this surface CLOSE the
9436 // axis into the FULL three-way XOR partition contract via
9437 // `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
9438
9439 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9440 /// [`Classification`] carries a specific
9441 /// [`crate::classification::SubstrateType`] variant answers
9442 /// [`Self::substrate_is_telemetry`] matching the closed set's own
9443 /// [`crate::classification::SubstrateType::is_telemetry`] truth
9444 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
9445 /// so a regression that (a) hard-coded the body to a fixed
9446 /// answer, (b) inverted the projection, or (c) crossed the wires
9447 /// with the sibling
9448 /// [`crate::classification::SubstrateType::is_resource`] /
9449 /// [`crate::classification::SubstrateType::is_policy`]
9450 /// projections fails HERE at the substrate primitive before
9451 /// drifting through the `telemetry-substrate` fixed tag or the
9452 /// peer point surface.
9453 #[test]
9454 fn substrate_is_telemetry_returns_substrate_projection_per_kind() {
9455 for populated in SubstrateType::ALL {
9456 let mut classification = Classification::gate_compute();
9457 classification.substrate = populated;
9458 let mut spec = empty_ephemeral();
9459 spec.classification = Some(classification);
9460 assert_eq!(
9461 spec.substrate_is_telemetry(),
9462 populated.is_telemetry(),
9463 "authored substrate={populated:?}: substrate_is_telemetry() drift",
9464 );
9465 }
9466 }
9467
9468 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9469 /// with `classification: None` routes through the
9470 /// [`Self::resolved_classification`] resolver's substrate default
9471 /// [`Classification::gate_compute`], which carries
9472 /// [`crate::classification::SubstrateType::Compute`] (the
9473 /// canonical resource-plane substrate, NOT a telemetry plane),
9474 /// and
9475 /// [`crate::classification::SubstrateType::Compute::is_telemetry`]
9476 /// projects `false`, so [`Self::substrate_is_telemetry`] returns
9477 /// `false`. Pins the resolver's chosen-field baseline at ONE
9478 /// narrow site — aligned with the sibling
9479 /// `substrate_is_policy_probes_false_on_absent_classification`
9480 /// (both projections on `gate_compute`'s chosen `substrate`
9481 /// field project `false` since `Compute` lives in the resource
9482 /// plane), mirror-inverted from
9483 /// `substrate_is_resource_probes_true_on_absent_classification`.
9484 #[test]
9485 fn substrate_is_telemetry_probes_false_on_absent_classification() {
9486 let spec = empty_ephemeral();
9487 assert!(spec.classification.is_none());
9488 assert!(
9489 !spec.substrate_is_telemetry(),
9490 "absent classification (defaults to gate_compute, substrate=Compute → is_telemetry=false)",
9491 );
9492 }
9493
9494 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9495 /// identically through [`Self::substrate_is_telemetry`] AND
9496 /// through
9497 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_telemetry()`
9498 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9499 /// classification, `Some(_)` classification on every
9500 /// [`crate::classification::SubstrateType::ALL`] variant) so a
9501 /// future regression on either side of the resolver fails HERE
9502 /// at the parity boundary. Byte-for-byte peer of
9503 /// `substrate_is_policy_matches_point_peer_through_lowered_classification`
9504 /// on the SAME closed-set axis via a sibling projection.
9505 #[test]
9506 fn substrate_is_telemetry_matches_point_peer_through_lowered_classification() {
9507 // Absent classification.
9508 let eph = empty_ephemeral();
9509 let lowered: ProcessSpec = eph.clone().into();
9510 assert_eq!(
9511 eph.substrate_is_telemetry(),
9512 lowered.classification.substrate_is_telemetry(),
9513 "None-classification parity drift",
9514 );
9515 // Authored classification.
9516 for populated in SubstrateType::ALL {
9517 let mut classification = Classification::gate_compute();
9518 classification.substrate = populated;
9519 let mut eph = empty_ephemeral();
9520 eph.classification = Some(classification);
9521 let lowered: ProcessSpec = eph.clone().into();
9522 assert_eq!(
9523 eph.substrate_is_telemetry(),
9524 lowered.classification.substrate_is_telemetry(),
9525 "authored substrate={populated:?}: parity drift",
9526 );
9527 }
9528 }
9529
9530 /// MUTEX pin — [`Self::substrate_is_resource`] AND
9531 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
9532 /// for ANY [`EphemeralSpec`] (authored or defaulted). Second
9533 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
9534 /// peer of
9535 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9536 /// on a sibling closed-set projection.
9537 #[test]
9538 fn ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all() {
9539 // Absent classification.
9540 let eph = empty_ephemeral();
9541 assert!(
9542 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
9543 "None-classification: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
9544 );
9545 // Authored classification.
9546 for populated in SubstrateType::ALL {
9547 let mut classification = Classification::gate_compute();
9548 classification.substrate = populated;
9549 let mut eph = empty_ephemeral();
9550 eph.classification = Some(classification);
9551 assert!(
9552 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
9553 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
9554 );
9555 }
9556 }
9557
9558 /// MUTEX pin — [`Self::substrate_is_policy`] AND
9559 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
9560 /// for ANY [`EphemeralSpec`] (authored or defaulted). Third
9561 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
9562 /// completes the three pairwise MUTEX relations alongside
9563 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9564 /// and
9565 /// `ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all`.
9566 #[test]
9567 fn ephemeral_substrate_is_policy_and_substrate_is_telemetry_are_mutex_over_all() {
9568 // Absent classification.
9569 let eph = empty_ephemeral();
9570 assert!(
9571 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
9572 "None-classification: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
9573 );
9574 // Authored classification.
9575 for populated in SubstrateType::ALL {
9576 let mut classification = Classification::gate_compute();
9577 classification.substrate = populated;
9578 let mut eph = empty_ephemeral();
9579 eph.classification = Some(classification);
9580 assert!(
9581 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
9582 "authored substrate={populated:?}: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
9583 );
9584 }
9585 }
9586
9587 /// THREE-WAY XOR PARTITION pin — for the absent-classification
9588 /// baseline AND every [`crate::classification::SubstrateType::ALL`]
9589 /// variant, EXACTLY ONE of [`Self::substrate_is_resource`],
9590 /// [`Self::substrate_is_policy`], and
9591 /// [`Self::substrate_is_telemetry`] returns `true`. CLOSES the
9592 /// three pairwise MUTEX pins on the substrate axis
9593 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`,
9594 /// `substrate_is_resource ⇒ ¬substrate_is_telemetry`,
9595 /// `substrate_is_policy ⇒ ¬substrate_is_telemetry`) into the
9596 /// FULL ternary XOR partition contract on the ephemeral surface
9597 /// — the resolver-hop peer of the parent-composed
9598 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`
9599 /// test. Structural twin of the sibling `point_type`-axis
9600 /// ternary lift sealed on this surface by
9601 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
9602 /// Guarantees the absent-classification case lands in the
9603 /// resource bucket (`gate_compute` → Compute → is_resource =
9604 /// true), so every unadorned `(defephemeral …)` audits under a
9605 /// definite non-empty plane bucket.
9606 #[test]
9607 fn ephemeral_substrate_probes_form_three_way_xor_partition_over_all() {
9608 // Absent classification.
9609 let eph = empty_ephemeral();
9610 let buckets = [
9611 eph.substrate_is_resource(),
9612 eph.substrate_is_policy(),
9613 eph.substrate_is_telemetry(),
9614 ];
9615 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9616 assert_eq!(
9617 hits, 1,
9618 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition 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 let buckets = [
9627 eph.substrate_is_resource(),
9628 eph.substrate_is_policy(),
9629 eph.substrate_is_telemetry(),
9630 ];
9631 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9632 assert_eq!(
9633 hits, 1,
9634 "authored substrate={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9635 );
9636 }
9637 }
9638
9639 // ── EphemeralSpec::calm_is_monotone pins ─────────────────────────
9640 //
9641 // Fail-before-pass-after granularity: `calm_is_monotone` did not
9642 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9643 // the "can this ephemeral spec participate in gossip-only writes?"
9644 // question went through the antisymmetric
9645 // `!self.calm_requires_coordination()` or through
9646 // `.resolved_classification().calm.is_monotone()`. Post-lift the
9647 // TWELFTH derived-nullary-boolean peer on the ephemeral surface
9648 // (SECOND on the calm axis, closing that axis into a binary XOR
9649 // partition on this surface) routes through the SAME
9650 // [`Self::resolved_classification`] resolver + the sibling
9651 // substrate primitive
9652 // [`crate::classification::Classification::calm_is_monotone`], so
9653 // the two-surface parity contract holds by construction, AND the
9654 // two calm-axis peers on this surface CLOSE the axis into the
9655 // FULL binary XOR partition contract via
9656 // `ephemeral_calm_probes_form_binary_xor_partition_over_all`.
9657
9658 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9659 /// [`Classification`] carries a specific
9660 /// [`crate::classification::CalmClassification`] variant answers
9661 /// [`Self::calm_is_monotone`] matching the closed set's own
9662 /// [`crate::classification::CalmClassification::is_monotone`]
9663 /// truth table. Sweep
9664 /// [`crate::classification::CalmClassification::ALL`] so a
9665 /// regression that (a) hard-coded the body to a fixed answer,
9666 /// (b) inverted the projection, or (c) crossed the wires with
9667 /// the sibling
9668 /// [`crate::classification::CalmClassification::requires_coordination`]
9669 /// projection fails HERE at the substrate primitive before
9670 /// drifting through the `monotone-calm` fixed tag or the peer
9671 /// point surface.
9672 #[test]
9673 fn calm_is_monotone_returns_calm_projection_per_kind() {
9674 for populated in CalmClassification::ALL {
9675 let mut classification = Classification::gate_compute();
9676 classification.calm = populated;
9677 let mut spec = empty_ephemeral();
9678 spec.classification = Some(classification);
9679 assert_eq!(
9680 spec.calm_is_monotone(),
9681 populated.is_monotone(),
9682 "authored calm={populated:?}: calm_is_monotone() drift",
9683 );
9684 }
9685 }
9686
9687 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9688 /// with `classification: None` routes through the
9689 /// [`Self::resolved_classification`] resolver's substrate default
9690 /// [`Classification::gate_compute`], which carries
9691 /// [`crate::classification::CalmClassification::default = Monotone`]
9692 /// via `#[default]`, and
9693 /// [`crate::classification::CalmClassification::Monotone::is_monotone`]
9694 /// projects `true`, so [`Self::calm_is_monotone`] returns
9695 /// `true`. Pins the resolver's default-arm short-circuit through
9696 /// TWO layers of `Default` ([`Classification::gate_compute`] →
9697 /// [`crate::classification::CalmClassification::default`])
9698 /// reaching this derived-nullary predicate. Mirror-inverted from
9699 /// the sibling
9700 /// `calm_requires_coordination_probes_false_on_absent_classification`
9701 /// (both walk the SAME defaulted `calm` field, so
9702 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
9703 /// closed set's disjoint XOR partition). Guarantees every
9704 /// unadorned `(defephemeral …)` reads as gossip-eligible under
9705 /// the positive CALM framing.
9706 #[test]
9707 fn calm_is_monotone_probes_true_on_absent_classification() {
9708 let spec = empty_ephemeral();
9709 assert!(spec.classification.is_none());
9710 assert!(
9711 spec.calm_is_monotone(),
9712 "absent classification (defaults to gate_compute, calm=Monotone → is_monotone=true)",
9713 );
9714 }
9715
9716 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9717 /// identically through [`Self::calm_is_monotone`] AND through
9718 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_is_monotone()`
9719 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9720 /// classification, `Some(_)` classification on every
9721 /// [`crate::classification::CalmClassification::ALL`] variant) so
9722 /// a future regression on either side of the resolver fails HERE
9723 /// at the parity boundary. Byte-for-byte peer of
9724 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
9725 /// on the SAME closed-set axis via the antisymmetric projection.
9726 #[test]
9727 fn calm_is_monotone_matches_point_peer_through_lowered_classification() {
9728 // Absent classification.
9729 let eph = empty_ephemeral();
9730 let lowered: ProcessSpec = eph.clone().into();
9731 assert_eq!(
9732 eph.calm_is_monotone(),
9733 lowered.classification.calm_is_monotone(),
9734 "None-classification parity drift",
9735 );
9736 // Authored classification.
9737 for populated in CalmClassification::ALL {
9738 let mut classification = Classification::gate_compute();
9739 classification.calm = populated;
9740 let mut eph = empty_ephemeral();
9741 eph.classification = Some(classification);
9742 let lowered: ProcessSpec = eph.clone().into();
9743 assert_eq!(
9744 eph.calm_is_monotone(),
9745 lowered.classification.calm_is_monotone(),
9746 "authored calm={populated:?}: parity drift",
9747 );
9748 }
9749 }
9750
9751 /// MUTEX pin — [`Self::calm_requires_coordination`] AND
9752 /// [`Self::calm_is_monotone`] are NEVER simultaneously true for
9753 /// ANY [`EphemeralSpec`] (authored or defaulted). FIRST
9754 /// ephemeral-surface `calm`-axis corner-peer MUTEX pin — the
9755 /// calm axis's counterpart to the sibling substrate-axis
9756 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9757 /// on a binary (rather than ternary) closed set.
9758 #[test]
9759 fn ephemeral_calm_requires_coordination_and_calm_is_monotone_are_mutex_over_all() {
9760 // Absent classification.
9761 let eph = empty_ephemeral();
9762 assert!(
9763 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
9764 "None-classification: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
9765 );
9766 // Authored classification.
9767 for populated in CalmClassification::ALL {
9768 let mut classification = Classification::gate_compute();
9769 classification.calm = populated;
9770 let mut eph = empty_ephemeral();
9771 eph.classification = Some(classification);
9772 assert!(
9773 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
9774 "authored calm={populated:?}: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
9775 );
9776 }
9777 }
9778
9779 /// BINARY XOR PARTITION pin — for the absent-classification
9780 /// baseline AND every
9781 /// [`crate::classification::CalmClassification::ALL`] variant,
9782 /// EXACTLY ONE of [`Self::calm_is_monotone`] and
9783 /// [`Self::calm_requires_coordination`] returns `true`. CLOSES
9784 /// the calm-axis MUTEX pin
9785 /// (`calm_requires_coordination ⇒ ¬calm_is_monotone`) into the
9786 /// FULL binary XOR partition contract on the ephemeral surface
9787 /// — the resolver-hop peer of the parent-composed
9788 /// `classification_calm_probes_form_binary_xor_partition_over_all`
9789 /// test. Binary counterpart of the ternary XOR partitions sealed
9790 /// on the sibling `point_type` and `substrate` axes by
9791 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
9792 /// and
9793 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
9794 /// Guarantees the absent-classification case lands in the
9795 /// monotone bucket (`gate_compute` → CalmClassification::Monotone
9796 /// → is_monotone = true), so every unadorned `(defephemeral …)`
9797 /// audits under a definite non-empty CALM bucket.
9798 #[test]
9799 fn ephemeral_calm_probes_form_binary_xor_partition_over_all() {
9800 // Absent classification.
9801 let eph = empty_ephemeral();
9802 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
9803 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9804 assert_eq!(
9805 hits, 1,
9806 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9807 );
9808 // Authored classification.
9809 for populated in CalmClassification::ALL {
9810 let mut classification = Classification::gate_compute();
9811 classification.calm = populated;
9812 let mut eph = empty_ephemeral();
9813 eph.classification = Some(classification);
9814 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
9815 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9816 assert_eq!(
9817 hits, 1,
9818 "authored calm={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9819 );
9820 }
9821 }
9822
9823 // ── EphemeralSpec::data_is_public pins ───────────────────────────
9824 //
9825 // Fail-before-pass-after granularity: `data_is_public` did not
9826 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9827 // the "is this ephemeral spec's dataset publicly distributable?"
9828 // question went through the antisymmetric
9829 // `!self.data_is_restricted()` or through
9830 // `.resolved_classification().data_classification.is_public()`.
9831 // Post-lift the THIRTEENTH derived-nullary-boolean peer on the
9832 // ephemeral surface (THIRD on the data axis, closing that axis
9833 // into a binary XOR partition on this surface) routes through the
9834 // SAME [`Self::resolved_classification`] resolver + the sibling
9835 // substrate primitive
9836 // [`crate::classification::Classification::data_is_public`], so
9837 // the two-surface parity contract holds by construction, AND the
9838 // two-way public/restricted split on this surface CLOSES the
9839 // data axis into the FULL binary XOR partition contract via
9840 // `ephemeral_data_probes_form_binary_xor_partition_over_all`.
9841
9842 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9843 /// [`Classification`] carries a specific
9844 /// [`crate::classification::DataClassification`] variant answers
9845 /// [`Self::data_is_public`] matching the closed set's own
9846 /// [`crate::classification::DataClassification::is_public`] truth
9847 /// table. Sweep
9848 /// [`crate::classification::DataClassification::ALL`] so a
9849 /// regression that (a) hard-coded the body to a fixed answer,
9850 /// (b) inverted the projection, or (c) crossed the wires with
9851 /// the sibling
9852 /// [`crate::classification::DataClassification::is_restricted`]
9853 /// projection fails HERE at the substrate primitive before
9854 /// drifting through the `public-data` fixed tag or the peer
9855 /// point surface.
9856 #[test]
9857 fn data_is_public_returns_data_projection_per_kind() {
9858 for populated in DataClassification::ALL {
9859 let mut classification = Classification::gate_compute();
9860 classification.data_classification = populated;
9861 let mut spec = empty_ephemeral();
9862 spec.classification = Some(classification);
9863 assert_eq!(
9864 spec.data_is_public(),
9865 populated.is_public(),
9866 "authored data_classification={populated:?}: data_is_public() drift",
9867 );
9868 }
9869 }
9870
9871 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9872 /// with `classification: None` routes through the
9873 /// [`Self::resolved_classification`] resolver's substrate default
9874 /// [`Classification::gate_compute`], which carries
9875 /// [`crate::classification::DataClassification::default = Internal`]
9876 /// via `#[default]`, and
9877 /// [`crate::classification::DataClassification::Internal::is_public`]
9878 /// projects `false`, so [`Self::data_is_public`] returns `false`.
9879 /// Pins the resolver's default-arm short-circuit through TWO
9880 /// layers of `Default` ([`Classification::gate_compute`] →
9881 /// [`crate::classification::DataClassification::default`])
9882 /// reaching this derived-nullary predicate. Mirror-inverted from
9883 /// the sibling
9884 /// `data_is_restricted_probes_true_on_absent_classification`
9885 /// (both walk the SAME defaulted `data_classification` field, so
9886 /// `is_restricted = true` ⇒ `is_public = false` on the closed
9887 /// set's disjoint XOR partition). Guarantees every unadorned
9888 /// `(defephemeral …)` audits under the access-controlled default
9889 /// rather than silently promoting an unadorned dataset onto the
9890 /// freely-distributable path.
9891 #[test]
9892 fn data_is_public_probes_false_on_absent_classification() {
9893 let spec = empty_ephemeral();
9894 assert!(spec.classification.is_none());
9895 assert!(
9896 !spec.data_is_public(),
9897 "absent classification (defaults to gate_compute, data_classification=Internal → is_public=false)",
9898 );
9899 }
9900
9901 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9902 /// identically through [`Self::data_is_public`] AND through
9903 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_public()`
9904 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9905 /// classification, `Some(_)` classification on every
9906 /// [`crate::classification::DataClassification::ALL`] variant) so
9907 /// a future regression on either side of the resolver fails HERE
9908 /// at the parity boundary. Byte-for-byte peer of
9909 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
9910 /// on the SAME closed-set axis via the antisymmetric projection.
9911 #[test]
9912 fn data_is_public_matches_point_peer_through_lowered_classification() {
9913 // Absent classification.
9914 let eph = empty_ephemeral();
9915 let lowered: ProcessSpec = eph.clone().into();
9916 assert_eq!(
9917 eph.data_is_public(),
9918 lowered.classification.data_is_public(),
9919 "None-classification parity drift",
9920 );
9921 // Authored classification.
9922 for populated in DataClassification::ALL {
9923 let mut classification = Classification::gate_compute();
9924 classification.data_classification = populated;
9925 let mut eph = empty_ephemeral();
9926 eph.classification = Some(classification);
9927 let lowered: ProcessSpec = eph.clone().into();
9928 assert_eq!(
9929 eph.data_is_public(),
9930 lowered.classification.data_is_public(),
9931 "authored data_classification={populated:?}: parity drift",
9932 );
9933 }
9934 }
9935
9936 /// MUTEX pin — [`Self::data_is_regulated`] AND
9937 /// [`Self::data_is_public`] are NEVER simultaneously true for ANY
9938 /// [`EphemeralSpec`] (authored or defaulted). FIRST ephemeral-
9939 /// surface data-axis antisymmetric MUTEX pin against the
9940 /// positive-distribution framing: sealed on the closed set by
9941 /// `data_classification_regulated_implies_not_public` and lifted
9942 /// through the resolver hop as a substrate-wide contract on this
9943 /// surface.
9944 #[test]
9945 fn ephemeral_data_is_regulated_and_data_is_public_are_mutex_over_all() {
9946 // Absent classification.
9947 let eph = empty_ephemeral();
9948 assert!(
9949 !(eph.data_is_regulated() && eph.data_is_public()),
9950 "None-classification: data_is_regulated AND data_is_public both true (mutex violated)",
9951 );
9952 // Authored classification.
9953 for populated in DataClassification::ALL {
9954 let mut classification = Classification::gate_compute();
9955 classification.data_classification = populated;
9956 let mut eph = empty_ephemeral();
9957 eph.classification = Some(classification);
9958 assert!(
9959 !(eph.data_is_regulated() && eph.data_is_public()),
9960 "authored data_classification={populated:?}: data_is_regulated AND data_is_public both true (mutex violated)",
9961 );
9962 }
9963 }
9964
9965 /// BINARY XOR PARTITION pin — for the absent-classification
9966 /// baseline AND every
9967 /// [`crate::classification::DataClassification::ALL`] variant,
9968 /// EXACTLY ONE of [`Self::data_is_public`] and
9969 /// [`Self::data_is_restricted`] returns `true`. CLOSES the data-
9970 /// axis MUTEX pin (`data_is_regulated ⇒ ¬data_is_public`) into
9971 /// the FULL binary XOR partition contract on the ephemeral
9972 /// surface — the resolver-hop peer of the parent-composed
9973 /// `classification_data_probes_form_binary_xor_partition_over_all`
9974 /// test. Binary counterpart of the ternary XOR partitions sealed
9975 /// on the sibling `point_type` and `substrate` axes by
9976 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
9977 /// and
9978 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
9979 /// Guarantees the absent-classification case lands in the
9980 /// access-controlled bucket (`gate_compute` →
9981 /// DataClassification::Internal → is_public = false,
9982 /// is_restricted = true), so every unadorned `(defephemeral …)`
9983 /// audits under a definite non-empty distribution bucket.
9984 #[test]
9985 fn ephemeral_data_probes_form_binary_xor_partition_over_all() {
9986 // Absent classification.
9987 let eph = empty_ephemeral();
9988 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
9989 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9990 assert_eq!(
9991 hits, 1,
9992 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9993 );
9994 // Authored classification.
9995 for populated in DataClassification::ALL {
9996 let mut classification = Classification::gate_compute();
9997 classification.data_classification = populated;
9998 let mut eph = empty_ephemeral();
9999 eph.classification = Some(classification);
10000 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
10001 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10002 assert_eq!(
10003 hits, 1,
10004 "authored data_classification={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10005 );
10006 }
10007 }
10008
10009 // ── EphemeralSpec::direction_prefers_lower pins ─────────────────
10010 //
10011 // Fail-before-pass-after granularity: `direction_prefers_lower`
10012 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10013 // walking the "does this ephemeral spec's rate-window evaluator
10014 // treat decreasing values as improvement?" question went through
10015 // `.resolved_classification().horizon.direction.unwrap_or_default().prefers_lower()`.
10016 // Post-lift the FOURTEENTH derived-nullary-boolean peer on the
10017 // ephemeral surface (FIRST on the optimization-direction axis,
10018 // opening the SIXTH classification axis into the fixed-tag algebra)
10019 // routes through the SAME [`Self::resolved_classification`] resolver
10020 // + the sibling substrate primitive
10021 // [`crate::classification::Classification::direction_prefers_lower`],
10022 // so the two-surface parity contract holds by construction.
10023
10024 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10025 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
10026 /// answers [`Self::direction_prefers_lower`] matching the closed
10027 /// set's own
10028 /// [`crate::classification::OptimizationDirection::prefers_lower`]
10029 /// truth table. Sweep
10030 /// [`crate::classification::OptimizationDirection::ALL`] so a
10031 /// regression that (a) hard-coded the body to a fixed answer,
10032 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
10033 /// hop, or (d) crossed the wires with a sibling classification-axis
10034 /// probe fails HERE at the substrate primitive before drifting
10035 /// through the `prefers-lower-direction` fixed tag or the peer
10036 /// point surface.
10037 #[test]
10038 fn direction_prefers_lower_returns_direction_projection_per_kind() {
10039 for populated in OptimizationDirection::ALL {
10040 let mut classification = Classification::gate_compute();
10041 classification.horizon.direction = Some(populated);
10042 let mut spec = empty_ephemeral();
10043 spec.classification = Some(classification);
10044 assert_eq!(
10045 spec.direction_prefers_lower(),
10046 populated.prefers_lower(),
10047 "authored horizon.direction={populated:?}: direction_prefers_lower() drift",
10048 );
10049 }
10050 }
10051
10052 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10053 /// with `classification: None` routes through the
10054 /// [`Self::resolved_classification`] resolver's substrate default
10055 /// [`Classification::gate_compute`], which carries
10056 /// `horizon: Horizon::default()` whose `direction` field is `None`,
10057 /// so `unwrap_or_default()` defaults to
10058 /// [`crate::classification::OptimizationDirection::Minimize`] via
10059 /// `#[default]`, and `Minimize.prefers_lower()` projects `true`,
10060 /// so [`Self::direction_prefers_lower`] returns `true`. Pins the
10061 /// resolver's default-arm short-circuit through THREE layers of
10062 /// `Default` ([`Classification::gate_compute`] →
10063 /// [`crate::classification::Horizon::default`] with `direction: None`
10064 /// → [`crate::classification::OptimizationDirection::default =
10065 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
10066 /// every unadorned `(defephemeral …)` reads under the lower-is-
10067 /// better polarity default (safe under the asymptotic-health
10068 /// rate-window evaluator convention: an operator must deliberately
10069 /// opt into Maximize polarity).
10070 #[test]
10071 fn direction_prefers_lower_probes_true_on_absent_classification() {
10072 let spec = empty_ephemeral();
10073 assert!(spec.classification.is_none());
10074 assert!(
10075 spec.direction_prefers_lower(),
10076 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_lower=true)",
10077 );
10078 }
10079
10080 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10081 /// identically through [`Self::direction_prefers_lower`] AND through
10082 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_lower()`
10083 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10084 /// classification, `Some(_)` classification on every
10085 /// [`crate::classification::OptimizationDirection::ALL`] variant) so
10086 /// a future regression on either side of the resolver fails HERE
10087 /// at the parity boundary. Byte-for-byte peer of
10088 /// `calm_is_monotone_matches_point_peer_through_lowered_classification`
10089 /// on the analog closed-set axis via the same resolver-hop shape.
10090 #[test]
10091 fn direction_prefers_lower_matches_point_peer_through_lowered_classification() {
10092 // Absent classification.
10093 let eph = empty_ephemeral();
10094 let lowered: ProcessSpec = eph.clone().into();
10095 assert_eq!(
10096 eph.direction_prefers_lower(),
10097 lowered.classification.direction_prefers_lower(),
10098 "None-classification parity drift",
10099 );
10100 // Authored classification.
10101 for populated in OptimizationDirection::ALL {
10102 let mut classification = Classification::gate_compute();
10103 classification.horizon.direction = Some(populated);
10104 let mut eph = empty_ephemeral();
10105 eph.classification = Some(classification);
10106 let lowered: ProcessSpec = eph.clone().into();
10107 assert_eq!(
10108 eph.direction_prefers_lower(),
10109 lowered.classification.direction_prefers_lower(),
10110 "authored horizon.direction={populated:?}: parity drift",
10111 );
10112 }
10113 }
10114
10115 // ── EphemeralSpec::direction_prefers_higher pins ────────────────
10116 //
10117 // Fail-before-pass-after granularity: `direction_prefers_higher`
10118 // did not exist pre-lift on `impl EphemeralSpec` — the positive
10119 // higher-is-better framing peer of
10120 // [`Self::direction_prefers_lower`] had no ephemeral-surface
10121 // substrate owner. Post-lift the FIFTEENTH derived-nullary-boolean
10122 // peer on the ephemeral surface (SECOND on the optimization-
10123 // direction axis, CLOSING the SIXTH classification axis into a
10124 // binary XOR partition on this surface) routes through the SAME
10125 // [`Self::resolved_classification`] resolver + the sibling
10126 // substrate primitive
10127 // [`crate::classification::Classification::direction_prefers_higher`],
10128 // so the two-surface parity contract holds by construction, AND
10129 // the two-way lower/higher split on this surface CLOSES the
10130 // optimization-direction axis into the FULL binary XOR partition
10131 // contract via
10132 // `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
10133
10134 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10135 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
10136 /// answers [`Self::direction_prefers_higher`] matching the closed
10137 /// set's own
10138 /// [`crate::classification::OptimizationDirection::prefers_higher`]
10139 /// truth table. Sweep
10140 /// [`crate::classification::OptimizationDirection::ALL`] so a
10141 /// regression that (a) hard-coded the body to a fixed answer,
10142 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
10143 /// hop, or (d) crossed the wires with a sibling classification-
10144 /// axis probe fails HERE at the substrate primitive before
10145 /// drifting through the `prefers-higher-direction` fixed tag or
10146 /// the peer point surface.
10147 #[test]
10148 fn direction_prefers_higher_returns_direction_projection_per_kind() {
10149 for populated in OptimizationDirection::ALL {
10150 let mut classification = Classification::gate_compute();
10151 classification.horizon.direction = Some(populated);
10152 let mut spec = empty_ephemeral();
10153 spec.classification = Some(classification);
10154 assert_eq!(
10155 spec.direction_prefers_higher(),
10156 populated.prefers_higher(),
10157 "authored horizon.direction={populated:?}: direction_prefers_higher() drift",
10158 );
10159 }
10160 }
10161
10162 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10163 /// with `classification: None` routes through the
10164 /// [`Self::resolved_classification`] resolver's substrate default
10165 /// [`Classification::gate_compute`], which carries
10166 /// `horizon: Horizon::default()` whose `direction` field is `None`,
10167 /// so `unwrap_or_default()` defaults to
10168 /// [`crate::classification::OptimizationDirection::Minimize`] via
10169 /// `#[default]`, and `Minimize.prefers_higher()` projects `false`,
10170 /// so [`Self::direction_prefers_higher`] returns `false`. Pins
10171 /// the resolver's default-arm short-circuit through THREE layers
10172 /// of `Default` ([`Classification::gate_compute`] →
10173 /// [`crate::classification::Horizon::default`] with `direction:
10174 /// None` → [`crate::classification::OptimizationDirection::default =
10175 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
10176 /// every unadorned `(defephemeral …)` reads UNDER the lower-is-
10177 /// better polarity default (safe under the asymptotic-health
10178 /// rate-window evaluator convention: an operator must
10179 /// deliberately opt into Maximize polarity). Mirror-inverted from
10180 /// the sibling `direction_prefers_lower_probes_true_on_absent_classification`
10181 /// baseline on the same resolver walk.
10182 #[test]
10183 fn direction_prefers_higher_probes_false_on_absent_classification() {
10184 let spec = empty_ephemeral();
10185 assert!(spec.classification.is_none());
10186 assert!(
10187 !spec.direction_prefers_higher(),
10188 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_higher=false)",
10189 );
10190 }
10191
10192 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10193 /// identically through [`Self::direction_prefers_higher`] AND
10194 /// through
10195 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_higher()`
10196 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10197 /// classification, `Some(_)` classification on every
10198 /// [`crate::classification::OptimizationDirection::ALL`] variant)
10199 /// so a future regression on either side of the resolver fails
10200 /// HERE at the parity boundary. Byte-for-byte peer of
10201 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
10202 /// on the antisymmetric closed-set arm via the same resolver-hop
10203 /// shape.
10204 #[test]
10205 fn direction_prefers_higher_matches_point_peer_through_lowered_classification() {
10206 // Absent classification.
10207 let eph = empty_ephemeral();
10208 let lowered: ProcessSpec = eph.clone().into();
10209 assert_eq!(
10210 eph.direction_prefers_higher(),
10211 lowered.classification.direction_prefers_higher(),
10212 "None-classification parity drift",
10213 );
10214 // Authored classification.
10215 for populated in OptimizationDirection::ALL {
10216 let mut classification = Classification::gate_compute();
10217 classification.horizon.direction = Some(populated);
10218 let mut eph = empty_ephemeral();
10219 eph.classification = Some(classification);
10220 let lowered: ProcessSpec = eph.clone().into();
10221 assert_eq!(
10222 eph.direction_prefers_higher(),
10223 lowered.classification.direction_prefers_higher(),
10224 "authored horizon.direction={populated:?}: parity drift",
10225 );
10226 }
10227 }
10228
10229 /// BINARY XOR PARTITION pin — for the absent-classification
10230 /// baseline AND every
10231 /// [`crate::classification::OptimizationDirection::ALL`] variant,
10232 /// EXACTLY ONE of [`Self::direction_prefers_lower`] and
10233 /// [`Self::direction_prefers_higher`] returns `true`. CLOSES the
10234 /// optimization-direction axis into the FULL binary XOR partition
10235 /// contract on the ephemeral surface — the resolver-hop peer of
10236 /// the parent-composed
10237 /// `classification_direction_probes_form_binary_xor_partition_over_all`
10238 /// test. Binary counterpart of the ternary XOR partitions sealed
10239 /// on the sibling `point_type` and `substrate` axes by
10240 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10241 /// and
10242 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10243 /// structural twin of the calm/data binary partitions
10244 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all` and
10245 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
10246 /// This pin is the SIXTH (and final) classification axis to reach
10247 /// the closed XOR partition landmark on the ephemeral resolver-
10248 /// hop surface — ALL SIX classification axes (horizon, calm,
10249 /// data, point, substrate, optimization-direction) now have
10250 /// their partitions closed on the ephemeral surface at this
10251 /// corner. Guarantees the absent-classification case lands in
10252 /// the definite lower-is-better bucket (`gate_compute` →
10253 /// Horizon::default → direction: None →
10254 /// OptimizationDirection::default = Minimize → prefers_lower =
10255 /// true, prefers_higher = false), so every unadorned
10256 /// `(defephemeral …)` audits under a definite non-empty polarity
10257 /// bucket.
10258 #[test]
10259 fn ephemeral_direction_probes_form_binary_xor_partition_over_all() {
10260 // Absent classification.
10261 let eph = empty_ephemeral();
10262 let buckets = [
10263 eph.direction_prefers_lower(),
10264 eph.direction_prefers_higher(),
10265 ];
10266 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10267 assert_eq!(
10268 hits, 1,
10269 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10270 );
10271 // Authored classification.
10272 for populated in OptimizationDirection::ALL {
10273 let mut classification = Classification::gate_compute();
10274 classification.horizon.direction = Some(populated);
10275 let mut eph = empty_ephemeral();
10276 eph.classification = Some(classification);
10277 let buckets = [
10278 eph.direction_prefers_lower(),
10279 eph.direction_prefers_higher(),
10280 ];
10281 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10282 assert_eq!(
10283 hits, 1,
10284 "authored horizon.direction={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10285 );
10286 }
10287 }
10288
10289 // ── EphemeralSpec::input_arity_is_one pins ──────────────────────
10290 //
10291 // Fail-before-pass-after granularity: `input_arity_is_one` did not
10292 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10293 // the "does this ephemeral spec's DAG-composition input port
10294 // accept a single upstream edge?" question went through
10295 // `.resolved_classification().point_type.input_arity().is_one()`.
10296 // Post-lift the SIXTEENTH derived-nullary-boolean peer on the
10297 // ephemeral surface (FIRST on the input-arity axis, opening the
10298 // SEVENTH classification axis into the fixed-tag algebra + the
10299 // derived-typed-projection stratum on this surface for the first
10300 // time) routes through the SAME [`Self::resolved_classification`]
10301 // resolver + the sibling substrate primitive
10302 // [`crate::classification::Classification::input_arity_is_one`],
10303 // so the two-surface parity contract holds by construction.
10304
10305 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10306 /// [`Classification`] carries `point_type: kind` answers
10307 /// [`Self::input_arity_is_one`] matching the closed set's own
10308 /// [`crate::classification::ConvergencePointType::input_arity`]
10309 /// truth table projected through [`Arity::is_one`]. Sweep
10310 /// [`crate::classification::ConvergencePointType::ALL`] so a
10311 /// regression that (a) hard-coded the body to a fixed answer,
10312 /// (b) inverted the projection, (c) dropped the resolver hop, or
10313 /// (d) crossed the wires with the sibling `output_arity`
10314 /// projection (which disagrees on six of eight variants) fails
10315 /// HERE at the substrate primitive before drifting through the
10316 /// future `single-input-arity` fixed tag or the peer point
10317 /// surface.
10318 #[test]
10319 fn input_arity_is_one_returns_input_arity_projection_per_kind() {
10320 for populated in ConvergencePointType::ALL {
10321 let mut classification = Classification::gate_compute();
10322 classification.point_type = populated;
10323 let mut spec = empty_ephemeral();
10324 spec.classification = Some(classification);
10325 assert_eq!(
10326 spec.input_arity_is_one(),
10327 populated.input_arity().is_one(),
10328 "authored point_type={populated:?}: input_arity_is_one() drift",
10329 );
10330 }
10331 }
10332
10333 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10334 /// with `classification: None` routes through the
10335 /// [`Self::resolved_classification`] resolver's substrate default
10336 /// [`Classification::gate_compute`], which carries `point_type:
10337 /// Gate` and `Gate.input_arity() = Many`, so
10338 /// [`Self::input_arity_is_one`] returns `false`. Pins the
10339 /// resolver's default-arm short-circuit reaching this derived-
10340 /// nullary predicate — every unadorned `(defephemeral …)` lands
10341 /// in the multi-input bucket under the substrate default. Mirror-
10342 /// inverted from the sibling `input_arity_is_many` baseline on
10343 /// the same resolver walk (the XOR partition forces exactly one
10344 /// bucket per baseline).
10345 #[test]
10346 fn input_arity_is_one_probes_false_on_absent_classification() {
10347 let spec = empty_ephemeral();
10348 assert!(spec.classification.is_none());
10349 assert!(
10350 !spec.input_arity_is_one(),
10351 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_one=false)",
10352 );
10353 }
10354
10355 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10356 /// identically through [`Self::input_arity_is_one`] AND through
10357 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_one()`
10358 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10359 /// classification, `Some(_)` classification on every
10360 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10361 /// so a future regression on either side of the resolver fails
10362 /// HERE at the parity boundary. Byte-for-byte peer of
10363 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
10364 /// on the same resolver-hop shape.
10365 #[test]
10366 fn input_arity_is_one_matches_point_peer_through_lowered_classification() {
10367 // Absent classification.
10368 let eph = empty_ephemeral();
10369 let lowered: ProcessSpec = eph.clone().into();
10370 assert_eq!(
10371 eph.input_arity_is_one(),
10372 lowered.classification.input_arity_is_one(),
10373 "None-classification parity drift",
10374 );
10375 // Authored classification.
10376 for populated in ConvergencePointType::ALL {
10377 let mut classification = Classification::gate_compute();
10378 classification.point_type = populated;
10379 let mut eph = empty_ephemeral();
10380 eph.classification = Some(classification);
10381 let lowered: ProcessSpec = eph.clone().into();
10382 assert_eq!(
10383 eph.input_arity_is_one(),
10384 lowered.classification.input_arity_is_one(),
10385 "authored point_type={populated:?}: parity drift",
10386 );
10387 }
10388 }
10389
10390 // ── EphemeralSpec::input_arity_is_many pins ─────────────────────
10391 //
10392 // Fail-before-pass-after granularity: `input_arity_is_many` did
10393 // not exist pre-lift on `impl EphemeralSpec` — the multi-input
10394 // framing peer of [`Self::input_arity_is_one`] had no ephemeral-
10395 // surface substrate owner. Post-lift the SEVENTEENTH derived-
10396 // nullary-boolean peer on the ephemeral surface (SECOND on the
10397 // input-arity axis, CLOSING the SEVENTH classification axis into
10398 // a binary XOR partition on this surface) routes through the SAME
10399 // [`Self::resolved_classification`] resolver + the sibling
10400 // substrate primitive
10401 // [`crate::classification::Classification::input_arity_is_many`],
10402 // so the two-surface parity contract holds by construction, AND
10403 // the two-way single/many split on this surface CLOSES the
10404 // input-arity axis into the FULL binary XOR partition contract
10405 // via `ephemeral_input_arity_probes_form_binary_xor_partition_over_all`.
10406
10407 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10408 /// [`Classification`] carries `point_type: kind` answers
10409 /// [`Self::input_arity_is_many`] matching the closed set's own
10410 /// [`crate::classification::ConvergencePointType::input_arity`]
10411 /// truth table projected through [`Arity::is_many`]. Sweep
10412 /// [`crate::classification::ConvergencePointType::ALL`] so a
10413 /// regression that (a) hard-coded the body to a fixed answer,
10414 /// (b) inverted the projection, (c) dropped the resolver hop, or
10415 /// (d) crossed the wires with the sibling `output_arity`
10416 /// projection fails HERE at the substrate primitive before
10417 /// drifting through the future `multi-input-arity` fixed tag or
10418 /// the peer point surface.
10419 #[test]
10420 fn input_arity_is_many_returns_input_arity_projection_per_kind() {
10421 for populated in ConvergencePointType::ALL {
10422 let mut classification = Classification::gate_compute();
10423 classification.point_type = populated;
10424 let mut spec = empty_ephemeral();
10425 spec.classification = Some(classification);
10426 assert_eq!(
10427 spec.input_arity_is_many(),
10428 populated.input_arity().is_many(),
10429 "authored point_type={populated:?}: input_arity_is_many() drift",
10430 );
10431 }
10432 }
10433
10434 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10435 /// with `classification: None` routes through the
10436 /// [`Self::resolved_classification`] resolver's substrate default
10437 /// [`Classification::gate_compute`], which carries `point_type:
10438 /// Gate` and `Gate.input_arity() = Many`, so
10439 /// [`Self::input_arity_is_many`] returns `true`. Pins the
10440 /// resolver's default-arm short-circuit reaching this derived-
10441 /// nullary predicate — every unadorned `(defephemeral …)` lands
10442 /// in the multi-input bucket under the substrate default. Mirror-
10443 /// inverted from the sibling `input_arity_is_one` baseline on
10444 /// the same resolver walk (the XOR partition forces exactly one
10445 /// bucket per baseline).
10446 #[test]
10447 fn input_arity_is_many_probes_true_on_absent_classification() {
10448 let spec = empty_ephemeral();
10449 assert!(spec.classification.is_none());
10450 assert!(
10451 spec.input_arity_is_many(),
10452 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_many=true)",
10453 );
10454 }
10455
10456 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10457 /// identically through [`Self::input_arity_is_many`] AND through
10458 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_many()`
10459 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10460 /// classification, `Some(_)` classification on every
10461 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10462 /// so a future regression on either side of the resolver fails
10463 /// HERE at the parity boundary. Byte-for-byte peer of
10464 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
10465 /// on the antisymmetric closed-set arm via the same resolver-hop
10466 /// shape.
10467 #[test]
10468 fn input_arity_is_many_matches_point_peer_through_lowered_classification() {
10469 // Absent classification.
10470 let eph = empty_ephemeral();
10471 let lowered: ProcessSpec = eph.clone().into();
10472 assert_eq!(
10473 eph.input_arity_is_many(),
10474 lowered.classification.input_arity_is_many(),
10475 "None-classification parity drift",
10476 );
10477 // Authored classification.
10478 for populated in ConvergencePointType::ALL {
10479 let mut classification = Classification::gate_compute();
10480 classification.point_type = populated;
10481 let mut eph = empty_ephemeral();
10482 eph.classification = Some(classification);
10483 let lowered: ProcessSpec = eph.clone().into();
10484 assert_eq!(
10485 eph.input_arity_is_many(),
10486 lowered.classification.input_arity_is_many(),
10487 "authored point_type={populated:?}: parity drift",
10488 );
10489 }
10490 }
10491
10492 /// BINARY XOR PARTITION pin — for the absent-classification
10493 /// baseline AND every
10494 /// [`crate::classification::ConvergencePointType::ALL`] variant,
10495 /// EXACTLY ONE of [`Self::input_arity_is_one`] and
10496 /// [`Self::input_arity_is_many`] returns `true`. CLOSES the
10497 /// input-arity axis into the FULL binary XOR partition contract
10498 /// on the ephemeral surface — the resolver-hop peer of the
10499 /// parent-composed
10500 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`
10501 /// test. Binary counterpart of the ternary XOR partitions sealed
10502 /// on the sibling `point_type` and `substrate` axes by
10503 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10504 /// and
10505 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10506 /// structural twin of the calm/data/direction binary partitions
10507 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
10508 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`,
10509 /// and
10510 /// `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
10511 /// This pin is the SEVENTH classification axis to reach the
10512 /// closed XOR partition landmark on the ephemeral resolver-hop
10513 /// surface — the FIRST closed axis on the derived-typed-
10514 /// projection stratum of this surface, opening the stratum beyond
10515 /// the six stored classification slots. Guarantees the absent-
10516 /// classification case lands in the definite multi-input bucket
10517 /// (`gate_compute` → point_type=Gate → input_arity=Many →
10518 /// is_one=false, is_many=true), so every unadorned
10519 /// `(defephemeral …)` audits under a definite non-empty input-
10520 /// arity bucket.
10521 #[test]
10522 fn ephemeral_input_arity_probes_form_binary_xor_partition_over_all() {
10523 // Absent classification.
10524 let eph = empty_ephemeral();
10525 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
10526 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10527 assert_eq!(
10528 hits, 1,
10529 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10530 );
10531 // Authored classification.
10532 for populated in ConvergencePointType::ALL {
10533 let mut classification = Classification::gate_compute();
10534 classification.point_type = populated;
10535 let mut eph = empty_ephemeral();
10536 eph.classification = Some(classification);
10537 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
10538 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10539 assert_eq!(
10540 hits, 1,
10541 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10542 );
10543 }
10544 }
10545
10546 // ── EphemeralSpec::output_arity_is_one pins ─────────────────────
10547 //
10548 // Fail-before-pass-after granularity: `output_arity_is_one` did not
10549 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10550 // the "does this ephemeral spec's DAG-composition output port emit
10551 // to a single downstream edge?" question went through
10552 // `.resolved_classification().point_type.output_arity().is_one()`.
10553 // Post-lift the EIGHTEENTH derived-nullary-boolean peer on the
10554 // ephemeral surface (FIRST on the output-arity axis, opening the
10555 // EIGHTH classification axis into the fixed-tag algebra + the
10556 // SECOND peer on the derived-typed-projection stratum after
10557 // [`Self::input_arity_is_one`]) routes through the SAME
10558 // [`Self::resolved_classification`] resolver + the sibling
10559 // substrate primitive
10560 // [`crate::classification::Classification::output_arity_is_one`],
10561 // so the two-surface parity contract holds by construction.
10562
10563 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10564 /// [`Classification`] carries `point_type: kind` answers
10565 /// [`Self::output_arity_is_one`] matching the closed set's own
10566 /// [`crate::classification::ConvergencePointType::output_arity`]
10567 /// truth table projected through [`Arity::is_one`]. Sweep
10568 /// [`crate::classification::ConvergencePointType::ALL`] so a
10569 /// regression that (a) hard-coded the body to a fixed answer,
10570 /// (b) inverted the projection, (c) dropped the resolver hop, or
10571 /// (d) crossed the wires with the sibling `input_arity`
10572 /// projection (which disagrees on six of eight variants) fails
10573 /// HERE at the substrate primitive before drifting through the
10574 /// future `single-output-arity` fixed tag or the peer point
10575 /// surface.
10576 #[test]
10577 fn output_arity_is_one_returns_output_arity_projection_per_kind() {
10578 for populated in ConvergencePointType::ALL {
10579 let mut classification = Classification::gate_compute();
10580 classification.point_type = populated;
10581 let mut spec = empty_ephemeral();
10582 spec.classification = Some(classification);
10583 assert_eq!(
10584 spec.output_arity_is_one(),
10585 populated.output_arity().is_one(),
10586 "authored point_type={populated:?}: output_arity_is_one() drift",
10587 );
10588 }
10589 }
10590
10591 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10592 /// with `classification: None` routes through the
10593 /// [`Self::resolved_classification`] resolver's substrate default
10594 /// [`Classification::gate_compute`], which carries `point_type:
10595 /// Gate` and `Gate.output_arity() = One`, so
10596 /// [`Self::output_arity_is_one`] returns `true`. Pins the
10597 /// resolver's default-arm short-circuit reaching this derived-
10598 /// nullary predicate — every unadorned `(defephemeral …)` lands
10599 /// in the single-output bucket under the substrate default.
10600 /// Mirror-inverted from the sibling `output_arity_is_many`
10601 /// baseline on the same resolver walk (the XOR partition forces
10602 /// exactly one bucket per baseline). Note the workspace-baseline
10603 /// answer FLIPS between the input-arity and output-arity axes on
10604 /// the exact same absent-classification baseline: the input-arity
10605 /// sibling `input_arity_is_one` answers `false`, but this
10606 /// output-arity peer answers `true` — direct evidence at the
10607 /// resolver-hop layer that the two axes carve the closed set
10608 /// into structurally different partitions.
10609 #[test]
10610 fn output_arity_is_one_probes_true_on_absent_classification() {
10611 let spec = empty_ephemeral();
10612 assert!(spec.classification.is_none());
10613 assert!(
10614 spec.output_arity_is_one(),
10615 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_one=true)",
10616 );
10617 }
10618
10619 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10620 /// identically through [`Self::output_arity_is_one`] AND through
10621 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_one()`
10622 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10623 /// classification, `Some(_)` classification on every
10624 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10625 /// so a future regression on either side of the resolver fails
10626 /// HERE at the parity boundary. Byte-for-byte peer of
10627 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
10628 /// on the sibling output-arity projection via the same
10629 /// resolver-hop shape.
10630 #[test]
10631 fn output_arity_is_one_matches_point_peer_through_lowered_classification() {
10632 // Absent classification.
10633 let eph = empty_ephemeral();
10634 let lowered: ProcessSpec = eph.clone().into();
10635 assert_eq!(
10636 eph.output_arity_is_one(),
10637 lowered.classification.output_arity_is_one(),
10638 "None-classification parity drift",
10639 );
10640 // Authored classification.
10641 for populated in ConvergencePointType::ALL {
10642 let mut classification = Classification::gate_compute();
10643 classification.point_type = populated;
10644 let mut eph = empty_ephemeral();
10645 eph.classification = Some(classification);
10646 let lowered: ProcessSpec = eph.clone().into();
10647 assert_eq!(
10648 eph.output_arity_is_one(),
10649 lowered.classification.output_arity_is_one(),
10650 "authored point_type={populated:?}: parity drift",
10651 );
10652 }
10653 }
10654
10655 // ── EphemeralSpec::output_arity_is_many pins ────────────────────
10656 //
10657 // Fail-before-pass-after granularity: `output_arity_is_many` did
10658 // not exist pre-lift on `impl EphemeralSpec` — the multi-output
10659 // framing peer of [`Self::output_arity_is_one`] had no ephemeral-
10660 // surface substrate owner. Post-lift the NINETEENTH derived-
10661 // nullary-boolean peer on the ephemeral surface (SECOND on the
10662 // output-arity axis, CLOSING the EIGHTH classification axis into
10663 // a binary XOR partition on this surface) routes through the SAME
10664 // [`Self::resolved_classification`] resolver + the sibling
10665 // substrate primitive
10666 // [`crate::classification::Classification::output_arity_is_many`],
10667 // so the two-surface parity contract holds by construction, AND
10668 // the two-way single/many split on this surface CLOSES the
10669 // output-arity axis into the FULL binary XOR partition contract
10670 // via `ephemeral_output_arity_probes_form_binary_xor_partition_over_all`,
10671 // completing the DAG-composition arity PAIR on the ephemeral
10672 // derived-typed-projection stratum.
10673
10674 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10675 /// [`Classification`] carries `point_type: kind` answers
10676 /// [`Self::output_arity_is_many`] matching the closed set's own
10677 /// [`crate::classification::ConvergencePointType::output_arity`]
10678 /// truth table projected through [`Arity::is_many`]. Sweep
10679 /// [`crate::classification::ConvergencePointType::ALL`] so a
10680 /// regression that (a) hard-coded the body to a fixed answer,
10681 /// (b) inverted the projection, (c) dropped the resolver hop, or
10682 /// (d) crossed the wires with the sibling `input_arity`
10683 /// projection fails HERE at the substrate primitive before
10684 /// drifting through the future `multi-output-arity` fixed tag or
10685 /// the peer point surface.
10686 #[test]
10687 fn output_arity_is_many_returns_output_arity_projection_per_kind() {
10688 for populated in ConvergencePointType::ALL {
10689 let mut classification = Classification::gate_compute();
10690 classification.point_type = populated;
10691 let mut spec = empty_ephemeral();
10692 spec.classification = Some(classification);
10693 assert_eq!(
10694 spec.output_arity_is_many(),
10695 populated.output_arity().is_many(),
10696 "authored point_type={populated:?}: output_arity_is_many() drift",
10697 );
10698 }
10699 }
10700
10701 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10702 /// with `classification: None` routes through the
10703 /// [`Self::resolved_classification`] resolver's substrate default
10704 /// [`Classification::gate_compute`], which carries `point_type:
10705 /// Gate` and `Gate.output_arity() = One`, so
10706 /// [`Self::output_arity_is_many`] returns `false`. Pins the
10707 /// resolver's default-arm short-circuit reaching this derived-
10708 /// nullary predicate — every unadorned `(defephemeral …)` lands
10709 /// in the single-output bucket under the substrate default.
10710 /// Mirror-inverted from the sibling `output_arity_is_one`
10711 /// baseline on the same resolver walk (the XOR partition forces
10712 /// exactly one bucket per baseline).
10713 #[test]
10714 fn output_arity_is_many_probes_false_on_absent_classification() {
10715 let spec = empty_ephemeral();
10716 assert!(spec.classification.is_none());
10717 assert!(
10718 !spec.output_arity_is_many(),
10719 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_many=false)",
10720 );
10721 }
10722
10723 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10724 /// identically through [`Self::output_arity_is_many`] AND through
10725 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_many()`
10726 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10727 /// classification, `Some(_)` classification on every
10728 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10729 /// so a future regression on either side of the resolver fails
10730 /// HERE at the parity boundary. Byte-for-byte peer of
10731 /// `output_arity_is_one_matches_point_peer_through_lowered_classification`
10732 /// on the antisymmetric closed-set arm via the same resolver-hop
10733 /// shape.
10734 #[test]
10735 fn output_arity_is_many_matches_point_peer_through_lowered_classification() {
10736 // Absent classification.
10737 let eph = empty_ephemeral();
10738 let lowered: ProcessSpec = eph.clone().into();
10739 assert_eq!(
10740 eph.output_arity_is_many(),
10741 lowered.classification.output_arity_is_many(),
10742 "None-classification parity drift",
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 lowered: ProcessSpec = eph.clone().into();
10751 assert_eq!(
10752 eph.output_arity_is_many(),
10753 lowered.classification.output_arity_is_many(),
10754 "authored point_type={populated:?}: parity drift",
10755 );
10756 }
10757 }
10758
10759 /// BINARY XOR PARTITION pin — for the absent-classification
10760 /// baseline AND every
10761 /// [`crate::classification::ConvergencePointType::ALL`] variant,
10762 /// EXACTLY ONE of [`Self::output_arity_is_one`] and
10763 /// [`Self::output_arity_is_many`] returns `true`. CLOSES the
10764 /// output-arity axis into the FULL binary XOR partition contract
10765 /// on the ephemeral surface — the resolver-hop peer of the
10766 /// parent-composed
10767 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`
10768 /// test. Binary counterpart of the ternary XOR partitions sealed
10769 /// on the sibling `point_type` and `substrate` axes by
10770 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10771 /// and
10772 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10773 /// structural twin of the calm/data/direction/input-arity binary
10774 /// partitions on this surface. This pin is the EIGHTH
10775 /// classification axis to reach the closed XOR partition landmark
10776 /// on the ephemeral resolver-hop surface — the SECOND closed axis
10777 /// on the derived-typed-projection stratum of this surface,
10778 /// completing the DAG-composition arity PAIR on the ephemeral
10779 /// stratum after the input-arity closure. Guarantees the absent-
10780 /// classification case lands in the definite single-output bucket
10781 /// (`gate_compute` → point_type=Gate → output_arity=One →
10782 /// is_one=true, is_many=false), so every unadorned
10783 /// `(defephemeral …)` audits under a definite non-empty
10784 /// output-arity bucket.
10785 #[test]
10786 fn ephemeral_output_arity_probes_form_binary_xor_partition_over_all() {
10787 // Absent classification.
10788 let eph = empty_ephemeral();
10789 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
10790 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10791 assert_eq!(
10792 hits, 1,
10793 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10794 );
10795 // Authored classification.
10796 for populated in ConvergencePointType::ALL {
10797 let mut classification = Classification::gate_compute();
10798 classification.point_type = populated;
10799 let mut eph = empty_ephemeral();
10800 eph.classification = Some(classification);
10801 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
10802 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10803 assert_eq!(
10804 hits, 1,
10805 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10806 );
10807 }
10808 }
10809
10810 /// BINARY XOR PARTITION pin — for the absent-classification
10811 /// baseline AND every
10812 /// [`crate::classification::HorizonKind::ALL`] variant, EXACTLY
10813 /// ONE of [`Self::horizon_terminates`] and
10814 /// [`Self::horizon_requires_metric_axes`] returns `true`. CLOSES
10815 /// the horizon axis into the FULL binary XOR partition contract
10816 /// on the ephemeral surface — the resolver-hop peer of the
10817 /// parent-composed
10818 /// `classification_horizon_probes_form_binary_xor_partition_over_all`
10819 /// test. Binary counterpart of the ternary XOR partitions sealed
10820 /// on the sibling `point_type` and `substrate` axes by
10821 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10822 /// and
10823 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10824 /// structural twin of the calm/data binary partitions
10825 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`
10826 /// and
10827 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
10828 /// This pin is the FIFTH (and final) classification axis to reach
10829 /// the closed XOR partition landmark on the ephemeral resolver-
10830 /// hop surface, sealing every classification axis under the
10831 /// SAME `hits == 1` bucket-array contract. Guarantees the absent-
10832 /// classification case lands in the definite terminating bucket
10833 /// (`gate_compute` → HorizonKind::Bounded → terminates = true,
10834 /// requires_metric_axes = false), so every unadorned
10835 /// `(defephemeral …)` audits under a definite non-empty horizon
10836 /// bucket. Rewritten from the earlier binary-XOR-only form
10837 /// (walked as `a ^ b`) into the canonical bucket-array shape
10838 /// shared with the calm/data partitions.
10839 #[test]
10840 fn ephemeral_horizon_probes_form_binary_xor_partition_over_all() {
10841 // Absent classification.
10842 let eph = empty_ephemeral();
10843 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
10844 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10845 assert_eq!(
10846 hits, 1,
10847 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10848 );
10849 // Authored classification.
10850 for populated in HorizonKind::ALL {
10851 let classification = Classification::gate_compute_with_axis(populated);
10852 let mut eph = empty_ephemeral();
10853 eph.classification = Some(classification);
10854 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
10855 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10856 assert_eq!(
10857 hits, 1,
10858 "authored horizon.kind={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10859 );
10860 }
10861 }
10862
10863 // ── EphemeralSpec::has_routing_form pins ─────────────────────────
10864 //
10865 // Fail-before-pass-after granularity: `has_routing_form` did not
10866 // exist pre-lift on `impl EphemeralSpec` — the point-surface
10867 // `routing-form-<kind>` prefix family in tatara-check routed
10868 // through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`
10869 // inline, so the ephemeral surface had no matching primitive to
10870 // publish the SAME `routing-form-<kind>` prefix family through
10871 // the `strip_and_classify_prefixed_kind` substrate. Post-lift the
10872 // Option-gated derived-scalar-child probe body lives at ONE
10873 // inherent site on [`EphemeralSpec`] and every consumer (this
10874 // module's peer-symmetry tests, tatara-check's ephemeral
10875 // require-tag classifier, any future audit dispatcher walking
10876 // [`RoutingForm::ALL`] over the ephemeral surface) binds through
10877 // the SAME `has_routing_form(kind)` shape.
10878
10879 fn routing_spec(is_stable: bool) -> RoutingSpec {
10880 use crate::routing::{RoutingBackend, RoutingHostname};
10881 RoutingSpec {
10882 hostnames: vec![RoutingHostname::content_hashed("api")],
10883 backend: RoutingBackend::plain("svc", 80),
10884 stable_name_claim: is_stable,
10885 priority: 0,
10886 }
10887 }
10888
10889 /// POPULATED-slot pin — a populated `routing` slot answers `true`
10890 /// exactly for the [`RoutingForm`] variant its
10891 /// [`RoutingSpec::has_form`] derived-scalar arm agrees with, and
10892 /// `false` for every other variant. Sweep the two-boolean × ALL
10893 /// cross so a regression that (a) hard-coded the arm to a single
10894 /// variant, (b) dropped the Option-parent gate (silently reading
10895 /// through `.unwrap_or_default()` on an absent routing slot), or
10896 /// (c) crossed the wires from
10897 /// [`RoutingForm::from_is_stable`] to a fixed variant fails
10898 /// HERE before landing at the operator-facing checks.lisp
10899 /// surface.
10900 #[test]
10901 fn has_routing_form_returns_true_iff_populated_routing_derives_form_per_kind() {
10902 for is_stable in [true, false] {
10903 let populated = RoutingForm::from_is_stable(is_stable);
10904 let mut spec = empty_ephemeral();
10905 spec.routing = Some(routing_spec(is_stable));
10906 for query in RoutingForm::ALL {
10907 let expected = query == populated;
10908 assert_eq!(
10909 spec.has_routing_form(query),
10910 expected,
10911 "ephemeral routing.stable_name_claim={is_stable} (derives {populated:?}): query {query:?} drifted",
10912 );
10913 }
10914 }
10915 }
10916
10917 /// OPTION-PARENT SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
10918 /// `routing` slot is `None` returns `false` for every
10919 /// [`RoutingForm`] variant, INCLUDING the closed set's
10920 /// derived-default [`RoutingForm::Instance`]. Locks the
10921 /// Option-parent silencing contract so a regression that dropped
10922 /// the `spec.routing.as_ref()` gate (silently probing an absent
10923 /// routing slot as if it carried the defaulted `Instance` form)
10924 /// fails HERE. Peer to
10925 /// [`evaluate_point_require_tag_returns_false_on_absent_routing_for_every_routing_form_kind`]
10926 /// on the point surface — the two-surface symmetry means both
10927 /// classifiers publish the SAME Option-parent silencing at ONE
10928 /// substrate site per surface.
10929 #[test]
10930 fn has_routing_form_returns_false_on_absent_routing_for_every_kind() {
10931 let spec = empty_ephemeral();
10932 assert!(spec.routing.is_none());
10933 for kind in RoutingForm::ALL {
10934 assert!(
10935 !spec.has_routing_form(kind),
10936 "absent ephemeral routing must return false for {kind:?}",
10937 );
10938 }
10939 }
10940
10941 /// DEFAULT-ARM SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
10942 /// `routing` slot is a [`RoutingSpec`] with `stable_name_claim`
10943 /// at its `#[serde(default)]` (bool default = `false`) answers
10944 /// `true` on [`RoutingForm::Instance`] and `false` on every other
10945 /// variant WITHOUT the operator naming the routing-form axis on
10946 /// the routing spec. Peer to
10947 /// [`evaluate_point_require_tag_returns_true_on_default_routing_form_for_instance_only`]
10948 /// on the point surface — both surfaces read the derived-child
10949 /// arm through the ONE substrate composer
10950 /// [`RoutingForm::from_is_stable`], so a future normalization at
10951 /// the derivation lands at ONE site and every downstream
10952 /// (routing-form require-tag families on both surfaces,
10953 /// closed-set audit dispatchers) picks it up mechanically.
10954 #[test]
10955 fn has_routing_form_probes_instance_only_on_default_populated_routing() {
10956 let mut spec = empty_ephemeral();
10957 spec.routing = Some(routing_spec(bool::default()));
10958 for kind in RoutingForm::ALL {
10959 let expected = kind == RoutingForm::Instance;
10960 assert_eq!(
10961 spec.has_routing_form(kind),
10962 expected,
10963 "default-populated ephemeral routing (stable_name_claim=false → Instance) baseline: query {kind:?} must be {expected}",
10964 );
10965 }
10966 }
10967
10968 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
10969 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
10970 /// answer identically on every [`RoutingForm`] × `is_stable`
10971 /// combination. Locks the byte-for-byte parity between
10972 /// [`EphemeralSpec::has_routing_form`] (this new primitive) and
10973 /// the point surface's `spec.routing.as_ref().is_some_and(|r|
10974 /// r.has_form(k))` inline projection at the tatara-check dispatch
10975 /// site. A regression that (a) diverged the ephemeral probe from
10976 /// the lowered point probe (e.g., dropped the Option-parent gate
10977 /// on ONE side, crossed the derived-child arm on the OTHER), or
10978 /// (b) diverged the `From<EphemeralSpec>` lowering's
10979 /// `routing: e.routing` copy from byte-for-byte forwarding, fails
10980 /// HERE at the two-surface boundary.
10981 #[test]
10982 fn has_routing_form_matches_point_peer_through_lowered_routing() {
10983 for is_stable in [true, false] {
10984 let mut authored = empty_ephemeral();
10985 authored.routing = Some(routing_spec(is_stable));
10986 let lowered: ProcessSpec = authored.clone().into();
10987 for kind in RoutingForm::ALL {
10988 let ephemeral_answer = authored.has_routing_form(kind);
10989 let point_answer = lowered.routing.as_ref().is_some_and(|r| r.has_form(kind));
10990 assert_eq!(
10991 ephemeral_answer, point_answer,
10992 "two-surface routing-form parity drift: stable_name_claim={is_stable}, kind={kind:?}",
10993 );
10994 }
10995 }
10996 }
10997
10998 // ── EphemeralSpec::has_applicable_exports_at substrate pins ───────
10999 //
11000 // Fail-before-pass-after granularity: `has_applicable_exports_at`
11001 // did not exist pre-lift on `impl EphemeralSpec` — the peer
11002 // `EphemeralLifetime::has_applicable_exports` on the lowered
11003 // `ProcessSpec` surface routed through the compound
11004 // `.iter().any(|e| e.when.fires_on(phase))` chain inline, so the
11005 // sugar surface had no matching primitive to publish an
11006 // `exports-fire-on-<phase>` prefix family through the
11007 // `strip_and_classify_prefixed_kind` substrate. Post-lift the
11008 // compound-`(when, phase) → fires_on(phase)` probe body lives at
11009 // ONE slice-level substrate site (`ExportSpecSliceExt::has_applicable_at`),
11010 // this ephemeral surface routes through it directly, and the
11011 // point surface reaches the same primitive through
11012 // `spec.lifetime.resolved_ephemeral().is_some_and(|e|
11013 // e.exports.has_applicable_at(phase))`.
11014
11015 fn export_at(when: crate::export::ExportTrigger) -> ExportSpec {
11016 use crate::export::{ArtifactSource, ReceiptsSource, StdoutChannel, VectorChannel};
11017 ExportSpec {
11018 source: ArtifactSource {
11019 receipts: Some(ReceiptsSource::default()),
11020 ..ArtifactSource::default()
11021 },
11022 channel: VectorChannel {
11023 stdout: Some(StdoutChannel::default()),
11024 ..VectorChannel::default()
11025 },
11026 when,
11027 experiment_id_override: None,
11028 }
11029 }
11030
11031 /// EMPTY-EXPORTS pin — an ephemeral spec with an empty `exports`
11032 /// vec returns `false` for EVERY [`ProcessPhase`]. Sweep
11033 /// [`ProcessPhase::ALL`] so a new variant added without a matching
11034 /// arm in [`crate::export::ExportTrigger::fires_on`] surfaces at
11035 /// rustc's exhaustiveness gate on the `ALL` literal (arity forced
11036 /// by `[Self; 11]`) rather than as a silent false-positive at
11037 /// every downstream `exports-fire-on-<phase>` ephemeral require-tag
11038 /// callsite.
11039 #[test]
11040 fn has_applicable_exports_at_returns_false_on_empty_exports_for_every_phase() {
11041 let spec = empty_ephemeral();
11042 assert!(spec.exports.is_empty());
11043 for phase in ProcessPhase::ALL {
11044 assert!(
11045 !spec.has_applicable_exports_at(phase),
11046 "empty-exports ephemeral must return false for {phase:?}",
11047 );
11048 }
11049 }
11050
11051 /// PER-TRIGGER × PER-PHASE pin — an ephemeral spec with a single
11052 /// export answers `has_applicable_exports_at` identically to the
11053 /// [`crate::export::ExportTrigger::fires_on`] truth table on that
11054 /// (trigger, phase) pair, for every combination. Sweep the
11055 /// [`crate::export::ExportTrigger::ALL`] × [`ProcessPhase::ALL`]
11056 /// cross so a regression that (a) short-circuited to raw `when ==
11057 /// kind` equality, (b) missed `Always`'s dual-phase coverage, or
11058 /// (c) inverted a non-terminal phase to return `true` fails HERE
11059 /// at the substrate primitive rather than at each downstream
11060 /// `exports-fire-on-<phase>` classifier callsite.
11061 #[test]
11062 fn has_applicable_exports_at_matches_fires_on_truth_table_per_pair() {
11063 for trigger in crate::export::ExportTrigger::ALL {
11064 let mut spec = empty_ephemeral();
11065 spec.exports = vec![export_at(trigger)];
11066 for phase in ProcessPhase::ALL {
11067 let expected = trigger.fires_on(phase);
11068 assert_eq!(
11069 spec.has_applicable_exports_at(phase),
11070 expected,
11071 "ephemeral trigger={trigger:?} phase={phase:?} drifted from fires_on",
11072 );
11073 }
11074 }
11075 }
11076
11077 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
11078 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
11079 /// answer identically on every [`ProcessPhase`] × trigger
11080 /// combination. Locks the byte-for-byte parity between
11081 /// [`EphemeralSpec::has_applicable_exports_at`] (this new primitive)
11082 /// and the point surface's `spec.lifetime.resolved_ephemeral()
11083 /// .is_some_and(|e| e.exports.has_applicable_at(phase))` projection
11084 /// at the tatara-check dispatch site. A regression that (a)
11085 /// diverged the ephemeral probe from the lowered-lifetime probe,
11086 /// (b) diverged the `From<EphemeralSpec>` lowering's
11087 /// `exports: e.exports` copy from byte-for-byte forwarding, fails
11088 /// HERE at the two-surface boundary.
11089 #[test]
11090 fn has_applicable_exports_at_matches_point_peer_through_lowered_exports() {
11091 for trigger in crate::export::ExportTrigger::ALL {
11092 let mut authored = empty_ephemeral();
11093 authored.exports = vec![export_at(trigger)];
11094 let lowered: ProcessSpec = authored.clone().into();
11095 for phase in ProcessPhase::ALL {
11096 let ephemeral_answer = authored.has_applicable_exports_at(phase);
11097 let point_answer = lowered
11098 .lifetime
11099 .resolved_ephemeral()
11100 .is_some_and(|e| e.exports.has_applicable_at(phase));
11101 assert_eq!(
11102 ephemeral_answer, point_answer,
11103 "two-surface exports-fire-on parity drift: trigger={trigger:?}, phase={phase:?}",
11104 );
11105 }
11106 }
11107 }
11108
11109 /// SUBSTRATE-DELEGATION pin (EphemeralSpec saturation-predicate
11110 /// triad) — the three `is_*_kind_saturated` methods on
11111 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
11112 /// [`ConditionSliceExt::is_kind_saturated`] over the two
11113 /// `Vec<Condition>` slots (precondition + postcondition) and
11114 /// compose the union via `ConditionKind::ALL.iter().all(|k|
11115 /// has_condition_kind(*k))`. Two-surface parity pin against
11116 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on the
11117 /// point-domain [`ProcessSpec`] surface — the two struct-level
11118 /// saturation callers compose against the SAME slice-level
11119 /// substrate primitive so a regression at the per-slice `all`
11120 /// short-circuit fails at that primitive's tests rather than as
11121 /// silent drift at either sugar-surface arm.
11122 #[test]
11123 fn is_condition_kind_saturated_triad_delegates_to_slice_is_kind_saturated() {
11124 // Empty ephemeral spec — every arm returns false.
11125 let spec = empty_ephemeral();
11126 assert!(
11127 !spec.is_precondition_kind_saturated(),
11128 "empty ephemeral must return false on is_precondition_kind_saturated",
11129 );
11130 assert!(
11131 !spec.is_postcondition_kind_saturated(),
11132 "empty ephemeral must return false on is_postcondition_kind_saturated",
11133 );
11134 assert!(
11135 !spec.is_condition_kind_saturated(),
11136 "empty ephemeral must return false on is_condition_kind_saturated",
11137 );
11138 assert_eq!(
11139 spec.is_condition_kind_saturated(),
11140 spec.missing_condition_kinds().is_empty(),
11141 "empty is_condition_kind_saturated must equal missing_condition_kinds().is_empty()",
11142 );
11143
11144 // Single-populated per side — sweep ALL × ALL.
11145 for pre_kind in ConditionKind::ALL {
11146 for post_kind in ConditionKind::ALL {
11147 let mut spec = empty_ephemeral();
11148 spec.preconditions.push(cond(pre_kind));
11149 spec.postconditions.push(cond(post_kind));
11150 assert_eq!(
11151 spec.is_precondition_kind_saturated(),
11152 spec.preconditions.is_kind_saturated(),
11153 "EphemeralSpec::is_precondition_kind_saturated must delegate verbatim to \
11154 preconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
11155 );
11156 assert_eq!(
11157 spec.is_postcondition_kind_saturated(),
11158 spec.postconditions.is_kind_saturated(),
11159 "EphemeralSpec::is_postcondition_kind_saturated must delegate verbatim to \
11160 postconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
11161 );
11162 let expected_union = ConditionKind::ALL
11163 .iter()
11164 .all(|k| pre_kind == *k || post_kind == *k);
11165 assert_eq!(
11166 spec.is_condition_kind_saturated(),
11167 expected_union,
11168 "EphemeralSpec::is_condition_kind_saturated must equal all-ALL-covered-by-either-slice \
11169 for pre={pre_kind:?} post={post_kind:?}",
11170 );
11171
11172 // Two-surface parity: lowered ProcessSpec's Boundary
11173 // must agree bit-for-bit with the ephemeral sugar
11174 // triad on every arm.
11175 let lowered: ProcessSpec = spec.clone().into();
11176 assert_eq!(
11177 spec.is_precondition_kind_saturated(),
11178 lowered.boundary.is_precondition_kind_saturated(),
11179 "two-surface is_precondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
11180 );
11181 assert_eq!(
11182 spec.is_postcondition_kind_saturated(),
11183 lowered.boundary.is_postcondition_kind_saturated(),
11184 "two-surface is_postcondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
11185 );
11186 assert_eq!(
11187 spec.is_condition_kind_saturated(),
11188 lowered.boundary.is_condition_kind_saturated(),
11189 "two-surface is_condition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
11190 );
11191 }
11192 }
11193
11194 // Saturated ephemeral — both slices carry every ConditionKind,
11195 // every arm returns true.
11196 let mut spec = empty_ephemeral();
11197 for k in ConditionKind::ALL {
11198 spec.preconditions.push(cond(k));
11199 spec.postconditions.push(cond(k));
11200 }
11201 assert!(
11202 spec.is_precondition_kind_saturated(),
11203 "saturated ephemeral must return true on is_precondition_kind_saturated",
11204 );
11205 assert!(
11206 spec.is_postcondition_kind_saturated(),
11207 "saturated ephemeral must return true on is_postcondition_kind_saturated",
11208 );
11209 assert!(
11210 spec.is_condition_kind_saturated(),
11211 "saturated ephemeral must return true on is_condition_kind_saturated",
11212 );
11213 }
11214
11215 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
11216 /// triad) — the three `has_any_missing_*_condition_kind` methods
11217 /// on [`EphemeralSpec`] delegate to the slice-level substrate
11218 /// primitive
11219 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
11220 /// over the two `Vec<Condition>` slots (precondition +
11221 /// postcondition) and compose the union via
11222 /// `!self.is_condition_kind_saturated()`. Two-surface parity pin
11223 /// against
11224 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
11225 /// the point-domain [`ProcessSpec`] surface — the two struct-level
11226 /// at-least-one halfspace callers compose against the SAME slice-
11227 /// level substrate primitive so a regression at the per-slice
11228 /// `all` short-circuit under negation fails at that primitive's
11229 /// tests rather than as silent drift at either sugar-surface arm.
11230 #[test]
11231 fn has_any_missing_condition_kind_triad_delegates_to_slice_has_any_missing_kind() {
11232 // Empty ephemeral spec — every arm returns true (every kind is
11233 // missing from every slice + from the union).
11234 let spec = empty_ephemeral();
11235 assert!(
11236 spec.has_any_missing_precondition_kind(),
11237 "empty ephemeral must return true on has_any_missing_precondition_kind",
11238 );
11239 assert!(
11240 spec.has_any_missing_postcondition_kind(),
11241 "empty ephemeral must return true on has_any_missing_postcondition_kind",
11242 );
11243 assert!(
11244 spec.has_any_missing_condition_kind(),
11245 "empty ephemeral must return true on has_any_missing_condition_kind",
11246 );
11247 assert_eq!(
11248 spec.has_any_missing_condition_kind(),
11249 !spec.is_condition_kind_saturated(),
11250 "empty has_any_missing_condition_kind must equal !is_condition_kind_saturated()",
11251 );
11252
11253 // Single-populated per side — sweep ALL × ALL, then pin the
11254 // (pre, post, union) triad + two-surface parity against the
11255 // lowered ProcessSpec's Boundary.
11256 for pre_kind in ConditionKind::ALL {
11257 for post_kind in ConditionKind::ALL {
11258 let mut spec = empty_ephemeral();
11259 spec.preconditions.push(cond(pre_kind));
11260 spec.postconditions.push(cond(post_kind));
11261 assert_eq!(
11262 spec.has_any_missing_precondition_kind(),
11263 spec.preconditions.has_any_missing_kind(),
11264 "EphemeralSpec::has_any_missing_precondition_kind must delegate verbatim to \
11265 preconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11266 );
11267 assert_eq!(
11268 spec.has_any_missing_postcondition_kind(),
11269 spec.postconditions.has_any_missing_kind(),
11270 "EphemeralSpec::has_any_missing_postcondition_kind must delegate verbatim to \
11271 postconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11272 );
11273 let expected_union = !ConditionKind::ALL
11274 .iter()
11275 .all(|k| pre_kind == *k || post_kind == *k);
11276 assert_eq!(
11277 spec.has_any_missing_condition_kind(),
11278 expected_union,
11279 "EphemeralSpec::has_any_missing_condition_kind must equal \
11280 !all-ALL-covered-by-either-slice \
11281 for pre={pre_kind:?} post={post_kind:?}",
11282 );
11283
11284 // Two-surface parity: lowered ProcessSpec's Boundary
11285 // must agree bit-for-bit with the ephemeral sugar
11286 // triad on every arm.
11287 let lowered: ProcessSpec = spec.clone().into();
11288 assert_eq!(
11289 spec.has_any_missing_precondition_kind(),
11290 lowered.boundary.has_any_missing_precondition_kind(),
11291 "two-surface has_any_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11292 );
11293 assert_eq!(
11294 spec.has_any_missing_postcondition_kind(),
11295 lowered.boundary.has_any_missing_postcondition_kind(),
11296 "two-surface has_any_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11297 );
11298 assert_eq!(
11299 spec.has_any_missing_condition_kind(),
11300 lowered.boundary.has_any_missing_condition_kind(),
11301 "two-surface has_any_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11302 );
11303 }
11304 }
11305
11306 // Saturated ephemeral — both slices carry every ConditionKind,
11307 // every arm returns false.
11308 let mut spec = empty_ephemeral();
11309 for k in ConditionKind::ALL {
11310 spec.preconditions.push(cond(k));
11311 spec.postconditions.push(cond(k));
11312 }
11313 assert!(
11314 !spec.has_any_missing_precondition_kind(),
11315 "saturated ephemeral must return false on has_any_missing_precondition_kind",
11316 );
11317 assert!(
11318 !spec.has_any_missing_postcondition_kind(),
11319 "saturated ephemeral must return false on has_any_missing_postcondition_kind",
11320 );
11321 assert!(
11322 !spec.has_any_missing_condition_kind(),
11323 "saturated ephemeral must return false on has_any_missing_condition_kind",
11324 );
11325 }
11326
11327 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-mid-endpoint
11328 /// triad) — the three `has_unique_missing_*_condition_kind`
11329 /// methods on [`EphemeralSpec`] delegate to the slice-level
11330 /// substrate primitive
11331 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
11332 /// over the two `Vec<Condition>` slots (precondition +
11333 /// postcondition) and compose the union via a two-step-short-
11334 /// circuit walk over [`ConditionKind::ALL`] under negated
11335 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
11336 /// against
11337 /// [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
11338 /// on the point-domain [`ProcessSpec`] surface — the two struct-
11339 /// level near-saturation-endpoint callers compose against the
11340 /// SAME slice-level substrate primitive so a regression at the
11341 /// per-slice two-step short-circuit walk under negation fails at
11342 /// that primitive's tests rather than as silent drift at either
11343 /// sugar-surface arm.
11344 #[test]
11345 fn has_unique_missing_condition_kind_triad_delegates_to_slice_has_unique_missing_kind() {
11346 // Empty ephemeral spec — every arm returns false (all N
11347 // missing, not exactly 1) on any N ≥ 2 closed set.
11348 assert!(
11349 ConditionKind::ALL.len() >= 2,
11350 "test assumes ConditionKind::ALL has ≥ 2 variants",
11351 );
11352 let spec = empty_ephemeral();
11353 assert!(
11354 !spec.has_unique_missing_precondition_kind(),
11355 "empty ephemeral must return false on has_unique_missing_precondition_kind",
11356 );
11357 assert!(
11358 !spec.has_unique_missing_postcondition_kind(),
11359 "empty ephemeral must return false on has_unique_missing_postcondition_kind",
11360 );
11361 assert!(
11362 !spec.has_unique_missing_condition_kind(),
11363 "empty ephemeral must return false on has_unique_missing_condition_kind",
11364 );
11365 assert_eq!(
11366 spec.has_unique_missing_condition_kind(),
11367 spec.missing_condition_kind_count() == 1,
11368 "empty has_unique_missing_condition_kind must equal (missing_condition_kind_count() == 1)",
11369 );
11370
11371 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
11372 // sets. Every per-slice arm returns false; the union returns
11373 // true iff exactly one ALL variant is uncovered.
11374 if ConditionKind::ALL.len() >= 3 {
11375 for pre_kind in ConditionKind::ALL {
11376 for post_kind in ConditionKind::ALL {
11377 let mut spec = empty_ephemeral();
11378 spec.preconditions.push(cond(pre_kind));
11379 spec.postconditions.push(cond(post_kind));
11380 assert_eq!(
11381 spec.has_unique_missing_precondition_kind(),
11382 spec.preconditions.has_unique_missing_kind(),
11383 "EphemeralSpec::has_unique_missing_precondition_kind must delegate verbatim to \
11384 preconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11385 );
11386 assert_eq!(
11387 spec.has_unique_missing_postcondition_kind(),
11388 spec.postconditions.has_unique_missing_kind(),
11389 "EphemeralSpec::has_unique_missing_postcondition_kind must delegate verbatim to \
11390 postconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
11391 );
11392 let uncovered = ConditionKind::ALL
11393 .into_iter()
11394 .filter(|k| *k != pre_kind && *k != post_kind)
11395 .count();
11396 let expected_union = uncovered == 1;
11397 assert_eq!(
11398 spec.has_unique_missing_condition_kind(),
11399 expected_union,
11400 "EphemeralSpec::has_unique_missing_condition_kind must equal \
11401 (uncovered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
11402 );
11403
11404 // Two-surface parity: lowered ProcessSpec's
11405 // Boundary must agree bit-for-bit with the
11406 // ephemeral sugar triad on every arm.
11407 let lowered: ProcessSpec = spec.clone().into();
11408 assert_eq!(
11409 spec.has_unique_missing_precondition_kind(),
11410 lowered.boundary.has_unique_missing_precondition_kind(),
11411 "two-surface has_unique_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11412 );
11413 assert_eq!(
11414 spec.has_unique_missing_postcondition_kind(),
11415 lowered.boundary.has_unique_missing_postcondition_kind(),
11416 "two-surface has_unique_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11417 );
11418 assert_eq!(
11419 spec.has_unique_missing_condition_kind(),
11420 lowered.boundary.has_unique_missing_condition_kind(),
11421 "two-surface has_unique_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
11422 );
11423 }
11424 }
11425 }
11426
11427 // Near-saturation-endpoint per side — each slice carries
11428 // every ConditionKind except one. Every per-slice arm returns
11429 // true; the union returns true iff BOTH slices omit the SAME
11430 // kind.
11431 for pre_omit in ConditionKind::ALL {
11432 for post_omit in ConditionKind::ALL {
11433 let mut spec = empty_ephemeral();
11434 for k in ConditionKind::ALL {
11435 if k != pre_omit {
11436 spec.preconditions.push(cond(k));
11437 }
11438 if k != post_omit {
11439 spec.postconditions.push(cond(k));
11440 }
11441 }
11442 assert!(
11443 spec.has_unique_missing_precondition_kind(),
11444 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_unique_missing_precondition_kind",
11445 );
11446 assert!(
11447 spec.has_unique_missing_postcondition_kind(),
11448 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_unique_missing_postcondition_kind",
11449 );
11450 let expected_union = pre_omit == post_omit;
11451 assert_eq!(
11452 spec.has_unique_missing_condition_kind(),
11453 expected_union,
11454 "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:?}",
11455 );
11456
11457 // Two-surface parity for near-saturation arm.
11458 let lowered: ProcessSpec = spec.clone().into();
11459 assert_eq!(
11460 spec.has_unique_missing_precondition_kind(),
11461 lowered.boundary.has_unique_missing_precondition_kind(),
11462 "two-surface has_unique_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11463 );
11464 assert_eq!(
11465 spec.has_unique_missing_postcondition_kind(),
11466 lowered.boundary.has_unique_missing_postcondition_kind(),
11467 "two-surface has_unique_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11468 );
11469 assert_eq!(
11470 spec.has_unique_missing_condition_kind(),
11471 lowered.boundary.has_unique_missing_condition_kind(),
11472 "two-surface has_unique_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
11473 );
11474 }
11475 }
11476
11477 // Saturated ephemeral — every arm returns false (0 missing,
11478 // not exactly 1).
11479 let mut spec = empty_ephemeral();
11480 for k in ConditionKind::ALL {
11481 spec.preconditions.push(cond(k));
11482 spec.postconditions.push(cond(k));
11483 }
11484 assert!(
11485 !spec.has_unique_missing_precondition_kind(),
11486 "saturated ephemeral must return false on has_unique_missing_precondition_kind",
11487 );
11488 assert!(
11489 !spec.has_unique_missing_postcondition_kind(),
11490 "saturated ephemeral must return false on has_unique_missing_postcondition_kind",
11491 );
11492 assert!(
11493 !spec.has_unique_missing_condition_kind(),
11494 "saturated ephemeral must return false on has_unique_missing_condition_kind",
11495 );
11496 }
11497
11498 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind-complement
11499 /// triad) — the three `lacks_*_condition_kind` methods on
11500 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
11501 /// [`ConditionSliceExt::lacks_kind`] over the two `Vec<Condition>`
11502 /// slots (precondition + postcondition) and compose the union via
11503 /// `!self.has_condition_kind(kind)`. Two-surface parity pin against
11504 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
11505 /// point-domain [`ProcessSpec`] surface — the two struct-level
11506 /// per-kind-complement callers compose against the SAME slice-level
11507 /// substrate primitive so a regression at the per-slice negation
11508 /// fails at that primitive's tests rather than as silent drift at
11509 /// either sugar-surface arm. Also pins the composition laws
11510 /// `lacks_*_condition_kind(k) == !has_*_condition_kind(k)` at each
11511 /// arm AND `lacks_condition_kind(k) == lacks_precondition_kind(k) &&
11512 /// lacks_postcondition_kind(k)` (the union AND-composition dual of
11513 /// `has`'s OR-composition).
11514 #[test]
11515 fn lacks_condition_kind_triad_delegates_to_slice_lacks_kind() {
11516 // Empty ephemeral spec — every arm returns true on every kind.
11517 let spec = empty_ephemeral();
11518 for kind in ConditionKind::ALL {
11519 assert!(
11520 spec.lacks_precondition_kind(kind),
11521 "empty ephemeral must return true on lacks_precondition_kind for {kind:?}",
11522 );
11523 assert!(
11524 spec.lacks_postcondition_kind(kind),
11525 "empty ephemeral must return true on lacks_postcondition_kind for {kind:?}",
11526 );
11527 assert!(
11528 spec.lacks_condition_kind(kind),
11529 "empty ephemeral must return true on lacks_condition_kind for {kind:?}",
11530 );
11531 assert_eq!(
11532 spec.lacks_condition_kind(kind),
11533 !spec.has_condition_kind(kind),
11534 "empty lacks_condition_kind must equal !has_condition_kind for {kind:?}",
11535 );
11536 }
11537
11538 // Single-populated per side — sweep ALL × ALL, then probe every
11539 // ConditionKind on the (pre, post, union) triad + two-surface
11540 // parity against the lowered ProcessSpec's Boundary.
11541 for pre_kind in ConditionKind::ALL {
11542 for post_kind in ConditionKind::ALL {
11543 let mut spec = empty_ephemeral();
11544 spec.preconditions.push(cond(pre_kind));
11545 spec.postconditions.push(cond(post_kind));
11546 let lowered: ProcessSpec = spec.clone().into();
11547 for probe in ConditionKind::ALL {
11548 assert_eq!(
11549 spec.lacks_precondition_kind(probe),
11550 spec.preconditions.lacks_kind(probe),
11551 "EphemeralSpec::lacks_precondition_kind must delegate verbatim to preconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11552 );
11553 assert_eq!(
11554 spec.lacks_postcondition_kind(probe),
11555 spec.postconditions.lacks_kind(probe),
11556 "EphemeralSpec::lacks_postcondition_kind must delegate verbatim to postconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11557 );
11558 let expected_union = pre_kind != probe && post_kind != probe;
11559 assert_eq!(
11560 spec.lacks_condition_kind(probe),
11561 expected_union,
11562 "EphemeralSpec::lacks_condition_kind must equal all-ALL-absent-in-both-slices for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11563 );
11564 assert_eq!(
11565 spec.lacks_condition_kind(probe),
11566 !spec.has_condition_kind(probe),
11567 "EphemeralSpec::lacks_condition_kind must equal !has_condition_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11568 );
11569 assert_eq!(
11570 spec.lacks_condition_kind(probe),
11571 spec.lacks_precondition_kind(probe)
11572 && spec.lacks_postcondition_kind(probe),
11573 "EphemeralSpec::lacks_condition_kind must equal AND-of-half-slice-arms for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11574 );
11575
11576 // Two-surface parity: lowered ProcessSpec's Boundary
11577 // must agree bit-for-bit with the ephemeral sugar
11578 // triad on every arm.
11579 assert_eq!(
11580 spec.lacks_precondition_kind(probe),
11581 lowered.boundary.lacks_precondition_kind(probe),
11582 "two-surface lacks_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11583 );
11584 assert_eq!(
11585 spec.lacks_postcondition_kind(probe),
11586 lowered.boundary.lacks_postcondition_kind(probe),
11587 "two-surface lacks_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11588 );
11589 assert_eq!(
11590 spec.lacks_condition_kind(probe),
11591 lowered.boundary.lacks_condition_kind(probe),
11592 "two-surface lacks_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
11593 );
11594 }
11595 }
11596 }
11597
11598 // Saturated ephemeral — both slices carry every ConditionKind,
11599 // every arm returns false on every kind.
11600 let mut spec = empty_ephemeral();
11601 for k in ConditionKind::ALL {
11602 spec.preconditions.push(cond(k));
11603 spec.postconditions.push(cond(k));
11604 }
11605 for kind in ConditionKind::ALL {
11606 assert!(
11607 !spec.lacks_precondition_kind(kind),
11608 "saturated ephemeral must return false on lacks_precondition_kind for {kind:?}",
11609 );
11610 assert!(
11611 !spec.lacks_postcondition_kind(kind),
11612 "saturated ephemeral must return false on lacks_postcondition_kind for {kind:?}",
11613 );
11614 assert!(
11615 !spec.lacks_condition_kind(kind),
11616 "saturated ephemeral must return false on lacks_condition_kind for {kind:?}",
11617 );
11618 }
11619 }
11620}