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 this ephemeral spec's stored [`TeardownPolicy`] equals
1287 /// `kind` — the substrate primitive that owns the
1288 /// (`&EphemeralSpec`, [`TeardownPolicy`]) → `bool` presence-probe
1289 /// shape on the sugar-surface type.
1290 ///
1291 /// # Peer to [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
1292 ///
1293 /// [`EphemeralLifetime::has_teardown_policy`] carries the same
1294 /// `(&self, TeardownPolicy) -> bool` signature on the point-surface
1295 /// carrier ([`ProcessSpec`]'s nested [`crate::lifetime::Lifetime`]
1296 /// slot reached through
1297 /// [`crate::lifetime::Lifetime::resolved_ephemeral`]); this peer
1298 /// composes byte-identical `==` semantics on
1299 /// [`EphemeralSpec`]'s direct `teardown: TeardownPolicy` scalar
1300 /// slot, so both surfaces' `teardown-policy-<kind>` require-tag
1301 /// families ([`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
1302 /// on the point surface, this peer on the ephemeral surface) route
1303 /// through the SAME scalar `==` shape. A future normalization at
1304 /// the probe shape (a widened return carrying a `TerminatePolicy`
1305 /// disambiguator, a debug-build assertion on operator-set vs
1306 /// defaulted overrides, a fleet-wide warn on `Never` combined with
1307 /// short TTLs) lands at ONE site per surface and every downstream
1308 /// `teardown-policy-<kind>` require-tag family + closed-set audit
1309 /// dispatcher picks it up mechanically.
1310 ///
1311 /// # Semantics — VARIANT match, not POPULATED slot
1312 ///
1313 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
1314 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
1315 /// absent state to detect. `has_teardown_policy(kind)` returns
1316 /// `true` iff `self.teardown == kind`. On a hand-authored
1317 /// [`EphemeralSpec`] that omits `:teardown` from the
1318 /// `(defephemeral …)` form (or a Rust builder that reaches
1319 /// [`TeardownPolicy::default`]) the probe returns `true` for
1320 /// [`TeardownPolicy::Always`] and `false` for every other variant
1321 /// — distinct from the Option-slot axis where a default carrier
1322 /// returns `false` for EVERY kind. An operator who left
1323 /// `:teardown` at the substrate default IS configured for
1324 /// `Always`, and a `:requires (teardown-policy-Always)` check
1325 /// should pass; only an operator who deliberately overrode the
1326 /// policy to `OnAttested` / `OnFailed` / `Never` fails the tag on
1327 /// this axis.
1328 ///
1329 /// # Corner — (required-scalar-child)
1330 ///
1331 /// Fresh corner on the ephemeral surface's presence-probe algebra:
1332 /// [`EphemeralSpec`] has no Option-parent hop between the sugar
1333 /// struct and the `teardown` scalar (the point surface reaches
1334 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
1335 /// through the Option-parent `resolved_ephemeral()` gate), so the
1336 /// probe body is a bare scalar `==` on a required field. Distinct
1337 /// from [`Self::has_condition_kind`] on this same surface, which
1338 /// walks a `Vec<Condition>` slice-child.
1339 ///
1340 /// # Compounding
1341 ///
1342 /// The ephemeral require-tag classifier composes this primitive
1343 /// with the closed-set `FromStr` autoderived on [`TeardownPolicy`]
1344 /// through the `strip_and_classify_prefixed_kind` substrate to
1345 /// publish a `teardown-policy-<kind>` prefix family byte-for-byte
1346 /// symmetrical with the point surface's family via
1347 /// [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]. A
1348 /// future fifth [`TeardownPolicy`] variant added to `ALL` (a
1349 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
1350 /// reaches BOTH surfaces' `teardown-policy-<kind>` prefix families
1351 /// through the SAME closed-set walk with no per-caller edit — the
1352 /// two-surface symmetry means adding a variant on the closed set
1353 /// publishes it in lockstep across every downstream consumer.
1354 ///
1355 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1356 /// preserves proofs — the scalar-carrier presence-probe body lives
1357 /// at ONE substrate site per surface so every downstream
1358 /// (`teardown-policy-<kind>` require-tag families on both surfaces
1359 /// in tatara-check, closed-set audit dispatchers, future variant
1360 /// additions on [`TeardownPolicy`]) binds through the SAME
1361 /// `has(kind)` shape rather than restating the `<eph>.teardown ==
1362 /// kind` closure body at each call site). THEORY.md §VI.1
1363 /// (generation over composition — a future variant lands at ONE
1364 /// `ALL` entry + one `as_str` arm on the closed set and the probe
1365 /// picks it up mechanically without further per-consumer edits).
1366 #[must_use]
1367 pub fn has_teardown_policy(&self, kind: TeardownPolicy) -> bool {
1368 self.teardown == kind
1369 }
1370
1371 /// Derived-bool-predicate presence probe on the stored
1372 /// [`Self::teardown`] slot — `true` iff this ephemeral sugar's
1373 /// [`TeardownPolicy`] would auto-SIGTERM the Process on the
1374 /// queried [`ProcessPhase`] transition (as read through
1375 /// [`TeardownPolicy::should_teardown_on`]).
1376 ///
1377 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
1378 ///
1379 /// Same shape, same axis, one refinement lower: the point-surface
1380 /// peer on [`crate::lifetime::EphemeralLifetime`] composes the SAME
1381 /// [`TeardownPolicy::should_teardown_on`] predicate against the
1382 /// SAME stored `teardown_policy` slot; this method composes the
1383 /// same predicate against the sugar surface's flattened
1384 /// [`Self::teardown`] slot. Both bodies delegate to the ONE
1385 /// substrate owner [`TeardownPolicy::should_teardown_on`], so a
1386 /// regression at the (policy, phase) → bool truth table surfaces
1387 /// at THAT primitive's tests rather than as silent drift at
1388 /// either struct-level caller.
1389 ///
1390 /// # Corner — (required-scalar-parent × derived-bool-predicate-child)
1391 ///
1392 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
1393 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
1394 /// Option-parent hop between the sugar struct and the `teardown`
1395 /// scalar (the point surface reaches
1396 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
1397 /// through the Option-parent `resolved_ephemeral()` gate). The
1398 /// probe body is a bare predicate application on a required
1399 /// field. Distinct from [`Self::has_teardown_policy`] on this
1400 /// same surface, which reads the raw stored variant for equality
1401 /// (`self.teardown == kind`) rather than the derived firing-arm
1402 /// predicate against a [`ProcessPhase`] argument.
1403 ///
1404 /// # Compounding
1405 ///
1406 /// The ephemeral require-tag classifier composes this primitive
1407 /// with the closed-set [`crate::phase::ProcessPhase`]'s
1408 /// autoderived `FromStr` through the
1409 /// `strip_and_classify_prefixed_kind` substrate to publish a
1410 /// `teardown-fires-on-<phase>` prefix family byte-for-byte
1411 /// symmetrical with the point surface's family via
1412 /// [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`].
1413 /// A future fifth [`TeardownPolicy`] variant added to `ALL` (a
1414 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
1415 /// reaches BOTH surfaces' `teardown-fires-on-<phase>` prefix
1416 /// families through the SAME
1417 /// [`TeardownPolicy::should_teardown_on`] match with no per-
1418 /// caller edit — the two-surface symmetry means adding a variant
1419 /// on the closed set publishes it in lockstep across every
1420 /// downstream consumer.
1421 ///
1422 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1423 /// preserves proofs — the derived-bool-predicate presence-probe
1424 /// body lives at ONE substrate site per surface, both composing
1425 /// the SAME [`TeardownPolicy::should_teardown_on`] projection, so
1426 /// every downstream (`teardown-fires-on-<phase>` require-tag
1427 /// families on both surfaces in tatara-check, closed-set audit
1428 /// dispatchers, future variant additions on either
1429 /// [`TeardownPolicy`] or [`crate::phase::ProcessPhase`]) binds
1430 /// through the SAME `has_teardown_firing_on(phase)` shape rather
1431 /// than restating the `<eph>.teardown.should_teardown_on(phase)`
1432 /// closure body at each call site). THEORY.md §VI.1 (generation
1433 /// over composition — a future variant lands at ONE `ALL` entry +
1434 /// one `as_str` arm + one `should_teardown_on` arm on the closed
1435 /// set and the probe picks it up mechanically without further
1436 /// per-consumer edits).
1437 #[must_use]
1438 pub const fn has_teardown_firing_on(&self, phase: ProcessPhase) -> bool {
1439 self.teardown.should_teardown_on(phase)
1440 }
1441
1442 /// Resolve the operator-authored [`Self::classification`] slot to
1443 /// the concrete [`Classification`] the point surface sees, filling
1444 /// `None` through the same [`default_ephemeral_class`] baseline the
1445 /// `From<EphemeralSpec> for ProcessSpec` lowering uses when the
1446 /// operator omits `:classification` from the `(defephemeral …)`
1447 /// form. Returns [`Cow::Borrowed`] on the populated arm (zero
1448 /// allocation), else [`Cow::Owned`] with the workspace-baseline
1449 /// `(Gate, Compute, Bounded, Monotone, Internal)` value the sibling
1450 /// primitive [`Classification::gate_compute`] owns.
1451 ///
1452 /// # ONE substrate primitive for `Option<Classification>` resolution
1453 ///
1454 /// This is the ONE `EphemeralSpec`-inherent primitive that owns the
1455 /// `Option<Classification>` → resolved-[`Classification`] walk.
1456 /// Every downstream classification-axis presence probe on the
1457 /// [`EphemeralSpec`] surface ([`Self::has_point_type`],
1458 /// [`Self::has_substrate`], [`Self::has_calm`],
1459 /// [`Self::has_data_classification`], [`Self::has_horizon_kind`],
1460 /// [`Self::has_optimization_direction`], [`Self::has_input_arity`],
1461 /// [`Self::has_output_arity`]) routes through THIS
1462 /// primitive so the "`None` fills through
1463 /// [`default_ephemeral_class`]" resolution lives at ONE site rather
1464 /// than being restated in each per-axis probe body. A future
1465 /// regression on the fill-through (a shift from the `(Gate,
1466 /// Compute, …)` baseline to a different `default_ephemeral_class`
1467 /// body, a shift from the `Option`-carrier shape to a
1468 /// serde-defaulted required-field carrier, an eventual audit hook
1469 /// naming the resolved-vs-authored provenance) lands at ONE site
1470 /// and every downstream axis-probe on the ephemeral surface picks
1471 /// it up mechanically.
1472 ///
1473 /// # Sibling to the `From<EphemeralSpec>` lowering
1474 ///
1475 /// The lowering `From<EphemeralSpec> for ProcessSpec` fills
1476 /// [`ProcessSpec::classification`] through the SAME
1477 /// `.unwrap_or_else(default_ephemeral_class)` walk that this
1478 /// primitive owns on the borrow-friendly `Cow` return. Both sites
1479 /// resolve the same operator-authored slot through the same default
1480 /// so a future two-surface parity contract on the classification
1481 /// axes (`point-type-<kind>` on both surfaces, `substrate-<kind>`
1482 /// on both surfaces, …) reads identically through the sibling
1483 /// point-surface probe [`Classification::has_<axis>`] on the
1484 /// lowered `ProcessSpec` and through THIS primitive on the same
1485 /// authored [`EphemeralSpec`].
1486 ///
1487 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1488 /// preserves proofs; the `Option<Classification>` resolution body
1489 /// lives at ONE substrate primitive on the ephemeral surface so
1490 /// every downstream classification-axis probe binds through the
1491 /// SAME `resolved_classification()` shape rather than restating
1492 /// the `self.classification.as_ref().unwrap_or(&default_…)`
1493 /// closure body at each callsite. THEORY.md §VI.1 — generation
1494 /// over composition; a future classification-axis peer
1495 /// (`has_substrate`, `has_calm`, …) lands as ONE inherent method
1496 /// that delegates through the resolver's `has_<axis>(kind)` call
1497 /// on the sibling [`Classification`] closed-set primitive with no
1498 /// per-axis restatement of the fill-through logic.
1499 #[must_use]
1500 pub fn resolved_classification(&self) -> Cow<'_, Classification> {
1501 match &self.classification {
1502 Some(c) => Cow::Borrowed(c),
1503 None => Cow::Owned(default_ephemeral_class()),
1504 }
1505 }
1506
1507 /// Overlay a single [`ClassificationAxis`] variant onto this
1508 /// ephemeral spec's authored [`Self::classification`] slot, filling
1509 /// `None` through [`Classification::gate_compute`] before the
1510 /// overlay so the resulting slot carries `Some(_)` regardless of
1511 /// the pre-call state. Fluent chaining primitive: the peer of
1512 /// [`ProcessSpec::gate_compute_with_axis`] (fresh-spec × axis
1513 /// overlay) and [`Classification::with_axis`] (arbitrary-base ×
1514 /// axis overlay) on the ephemeral sugar surface.
1515 ///
1516 /// # Substrate ergonomics
1517 ///
1518 /// Pre-lift the four-line shape `let mut classification =
1519 /// Classification::gate_compute(); classification.<axis> =
1520 /// populated; let spec = EphemeralSpec { classification:
1521 /// Some(classification), ..ephemeral_fixture() };` (and its newer
1522 /// three-line peer `let classification =
1523 /// Classification::gate_compute_with_axis(populated); let spec =
1524 /// EphemeralSpec { classification: Some(classification),
1525 /// ..ephemeral_fixture() };`) recurred at THIRTY-SIX hand-authored
1526 /// callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger
1527 /// inside `tatara-reconciler::bin::tatara-check`'s
1528 /// `evaluate_ephemeral_require_tag_*` classifier-facing test
1529 /// module. Post-lift each callsite reads
1530 /// `let spec = ephemeral_fixture().with_classification_axis(populated);`
1531 /// — one line, one immutable binding, and every per-axis loop
1532 /// dispatches its per-iteration axis mutation through the SAME
1533 /// [`ClassificationAxis::overlay`] trait rather than by directly
1534 /// poking a `classification.<axis>` field or restating the
1535 /// `Some(_)` wrap.
1536 ///
1537 /// # Fluent chaining semantics
1538 ///
1539 /// * `EphemeralSpec { classification: None, .. }
1540 /// .with_classification_axis(axis)` produces
1541 /// `EphemeralSpec { classification:
1542 /// Some(Classification::gate_compute_with_axis(axis)), .. }` —
1543 /// the `None`-arm short-circuit fills through
1544 /// [`Classification::gate_compute`] identically to the sibling
1545 /// [`Self::resolved_classification`] resolver on the read side.
1546 /// * `EphemeralSpec { classification: Some(prior), .. }
1547 /// .with_classification_axis(axis)` produces
1548 /// `EphemeralSpec { classification: Some(prior.with_axis(axis)),
1549 /// .. }` — the axis overlay composes onto the existing carrier
1550 /// via [`ClassificationAxis::overlay`], preserving every other
1551 /// axis slot on `prior`. Chained calls
1552 /// `.with_classification_axis(a).with_classification_axis(b)`
1553 /// compose arbitrary N-axis conjunctions on the ephemeral
1554 /// sugar surface with the same order-independence guarantee
1555 /// [`Classification::with_axis`] carries on distinct-slot axes.
1556 ///
1557 /// # Sibling to [`ProcessSpec::gate_compute_with_axis`]
1558 ///
1559 /// Same (spec-carrier × axis) shape, one refinement lower on
1560 /// the composition-depth axis: `ProcessSpec::gate_compute_with_axis`
1561 /// owns the (fresh-`gate_compute_defaults`-spec × axis-overlay)
1562 /// construction on the point-surface carrier;
1563 /// [`Self::with_classification_axis`] owns the
1564 /// (arbitrary-`EphemeralSpec` × axis-overlay-onto-authored-classification)
1565 /// construction on the ephemeral sugar-surface carrier. Both
1566 /// primitives compose through the SAME
1567 /// [`ClassificationAxis::overlay`] trait so a regression on any
1568 /// axis's overlay surfaces at both composer owners' pin sets
1569 /// simultaneously.
1570 ///
1571 /// # Compounding
1572 ///
1573 /// A future SIXTH classification axis lands as ONE peer
1574 /// `impl ClassificationAxis` — every ephemeral-surface fixture
1575 /// that binds through this primitive picks up the sixth axis
1576 /// mechanically without a `classification.<new-axis> = value;`
1577 /// restatement per site. A future audit dispatcher walking the
1578 /// (ephemeral-surface × axis-loop) shape (per-axis matrix
1579 /// generator, closed-set-sweep sagas, per-axis-XOR-partition-
1580 /// witness synthesis on the ephemeral side) binds through the
1581 /// SAME composer regardless of which axis it targets. Directly
1582 /// benefits the P1 caixa-tatara renderer target
1583 /// (`(defaplicacao …)` → `Process` mechanical lowering test
1584 /// fixtures that construct authored classifications through the
1585 /// ephemeral sugar surface) and future ephemeral-surface XOR-
1586 /// partition landmark tests peer to the point-surface pins in
1587 /// `tatara-check.rs`.
1588 ///
1589 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1590 /// preserves proofs; the [`ClassificationAxis::overlay`] trait
1591 /// owns the axis-dispatch proof at ONE site and this primitive
1592 /// extends the ONE-site guarantee to the (ephemeral-spec ×
1593 /// authored-classification × axis-overlay) construction shape.
1594 /// THEORY.md §VI.1 — generation over composition; the 3-to-4-line
1595 /// hand-authored classification-then-wrap shape recurred at ≥ 36
1596 /// hand-authored callsites past the ★★ PRIME-DIRECTIVE ≥ 2
1597 /// duplication threshold and is lifted onto ONE substrate owner
1598 /// here.
1599 #[must_use]
1600 pub fn with_classification_axis<A: ClassificationAxis>(mut self, axis: A) -> Self {
1601 let mut c = self
1602 .classification
1603 .take()
1604 .unwrap_or_else(Classification::gate_compute);
1605 axis.overlay(&mut c);
1606 self.classification = Some(c);
1607 self
1608 }
1609
1610 /// True iff the resolved [`Classification`] carries the given
1611 /// [`ConvergencePointType`] on its `point_type` slot — byte-for-
1612 /// byte peer of [`Classification::has_point_type`] wrapped through
1613 /// the [`Self::resolved_classification`] resolver so an
1614 /// operator-omitted `:classification` slot reads as the
1615 /// [`default_ephemeral_class`] baseline the sibling
1616 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
1617 ///
1618 /// # Two-surface parity contract
1619 ///
1620 /// A given [`EphemeralSpec`] classifies identically through this
1621 /// primitive AND through
1622 /// `<eph.clone().into::<ProcessSpec>>().classification.has_point_type(kind)`
1623 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
1624 /// resolver on this side and the `.unwrap_or_else(...)` fill on
1625 /// the lowering side both dereference the same
1626 /// `default_ephemeral_class()` value on `None` and the same
1627 /// authored value on `Some(_)`. This means the ephemeral-surface
1628 /// `point-type-<kind>` `:requires` family in
1629 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
1630 /// truth on the SAME authored spec as the point-surface family
1631 /// on the mechanically-lowered `ProcessSpec`.
1632 ///
1633 /// # Sibling to the seven other classification axes
1634 ///
1635 /// FIRST classification-axis peer on the [`EphemeralSpec`]
1636 /// surface. Six future sibling axes on the SAME `Cow`-resolver
1637 /// carrier ([`Self::has_substrate`] opened the SECOND,
1638 /// [`Self::has_calm`] the THIRD,
1639 /// [`Self::has_data_classification`] the FOURTH,
1640 /// [`Self::has_horizon_kind`] the FIFTH,
1641 /// [`Self::has_optimization_direction`] the SIXTH; then
1642 /// `has_input_arity`, `has_output_arity`) land as one-line
1643 /// wrappers around the SAME resolver + the sibling
1644 /// [`Classification`] closed-set primitive, so a future variant
1645 /// added to [`ConvergencePointType`] (or any of the seven other
1646 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
1647 /// families through the SAME closed-set walk with no per-caller
1648 /// edit.
1649 ///
1650 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1651 /// preserves proofs; the classification-axis presence-probe body
1652 /// composes ONE resolver primitive
1653 /// ([`Self::resolved_classification`]) with ONE closed-set
1654 /// primitive ([`Classification::has_point_type`]) so every
1655 /// downstream (`point-type-<kind>` require-tag families on both
1656 /// surfaces in tatara-check, closed-set audit dispatchers, future
1657 /// variant additions on [`ConvergencePointType`]) binds through
1658 /// the SAME `has(kind)` shape rather than restating either the
1659 /// resolver walk or the closed-set equality at the callsite.
1660 #[must_use]
1661 pub fn has_point_type(&self, kind: ConvergencePointType) -> bool {
1662 self.resolved_classification().has_point_type(kind)
1663 }
1664
1665 /// True iff the resolved [`Classification`] carries the given
1666 /// [`SubstrateType`] on its `substrate` slot — byte-for-byte peer
1667 /// of [`Classification::has_substrate`] wrapped through the
1668 /// [`Self::resolved_classification`] resolver so an operator-
1669 /// omitted `:classification` slot reads as the
1670 /// [`default_ephemeral_class`] baseline the sibling
1671 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
1672 ///
1673 /// # Two-surface parity contract
1674 ///
1675 /// A given [`EphemeralSpec`] classifies identically through this
1676 /// primitive AND through
1677 /// `<eph.clone().into::<ProcessSpec>>().classification.has_substrate(kind)`
1678 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
1679 /// resolver on this side and the `.unwrap_or_else(...)` fill on
1680 /// the lowering side both dereference the same
1681 /// `default_ephemeral_class()` value on `None` and the same
1682 /// authored value on `Some(_)`. This means the ephemeral-surface
1683 /// `substrate-<kind>` `:requires` family in
1684 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
1685 /// truth on the SAME authored spec as the point-surface family
1686 /// on the mechanically-lowered `ProcessSpec`.
1687 ///
1688 /// # SECOND classification-axis peer on the ephemeral surface
1689 ///
1690 /// Peer of [`Self::has_point_type`] — both route through the SAME
1691 /// [`Self::resolved_classification`] resolver, so the operator-
1692 /// omitted `:classification` slot's fill-through logic lives at
1693 /// ONE substrate primitive rather than being restated in each
1694 /// per-axis probe body. Five future sibling axes on the SAME
1695 /// `Cow`-resolver carrier ([`Self::has_calm`] opened the THIRD,
1696 /// [`Self::has_data_classification`] the FOURTH,
1697 /// [`Self::has_horizon_kind`] the FIFTH,
1698 /// [`Self::has_optimization_direction`] the SIXTH; then
1699 /// `has_input_arity`, `has_output_arity`) land as one-line
1700 /// wrappers around the SAME resolver + the sibling
1701 /// [`Classification`] closed-set primitive, so a future variant
1702 /// added to [`SubstrateType`] (or any of the six other closed
1703 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
1704 /// through the SAME closed-set walk with no per-caller edit.
1705 ///
1706 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1707 /// preserves proofs; the classification-axis presence-probe body
1708 /// composes ONE resolver primitive
1709 /// ([`Self::resolved_classification`]) with ONE closed-set
1710 /// primitive ([`Classification::has_substrate`]) so every
1711 /// downstream (`substrate-<kind>` require-tag families on both
1712 /// surfaces in tatara-check, closed-set audit dispatchers, future
1713 /// variant additions on [`SubstrateType`]) binds through the
1714 /// SAME `has(kind)` shape rather than restating either the
1715 /// resolver walk or the closed-set equality at the callsite.
1716 #[must_use]
1717 pub fn has_substrate(&self, kind: SubstrateType) -> bool {
1718 self.resolved_classification().has_substrate(kind)
1719 }
1720
1721 /// True iff the resolved [`Classification`] carries the given
1722 /// [`CalmClassification`] on its `calm` slot — byte-for-byte peer
1723 /// of [`Classification::has_calm`] wrapped through the
1724 /// [`Self::resolved_classification`] resolver so an operator-
1725 /// omitted `:classification` slot reads as the
1726 /// [`default_ephemeral_class`] baseline the sibling
1727 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
1728 ///
1729 /// # Two-surface parity contract
1730 ///
1731 /// A given [`EphemeralSpec`] classifies identically through this
1732 /// primitive AND through
1733 /// `<eph.clone().into::<ProcessSpec>>().classification.has_calm(kind)`
1734 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
1735 /// resolver on this side and the `.unwrap_or_else(...)` fill on
1736 /// the lowering side both dereference the same
1737 /// `default_ephemeral_class()` value on `None` and the same
1738 /// authored value on `Some(_)`. This means the ephemeral-surface
1739 /// `calm-<kind>` `:requires` family in
1740 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
1741 /// truth on the SAME authored spec as the point-surface family
1742 /// on the mechanically-lowered `ProcessSpec`.
1743 ///
1744 /// # THIRD classification-axis peer on the ephemeral surface
1745 ///
1746 /// Peer of [`Self::has_point_type`] and [`Self::has_substrate`] —
1747 /// all three route through the SAME
1748 /// [`Self::resolved_classification`] resolver, so the operator-
1749 /// omitted `:classification` slot's fill-through logic lives at
1750 /// ONE substrate primitive rather than being restated in each
1751 /// per-axis probe body. FIRST occupant on the (Option-parent ×
1752 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
1753 /// of the ephemeral-surface presence-probe algebra — distinct
1754 /// from the (Option-parent × NON-DEFAULT-scalar-child) corner
1755 /// the first two classification-axis peers opened, since
1756 /// [`CalmClassification`] carries `#[default] = Monotone` on the
1757 /// closed set. The default-arm short-circuit on the absent-
1758 /// classification arm reads `true` on the [`CalmClassification`]
1759 /// child's `#[default]` variant precisely because BOTH the parent
1760 /// Option's fill-through baseline (`default_ephemeral_class`) AND
1761 /// the child's own `#[default]` land on the SAME variant
1762 /// ([`CalmClassification::Monotone`]) — a two-defaults
1763 /// composition property distinct from the NON-DEFAULT-scalar
1764 /// peers, whose absent-classification arm defaults through a
1765 /// specific chosen baseline (`ConvergencePointType::Gate`,
1766 /// `SubstrateType::Compute`) rather than through the child's own
1767 /// `#[default]`. Four future sibling axes on the SAME
1768 /// `Cow`-resolver carrier ([`Self::has_data_classification`]
1769 /// opened the FOURTH, [`Self::has_horizon_kind`] the FIFTH,
1770 /// [`Self::has_optimization_direction`] the SIXTH; then
1771 /// `has_input_arity`, `has_output_arity`) land as one-line
1772 /// wrappers around the SAME resolver + the sibling
1773 /// [`Classification`] closed-set primitive, so a future variant
1774 /// added to [`CalmClassification`] (or any of the five other
1775 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
1776 /// families through the SAME closed-set walk with no per-caller
1777 /// edit.
1778 ///
1779 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1780 /// preserves proofs; the classification-axis presence-probe body
1781 /// composes ONE resolver primitive
1782 /// ([`Self::resolved_classification`]) with ONE closed-set
1783 /// primitive ([`Classification::has_calm`]) so every downstream
1784 /// (`calm-<kind>` require-tag families on both surfaces in
1785 /// tatara-check, closed-set audit dispatchers, future variant
1786 /// additions on [`CalmClassification`]) binds through the SAME
1787 /// `has(kind)` shape rather than restating either the resolver
1788 /// walk or the closed-set equality at the callsite.
1789 #[must_use]
1790 pub fn has_calm(&self, kind: CalmClassification) -> bool {
1791 self.resolved_classification().has_calm(kind)
1792 }
1793
1794 /// True iff the resolved [`Classification`] carries the given
1795 /// [`DataClassification`] on its `data_classification` slot —
1796 /// byte-for-byte peer of [`Classification::has_data_classification`]
1797 /// wrapped through the [`Self::resolved_classification`] resolver
1798 /// so an operator-omitted `:classification` slot reads as the
1799 /// [`default_ephemeral_class`] baseline the sibling
1800 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
1801 ///
1802 /// # Two-surface parity contract
1803 ///
1804 /// A given [`EphemeralSpec`] classifies identically through this
1805 /// primitive AND through
1806 /// `<eph.clone().into::<ProcessSpec>>().classification.has_data_classification(kind)`
1807 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
1808 /// resolver on this side and the `.unwrap_or_else(...)` fill on
1809 /// the lowering side both dereference the same
1810 /// `default_ephemeral_class()` value on `None` and the same
1811 /// authored value on `Some(_)`. This means the ephemeral-surface
1812 /// `data-classification-<kind>` `:requires` family in
1813 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
1814 /// truth on the SAME authored spec as the point-surface family
1815 /// on the mechanically-lowered `ProcessSpec`.
1816 ///
1817 /// # FOURTH classification-axis peer on the ephemeral surface
1818 ///
1819 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`], and
1820 /// [`Self::has_calm`] — all four route through the SAME
1821 /// [`Self::resolved_classification`] resolver, so the operator-
1822 /// omitted `:classification` slot's fill-through logic lives at
1823 /// ONE substrate primitive rather than being restated in each
1824 /// per-axis probe body. SECOND occupant on the (Option-parent ×
1825 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
1826 /// of the ephemeral-surface presence-probe algebra alongside
1827 /// [`Self::has_calm`] — both probe REQUIRED [`Classification`]
1828 /// sub-slots whose child closed set carries its own `#[default]`
1829 /// ([`DataClassification::Internal`] here,
1830 /// [`CalmClassification::Monotone`] on the peer), so the
1831 /// default-arm short-circuit on the absent-classification arm
1832 /// reads `true` on the [`DataClassification`] child's
1833 /// `#[default]` variant precisely because BOTH the parent
1834 /// Option's fill-through baseline (`default_ephemeral_class`)
1835 /// AND the child's own `#[default]` land on the SAME variant
1836 /// ([`DataClassification::Internal`]). The two-defaults
1837 /// composition property now walks TWO independent defaulted-
1838 /// scalar-child slots on the SAME ephemeral resolver — a
1839 /// regression that promoted a different [`DataClassification`]
1840 /// variant to `#[default]` (or wired the arm to a fixed variant
1841 /// answer) fails HERE at ONE narrow substrate site before
1842 /// drifting through every unadorned ephemeral spec's baseline
1843 /// data-classification answer. Distinct from the FIRST + SECOND
1844 /// peers on the (Option-parent × NON-DEFAULT-scalar-child)
1845 /// corner, whose absent-classification arm defaults through a
1846 /// specific chosen baseline (`ConvergencePointType::Gate`,
1847 /// `SubstrateType::Compute`) rather than through the child's own
1848 /// `#[default]`. Four future sibling axes on the SAME
1849 /// `Cow`-resolver carrier ([`Self::has_horizon_kind`] opened the
1850 /// FIFTH, [`Self::has_optimization_direction`] the SIXTH; then
1851 /// `has_input_arity`, `has_output_arity`) land as one-line
1852 /// wrappers around the SAME resolver + the sibling
1853 /// [`Classification`] closed-set primitive, so a future variant
1854 /// added to [`DataClassification`] (or any of the four other
1855 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
1856 /// families through the SAME closed-set walk with no per-caller
1857 /// edit.
1858 ///
1859 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1860 /// preserves proofs; the classification-axis presence-probe body
1861 /// composes ONE resolver primitive
1862 /// ([`Self::resolved_classification`]) with ONE closed-set
1863 /// primitive ([`Classification::has_data_classification`]) so
1864 /// every downstream (`data-classification-<kind>` require-tag
1865 /// families on both surfaces in tatara-check, closed-set audit
1866 /// dispatchers, future variant additions on
1867 /// [`DataClassification`]) binds through the SAME `has(kind)`
1868 /// shape rather than restating either the resolver walk or the
1869 /// closed-set equality at the callsite.
1870 #[must_use]
1871 pub fn has_data_classification(&self, kind: DataClassification) -> bool {
1872 self.resolved_classification().has_data_classification(kind)
1873 }
1874
1875 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
1876 /// carries the given [`HorizonKind`] discriminator on its
1877 /// `horizon.kind` slot — byte-for-byte peer of
1878 /// [`Classification::has_horizon_kind`] wrapped through the
1879 /// [`Self::resolved_classification`] resolver so an operator-
1880 /// omitted `:classification` slot reads as the
1881 /// [`default_ephemeral_class`] baseline the sibling
1882 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
1883 ///
1884 /// # Two-surface parity contract
1885 ///
1886 /// A given [`EphemeralSpec`] classifies identically through this
1887 /// primitive AND through
1888 /// `<eph.clone().into::<ProcessSpec>>().classification.has_horizon_kind(kind)`
1889 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
1890 /// resolver on this side and the `.unwrap_or_else(...)` fill on
1891 /// the lowering side both dereference the same
1892 /// `default_ephemeral_class()` value on `None` and the same
1893 /// authored value on `Some(_)`. This means the ephemeral-surface
1894 /// `horizon-<kind>` `:requires` family in
1895 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
1896 /// truth on the SAME authored spec as the point-surface family
1897 /// on the mechanically-lowered `ProcessSpec`.
1898 ///
1899 /// # FIFTH classification-axis peer on the ephemeral surface
1900 ///
1901 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
1902 /// [`Self::has_calm`], and [`Self::has_data_classification`] — all
1903 /// five route through the SAME [`Self::resolved_classification`]
1904 /// resolver, so the operator-omitted `:classification` slot's
1905 /// fill-through logic lives at ONE substrate primitive rather
1906 /// than being restated in each per-axis probe body. OPENS a fresh
1907 /// (Option-parent × NESTED-STRUCT-scalar-child ×
1908 /// operator-resolvable-baseline) corner on the ephemeral-surface
1909 /// presence-probe algebra — the four prior peers on this surface
1910 /// all read the closed-set discriminator DIRECTLY off a scalar
1911 /// [`Classification`] slot (`point_type`, `substrate`, `calm`,
1912 /// `data_classification`); this probe instead threads through a
1913 /// NESTED-STRUCT intermediary ([`Horizon`], the defaulted nested
1914 /// struct owning the `horizon` axis) to reach a scalar
1915 /// [`HorizonKind`] discriminator on `horizon.kind`. The
1916 /// default-arm short-circuit on the absent-classification arm
1917 /// reads `true` on the [`HorizonKind`] child's `#[default]`
1918 /// variant precisely because BOTH the parent Option's fill-
1919 /// through baseline ([`default_ephemeral_class`], which fills
1920 /// `horizon: Horizon::default()`) AND the child's own `#[default]`
1921 /// land on the SAME variant ([`HorizonKind::Bounded`]). A
1922 /// regression that dropped `#[default]` on [`HorizonKind`], or
1923 /// promoted `Asymptotic` to `#[default]`, or wired the arm to a
1924 /// fixed variant answer, or crossed the wires through the wrong
1925 /// nested struct fails HERE at ONE narrow substrate site before
1926 /// drifting through every unadorned ephemeral spec's baseline
1927 /// horizon answer. Distinct from the FIRST + SECOND peers on the
1928 /// (Option-parent × NON-DEFAULT-scalar-child) corner
1929 /// (`has_point_type`, `has_substrate`) whose absent-classification
1930 /// arm defaults through a specific chosen baseline
1931 /// (`ConvergencePointType::Gate`, `SubstrateType::Compute`), AND
1932 /// distinct from the THIRD + FOURTH peers on the (Option-parent ×
1933 /// DEFAULTED-scalar-child) corner (`has_calm`,
1934 /// `has_data_classification`) which reach a defaulted scalar
1935 /// DIRECTLY off the parent without a nested-struct hop. Three
1936 /// future sibling axes on the SAME `Cow`-resolver carrier
1937 /// ([`Self::has_optimization_direction`] opened the SIXTH; then
1938 /// `has_input_arity`, `has_output_arity`) land as one-line
1939 /// wrappers around the SAME resolver + the sibling
1940 /// [`Classification`] closed-set primitive, so a future variant
1941 /// added to [`HorizonKind`] (or any of the three other closed
1942 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
1943 /// through the SAME closed-set walk with no per-caller edit.
1944 ///
1945 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
1946 /// preserves proofs; the classification-axis presence-probe body
1947 /// composes ONE resolver primitive
1948 /// ([`Self::resolved_classification`]) with ONE closed-set
1949 /// primitive ([`Classification::has_horizon_kind`]) so every
1950 /// downstream (`horizon-<kind>` require-tag families on both
1951 /// surfaces in tatara-check, closed-set audit dispatchers, future
1952 /// variant additions on [`HorizonKind`]) binds through the SAME
1953 /// `has(kind)` shape rather than restating either the resolver
1954 /// walk or the closed-set equality at the callsite.
1955 #[must_use]
1956 pub fn has_horizon_kind(&self, kind: HorizonKind) -> bool {
1957 self.resolved_classification().has_horizon_kind(kind)
1958 }
1959
1960 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
1961 /// carries the given [`OptimizationDirection`] discriminator on its
1962 /// `horizon.direction` slot (with the substrate
1963 /// `Option::unwrap_or_default` treating `None` as the closed set's
1964 /// `#[default] Minimize`) — byte-for-byte peer of
1965 /// [`Classification::has_optimization_direction`] wrapped through
1966 /// the [`Self::resolved_classification`] resolver so an operator-
1967 /// omitted `:classification` slot reads as the
1968 /// [`default_ephemeral_class`] baseline the sibling
1969 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
1970 ///
1971 /// # Two-surface parity contract
1972 ///
1973 /// A given [`EphemeralSpec`] classifies identically through this
1974 /// primitive AND through
1975 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
1976 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
1977 /// resolver on this side and the `.unwrap_or_else(...)` fill on
1978 /// the lowering side both dereference the same
1979 /// `default_ephemeral_class()` value on `None` and the same
1980 /// authored value on `Some(_)`, and the sibling
1981 /// [`Classification::has_optimization_direction`] applies the same
1982 /// `Option::unwrap_or_default` collapse on the inner
1983 /// `horizon.direction` slot on both sides. This means the
1984 /// ephemeral-surface `optimization-direction-<kind>` `:requires`
1985 /// family in `tatara-reconciler::bin::tatara-check` publishes the
1986 /// SAME truth on the SAME authored spec as the point-surface
1987 /// family on the mechanically-lowered `ProcessSpec`.
1988 ///
1989 /// # SIXTH classification-axis peer on the ephemeral surface
1990 ///
1991 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
1992 /// [`Self::has_calm`], [`Self::has_data_classification`], and
1993 /// [`Self::has_horizon_kind`] — all six route through the SAME
1994 /// [`Self::resolved_classification`] resolver, so the operator-
1995 /// omitted `:classification` slot's fill-through logic lives at
1996 /// ONE substrate primitive rather than being restated in each per-
1997 /// axis probe body. SECOND occupant on the (Option-parent ×
1998 /// NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
1999 /// corner alongside [`Self::has_horizon_kind`] — both probes thread
2000 /// through the SAME nested [`Horizon`] intermediary to reach a
2001 /// scalar discriminator on the six-axis classification lattice, but
2002 /// this method additionally traverses an `Option`-slot with
2003 /// `unwrap_or_default` so a Process filled through
2004 /// [`crate::classification::Horizon::default`] (leaves `direction:
2005 /// None`) still reads `true` on the closed set's default arm
2006 /// ([`OptimizationDirection::Minimize`]). The corner therefore
2007 /// admits BOTH direct nested-scalar shapes ([`Self::has_horizon_kind`]
2008 /// walks `horizon.kind: HorizonKind` directly) AND Option-nested-
2009 /// scalar shapes (this method walks `horizon.direction:
2010 /// Option<OptimizationDirection>` through `unwrap_or_default`),
2011 /// pinning the corner as a proven-repeatable primitive shape on the
2012 /// ephemeral surface rather than a single-example curiosity. The
2013 /// two-defaults composition property (parent Option's fill-through
2014 /// baseline via `default_ephemeral_class` AND child's closed-set
2015 /// `#[default]` land on the SAME variant) reaches through TWO
2016 /// hops here: the parent Option's `.unwrap_or_else(default_…)`
2017 /// AND the inner Option's `.unwrap_or_default()` both dereference
2018 /// to the same [`OptimizationDirection::Minimize`] baseline the
2019 /// closed set publishes. A regression that flipped
2020 /// [`OptimizationDirection`]'s `#[default]` off `Minimize` (which
2021 /// would silently invert every unadorned `Asymptotic` Process's
2022 /// rate-window evaluator polarity), or that dropped the resolver
2023 /// hop, or that wired the arm to a fixed variant answer, fails
2024 /// HERE at ONE narrow substrate site before drifting through every
2025 /// unadorned ephemeral spec's baseline direction answer. Two future
2026 /// sibling axes on the SAME `Cow`-resolver carrier
2027 /// (`has_input_arity`, `has_output_arity`) land as one-line
2028 /// wrappers around the SAME resolver + the sibling
2029 /// [`Classification`] closed-set primitive, so a future variant
2030 /// added to [`OptimizationDirection`] (or any of the two other
2031 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
2032 /// families through the SAME closed-set walk with no per-caller
2033 /// edit.
2034 ///
2035 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2036 /// preserves proofs; the classification-axis presence-probe body
2037 /// composes ONE resolver primitive
2038 /// ([`Self::resolved_classification`]) with ONE closed-set
2039 /// primitive ([`Classification::has_optimization_direction`]) so
2040 /// every downstream (`optimization-direction-<kind>` require-tag
2041 /// families on both surfaces in tatara-check, closed-set audit
2042 /// dispatchers, future variant additions on
2043 /// [`OptimizationDirection`]) binds through the SAME `has(kind)`
2044 /// shape rather than restating either the resolver walk or the
2045 /// closed-set equality plus the nested-struct-Option-hop at the
2046 /// callsite.
2047 #[must_use]
2048 pub fn has_optimization_direction(&self, kind: OptimizationDirection) -> bool {
2049 self.resolved_classification()
2050 .has_optimization_direction(kind)
2051 }
2052
2053 /// True iff the resolved [`Classification`]'s nested
2054 /// [`ConvergencePointType`] projects (via the many-to-one
2055 /// [`ConvergencePointType::input_arity`] typed projection) to the
2056 /// given [`Arity`] discriminator — byte-for-byte peer of
2057 /// [`Classification::has_input_arity`] wrapped through the
2058 /// [`Self::resolved_classification`] resolver so an operator-omitted
2059 /// `:classification` slot reads as the [`default_ephemeral_class`]
2060 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
2061 /// lowering fills.
2062 ///
2063 /// # Two-surface parity contract
2064 ///
2065 /// A given [`EphemeralSpec`] classifies identically through this
2066 /// primitive AND through
2067 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
2068 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2069 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
2070 /// lowering side both dereference the same
2071 /// `default_ephemeral_class()` value on `None` and the same
2072 /// authored value on `Some(_)`, and the sibling
2073 /// [`Classification::has_input_arity`] applies the same
2074 /// `point_type.input_arity()` typed projection on both sides. This
2075 /// means the ephemeral-surface `input-arity-<kind>` `:requires`
2076 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2077 /// SAME truth on the SAME authored spec as the point-surface family
2078 /// on the mechanically-lowered `ProcessSpec`.
2079 ///
2080 /// # SEVENTH classification-axis peer on the ephemeral surface — first via a derived-typed-projection
2081 ///
2082 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2083 /// [`Self::has_calm`], [`Self::has_data_classification`],
2084 /// [`Self::has_horizon_kind`], and
2085 /// [`Self::has_optimization_direction`] — all seven route through
2086 /// the SAME [`Self::resolved_classification`] resolver, so the
2087 /// operator-omitted `:classification` slot's fill-through logic
2088 /// lives at ONE substrate primitive rather than being restated in
2089 /// each per-axis probe body. FIRST occupant on the (Option-parent ×
2090 /// NESTED-STRUCT-scalar-child × derived-typed-projection) corner on
2091 /// the ephemeral surface — byte-for-byte symmetric with the
2092 /// derived-typed-projection precedent set by
2093 /// [`Classification::has_input_arity`] on the point surface: THAT
2094 /// peer routes through [`ConvergencePointType::input_arity`] on a
2095 /// required [`Classification`] carrier; THIS peer routes through the
2096 /// SAME projection on the `Cow`-resolver carrier so the resolver
2097 /// walk composes with the projection at ONE substrate site rather
2098 /// than being restated per surface. Distinct from the SIXTH peer
2099 /// [`Self::has_optimization_direction`] (which walks
2100 /// `horizon.direction` through an `Option::unwrap_or_default`
2101 /// collapse to reach a defaulted scalar child) and the FIFTH peer
2102 /// [`Self::has_horizon_kind`] (which walks `horizon.kind` DIRECTLY
2103 /// as a scalar without any typed-projection hop) on ONE dimension:
2104 /// this probe threads through the many-to-one closed-set typed
2105 /// projection [`ConvergencePointType::input_arity`] (`Transform |
2106 /// Fork | Broadcast | Observe → One`, `Join | Gate | Select |
2107 /// Reduce → Many`) so the child's closed set ([`Arity`]) is REACHED
2108 /// THROUGH a projection layer, not read raw off a scalar. The
2109 /// corner therefore admits three ephemeral-surface traversal
2110 /// shapes through the SAME `resolved_classification().<field>`
2111 /// walk: direct-nested-scalar
2112 /// ([`Self::has_horizon_kind`] reads `horizon.kind: HorizonKind`
2113 /// directly), Option-nested-scalar
2114 /// ([`Self::has_optimization_direction`] reads `horizon.direction:
2115 /// Option<OptimizationDirection>` through `unwrap_or_default`), and
2116 /// derived-typed-projection (this method reads
2117 /// `point_type.input_arity(): Arity` through a many-to-one
2118 /// projection). The co-tenant derived-typed-projection axis on the
2119 /// SAME `Cow`-resolver carrier ([`Self::has_output_arity`]) lands as
2120 /// a one-line wrapper around the SAME resolver + the sibling
2121 /// [`Classification`] closed-set primitive, so a future variant
2122 /// added to [`Arity`] or to [`ConvergencePointType`] reaches BOTH
2123 /// surfaces' `<axis>-<kind>` prefix families through the SAME
2124 /// closed-set walk with no per-caller edit.
2125 ///
2126 /// # Semantics — VARIANT match on the projected image
2127 ///
2128 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
2129 /// `#[default]`), so exactly ONE of the two arms answers `true` per
2130 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
2131 /// shortcut. The absent-`:classification` baseline
2132 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
2133 /// [`ConvergencePointType::input_arity`] projects `Gate → Many`, so
2134 /// the ephemeral sugar surface's `input-arity-Many` require-tag
2135 /// reads `true` on every operator-authored spec that omits the
2136 /// `:classification` slot — pinning the workspace's convergent-by-
2137 /// default point posture on the input side. The many-to-one
2138 /// projection shape means the answer is invariant under intra-
2139 /// bucket point-type swaps (`Transform ↔ Fork ↔ Broadcast ↔
2140 /// Observe` all keep `input-arity-One = true`) and flips at bucket
2141 /// boundaries (`Transform ↔ Join` flips `input-arity-One` from
2142 /// `true` to `false`). A regression that dropped the resolver hop,
2143 /// probed [`ConvergencePointType`] directly (dropping the
2144 /// `.input_arity()` call), inverted the projection (`One ↔ Many`),
2145 /// or crossed the wires with the sibling
2146 /// [`ConvergencePointType::output_arity`] projection fails HERE at
2147 /// ONE narrow substrate site before drifting through every
2148 /// unadorned ephemeral spec's baseline input-arity answer.
2149 ///
2150 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2151 /// preserves proofs; the classification-axis presence-probe body
2152 /// composes ONE resolver primitive
2153 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
2154 /// ([`Classification::has_input_arity`]) so every downstream
2155 /// (`input-arity-<kind>` require-tag families on both surfaces in
2156 /// tatara-check, closed-set audit dispatchers, future variant
2157 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
2158 /// through the SAME `has(kind)` shape rather than restating either
2159 /// the resolver walk or the closed-set equality plus the typed-
2160 /// projection hop at the callsite.
2161 #[must_use]
2162 pub fn has_input_arity(&self, kind: Arity) -> bool {
2163 self.resolved_classification().has_input_arity(kind)
2164 }
2165
2166 /// True iff the resolved [`Classification`]'s nested
2167 /// [`ConvergencePointType`] projects (via the many-to-one
2168 /// [`ConvergencePointType::output_arity`] typed projection) to the
2169 /// given [`Arity`] discriminator — byte-for-byte peer of
2170 /// [`Classification::has_output_arity`] wrapped through the
2171 /// [`Self::resolved_classification`] resolver so an operator-omitted
2172 /// `:classification` slot reads as the [`default_ephemeral_class`]
2173 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
2174 /// lowering fills.
2175 ///
2176 /// # Two-surface parity contract
2177 ///
2178 /// A given [`EphemeralSpec`] classifies identically through this
2179 /// primitive AND through
2180 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
2181 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
2182 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
2183 /// lowering side both dereference the same
2184 /// `default_ephemeral_class()` value on `None` and the same
2185 /// authored value on `Some(_)`, and the sibling
2186 /// [`Classification::has_output_arity`] applies the same
2187 /// `point_type.output_arity()` typed projection on both sides. This
2188 /// means the ephemeral-surface `output-arity-<kind>` `:requires`
2189 /// family in `tatara-reconciler::bin::tatara-check` publishes the
2190 /// SAME truth on the SAME authored spec as the point-surface family
2191 /// on the mechanically-lowered `ProcessSpec`.
2192 ///
2193 /// # EIGHTH classification-axis peer — closes the ephemeral-side DAG-composition arity pair
2194 ///
2195 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2196 /// [`Self::has_calm`], [`Self::has_data_classification`],
2197 /// [`Self::has_horizon_kind`], [`Self::has_optimization_direction`],
2198 /// and [`Self::has_input_arity`] — all eight route through the SAME
2199 /// [`Self::resolved_classification`] resolver, so the operator-
2200 /// omitted `:classification` slot's fill-through logic lives at ONE
2201 /// substrate primitive rather than being restated in each per-axis
2202 /// probe body. SECOND occupant on the (Option-parent × NESTED-
2203 /// STRUCT-scalar-child × derived-typed-projection) corner on the
2204 /// ephemeral surface — co-tenant with [`Self::has_input_arity`] on
2205 /// the SAME `point_type` scalar carrier through the SAME [`Arity`]
2206 /// closed set but through the sibling many-to-one typed projection
2207 /// [`ConvergencePointType::output_arity`] (`Transform | Join | Gate
2208 /// | Select | Reduce | Observe → One`, `Fork | Broadcast → Many`).
2209 /// Closes the DAG-composition arity pair on the ephemeral side —
2210 /// the two projections DISAGREE on the diffusive arms `Fork |
2211 /// Broadcast` (input `One` vs. output `Many`) and on the convergent
2212 /// arms `Join | Gate | Select | Reduce` (input `Many` vs. output
2213 /// `One`), and AGREE on the endomorphic arms `Transform | Observe`
2214 /// (both `One`). Byte-for-byte symmetric with the DAG-composition
2215 /// arity pair on the point surface ([`Classification::has_input_arity`] +
2216 /// [`Classification::has_output_arity`]) — THAT pair walks a required
2217 /// [`Classification`] carrier; THIS pair walks the SAME projection
2218 /// pair on the `Cow`-resolver carrier so the resolver walk composes
2219 /// with the projection at ONE substrate site rather than being
2220 /// restated per surface.
2221 ///
2222 /// # Semantics — VARIANT match on the projected image
2223 ///
2224 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
2225 /// `#[default]`), so exactly ONE of the two arms answers `true` per
2226 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
2227 /// shortcut. The absent-`:classification` baseline
2228 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
2229 /// [`ConvergencePointType::output_arity`] projects `Gate → One`, so
2230 /// the ephemeral sugar surface's `output-arity-One` require-tag
2231 /// reads `true` on every operator-authored spec that omits the
2232 /// `:classification` slot — pinning the workspace's convergent-by-
2233 /// default point posture on the output side. The many-to-one
2234 /// projection shape means the answer is invariant under intra-
2235 /// bucket point-type swaps (`Fork ↔ Broadcast` both keep
2236 /// `output-arity-Many = true`; `Transform ↔ Join ↔ Gate ↔ Select ↔
2237 /// Reduce ↔ Observe` all keep `output-arity-One = true`) and flips
2238 /// at bucket boundaries (`Fork ↔ Transform` flips `output-arity-
2239 /// Many` from `true` to `false`). A regression that dropped the
2240 /// resolver hop, probed [`ConvergencePointType`] directly (dropping
2241 /// the `.output_arity()` call), inverted the projection (`One ↔
2242 /// Many`), or crossed the wires with the sibling
2243 /// [`ConvergencePointType::input_arity`] projection fails HERE at
2244 /// ONE narrow substrate site before drifting through every
2245 /// unadorned ephemeral spec's baseline output-arity answer.
2246 ///
2247 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2248 /// preserves proofs; the classification-axis presence-probe body
2249 /// composes ONE resolver primitive
2250 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
2251 /// ([`Classification::has_output_arity`]) so every downstream
2252 /// (`output-arity-<kind>` require-tag families on both surfaces in
2253 /// tatara-check, closed-set audit dispatchers, future variant
2254 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
2255 /// through the SAME `has(kind)` shape rather than restating either
2256 /// the resolver walk or the closed-set equality plus the typed-
2257 /// projection hop at the callsite.
2258 #[must_use]
2259 pub fn has_output_arity(&self, kind: Arity) -> bool {
2260 self.resolved_classification().has_output_arity(kind)
2261 }
2262
2263 /// Derived-boolean predicate — does this ephemeral spec's
2264 /// resolved [`Classification`]'s [`Horizon`] project to `true`
2265 /// under [`crate::classification::HorizonKind::terminates`]?
2266 /// Byte-for-byte peer of
2267 /// [`Classification::horizon_terminates`] wrapped through the
2268 /// [`Self::resolved_classification`] resolver so an operator-
2269 /// omitted `:classification` slot on `(defephemeral …)` still
2270 /// answers via the substrate default. The ONE ephemeral-surface
2271 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2272 /// derived-nullary-boolean walk on the classification-horizon
2273 /// axis.
2274 ///
2275 /// # Two-surface parity — resolver hop + Classification primitive
2276 ///
2277 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
2278 /// [`Self::has_calm`], [`Self::has_data_classification`],
2279 /// [`Self::has_horizon_kind`],
2280 /// [`Self::has_optimization_direction`],
2281 /// [`Self::has_input_arity`], and [`Self::has_output_arity`] on
2282 /// the (resolver-hop × [`Classification`] presence primitive)
2283 /// axis: all nine methods route through the SAME
2284 /// [`Self::resolved_classification`] resolver, and each composes
2285 /// against ONE [`Classification`] primitive. This method
2286 /// distinguishes itself by targeting the [`Classification`]
2287 /// primitive [`Classification::horizon_terminates`] which is the
2288 /// FIRST derived-nullary-boolean (no closed-set argument)
2289 /// primitive on the [`Classification`] surface — every prior
2290 /// peer probe on [`Classification`] admits a closed-set `kind`
2291 /// argument and answers a variant-equality question, while this
2292 /// probe collapses [`HorizonKind::ALL`] onto a single boolean
2293 /// via the closed set's own [`HorizonKind::terminates`]
2294 /// predicate.
2295 ///
2296 /// # Semantics — resolver hop + derived-nullary-boolean
2297 ///
2298 /// `horizon_terminates()` returns `true` iff
2299 /// `self.resolved_classification().horizon_terminates()`. The
2300 /// resolver returns the authored [`Classification`] when
2301 /// present and the substrate default
2302 /// [`Classification::gate_compute`] on absence. Because
2303 /// [`Classification::gate_compute`] uses [`Horizon::default`]
2304 /// (whose `kind` field defaults to [`HorizonKind::Bounded`] via
2305 /// `#[default]`), a bare ephemeral spec with no `:classification`
2306 /// slot answers `true` — the default-arm short-circuit
2307 /// propagates through THREE layers of `Default`
2308 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
2309 /// [`HorizonKind::default`]) to this predicate's answer, matching
2310 /// the default-arm shortcut every prior defaulted-child probe
2311 /// on this surface publishes. A regression that dropped the
2312 /// resolver hop, probed [`Classification::has_horizon_kind`]
2313 /// directly (dropping the `.terminates()` projection), or
2314 /// crossed the wires with the antisymmetric partner
2315 /// [`HorizonKind::requires_metric_axes`] fails HERE at ONE
2316 /// narrow substrate site before drifting through every
2317 /// unadorned ephemeral spec's baseline horizon-terminates
2318 /// answer.
2319 ///
2320 /// # Compounding
2321 ///
2322 /// The ephemeral require-tag classifier composes this primitive
2323 /// as a fixed tag `terminating-horizon` on
2324 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2325 /// surface's `terminating-horizon` fixed tag on
2326 /// `POINT_FIXED_TAG_ARMS` via [`Classification::horizon_terminates`]
2327 /// directly. The two-surface parity contract holds by
2328 /// construction: both surfaces route through the SAME
2329 /// [`Classification::horizon_terminates`] primitive after the
2330 /// ephemeral surface pays ONE resolver hop — a future
2331 /// [`HorizonKind`] variant or a future normalization at the
2332 /// substrate primitive lands at ONE site and both surfaces'
2333 /// `terminating-horizon` fixed tags inherit the shift
2334 /// mechanically. A future co-tenant peer on this surface (a
2335 /// hypothetical `horizon_requires_metric_axes` composing the
2336 /// antisymmetric partner [`HorizonKind::requires_metric_axes`]
2337 /// through the SAME resolver hop) lands as ONE peer inherent
2338 /// method with the same nullary-derived body.
2339 ///
2340 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2341 /// preserves proofs; the classification-axis derived-nullary-
2342 /// boolean probe body composes ONE resolver primitive
2343 /// ([`Self::resolved_classification`]) with ONE
2344 /// [`Classification`] primitive
2345 /// ([`Classification::horizon_terminates`]) so every downstream
2346 /// (`terminating-horizon` fixed tags on both surfaces in
2347 /// tatara-check, future scheduler / termination-shape
2348 /// validators, future variant additions on [`HorizonKind`])
2349 /// binds through the SAME `horizon_terminates()` shape rather
2350 /// than restating either the resolver walk or the closed-set
2351 /// projection composition at the callsite. THEORY.md §VI.1 —
2352 /// generation over composition; a future [`HorizonKind`]
2353 /// variant lands at ONE `ALL` entry + ONE `terminates` arm on
2354 /// the closed set and both surfaces pick it up mechanically.
2355 #[must_use]
2356 pub fn horizon_terminates(&self) -> bool {
2357 self.resolved_classification().horizon_terminates()
2358 }
2359
2360 /// Derived-boolean predicate — does this ephemeral spec's
2361 /// resolved [`Classification`]'s [`Horizon`] project to `true`
2362 /// under [`crate::classification::HorizonKind::requires_metric_axes`]?
2363 /// Byte-for-byte peer of
2364 /// [`Classification::horizon_requires_metric_axes`] wrapped
2365 /// through the [`Self::resolved_classification`] resolver so an
2366 /// operator-omitted `:classification` slot on `(defephemeral …)`
2367 /// still answers via the substrate default. The ONE ephemeral-
2368 /// surface substrate primitive that owns the
2369 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on
2370 /// the metric-axes-required question over the classification-
2371 /// horizon axis.
2372 ///
2373 /// # Antisymmetric peer of [`Self::horizon_terminates`]
2374 ///
2375 /// Byte-for-byte antisymmetric peer of [`Self::horizon_terminates`]
2376 /// via the SAME [`Self::resolved_classification`] resolver hop
2377 /// and the SAME closed set [`crate::classification::HorizonKind`]:
2378 /// [`Self::horizon_terminates`] composes
2379 /// [`Classification::horizon_terminates`] (walking
2380 /// [`crate::classification::HorizonKind::terminates`]); this
2381 /// method composes the ANTISYMMETRIC partner
2382 /// [`Classification::horizon_requires_metric_axes`] (walking
2383 /// [`crate::classification::HorizonKind::requires_metric_axes`]).
2384 /// The closed set pins the XOR contract
2385 /// `terminates() ^ requires_metric_axes()` on every variant, so
2386 /// exactly ONE of these two ephemeral-surface derived-nullary
2387 /// probes answers `true` per resolved [`Classification`] and the
2388 /// two probes together partition the resolver's output space into
2389 /// two disjoint buckets on every ephemeral spec — authored or
2390 /// defaulted.
2391 ///
2392 /// # Semantics — resolver hop + derived-nullary-boolean
2393 ///
2394 /// `horizon_requires_metric_axes()` returns `true` iff
2395 /// `self.resolved_classification().horizon_requires_metric_axes()`.
2396 /// The resolver returns the authored [`Classification`] when
2397 /// present and the substrate default
2398 /// [`Classification::gate_compute`] on absence. Because
2399 /// [`Classification::gate_compute`] uses [`Horizon::default`]
2400 /// (whose `kind` field defaults to
2401 /// [`crate::classification::HorizonKind::Bounded`] via
2402 /// `#[default]`), a bare ephemeral spec with no `:classification`
2403 /// slot answers `false` — the default-arm short-circuit
2404 /// propagates through THREE layers of `Default`
2405 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
2406 /// [`crate::classification::HorizonKind::default`]) to this
2407 /// predicate's answer, the mirror image of
2408 /// [`Self::horizon_terminates`]'s default-arm `true` answer. A
2409 /// regression that dropped the resolver hop, probed
2410 /// [`Classification::has_horizon_kind`] directly (dropping the
2411 /// `.requires_metric_axes()` projection), or crossed the wires
2412 /// with the antisymmetric partner
2413 /// [`crate::classification::HorizonKind::terminates`] fails HERE
2414 /// at ONE narrow substrate site before drifting through every
2415 /// unadorned ephemeral spec's baseline metric-provisioning
2416 /// answer.
2417 ///
2418 /// # Compounding
2419 ///
2420 /// The ephemeral require-tag classifier composes this primitive
2421 /// as a fixed tag `metric-axes-required` on
2422 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2423 /// surface's `metric-axes-required` fixed tag on
2424 /// `POINT_FIXED_TAG_ARMS` via
2425 /// [`Classification::horizon_requires_metric_axes`] directly. The
2426 /// two-surface parity contract holds by construction: both
2427 /// surfaces route through the SAME
2428 /// [`Classification::horizon_requires_metric_axes`] primitive
2429 /// after the ephemeral surface pays ONE resolver hop — a future
2430 /// [`crate::classification::HorizonKind`] variant or a future
2431 /// normalization at the substrate primitive lands at ONE site and
2432 /// both surfaces' `metric-axes-required` fixed tags inherit the
2433 /// shift mechanically.
2434 ///
2435 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2436 /// preserves proofs; the classification-axis derived-nullary-
2437 /// boolean probe body composes ONE resolver primitive
2438 /// ([`Self::resolved_classification`]) with ONE
2439 /// [`Classification`] primitive
2440 /// ([`Classification::horizon_requires_metric_axes`]) so every
2441 /// downstream (`metric-axes-required` fixed tags on both
2442 /// surfaces in tatara-check, future scheduler / metric-
2443 /// provisioning validators, future variant additions on
2444 /// [`crate::classification::HorizonKind`]) binds through the
2445 /// SAME `horizon_requires_metric_axes()` shape rather than
2446 /// restating either the resolver walk or the closed-set
2447 /// projection composition at the callsite. THEORY.md §VI.1 —
2448 /// generation over composition; a future
2449 /// [`crate::classification::HorizonKind`] variant lands at ONE
2450 /// `ALL` entry + ONE `requires_metric_axes` arm on the closed
2451 /// set and both surfaces pick it up mechanically.
2452 #[must_use]
2453 pub fn horizon_requires_metric_axes(&self) -> bool {
2454 self.resolved_classification()
2455 .horizon_requires_metric_axes()
2456 }
2457
2458 /// Derived-boolean predicate — does this ephemeral spec's
2459 /// resolved [`Classification`]'s [`crate::classification::CalmClassification`]
2460 /// project to `true` under
2461 /// [`crate::classification::CalmClassification::requires_coordination`]?
2462 /// Byte-for-byte peer of
2463 /// [`Classification::calm_requires_coordination`] wrapped through
2464 /// the [`Self::resolved_classification`] resolver so an operator-
2465 /// omitted `:classification` slot on `(defephemeral …)` still
2466 /// answers via the substrate default. The ONE ephemeral-surface
2467 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2468 /// derived-nullary-boolean walk on the coordination-required
2469 /// question over the classification-calm axis.
2470 ///
2471 /// # Third derived-nullary-boolean peer on the ephemeral surface
2472 ///
2473 /// Peer of [`Self::horizon_terminates`] and
2474 /// [`Self::horizon_requires_metric_axes`] on the ephemeral
2475 /// surface's (resolver-hop × derived-nullary-bool) shape — the
2476 /// FIRST peer threading the classification-calm axis rather than
2477 /// the classification-horizon axis. Distinct from both prior
2478 /// derived-nullary peers by ONE structural degree at the underlying
2479 /// [`Classification`] primitive: [`Self::horizon_terminates`] +
2480 /// [`Self::horizon_requires_metric_axes`] both walk the nested
2481 /// `.horizon.kind` sub-slot's derived projection, while this probe
2482 /// walks the direct scalar `.calm` field's derived projection.
2483 /// The resolver-hop shape is byte-identical.
2484 ///
2485 /// # Semantics — resolver hop + derived-nullary-boolean
2486 ///
2487 /// `calm_requires_coordination()` returns `true` iff
2488 /// `self.resolved_classification().calm_requires_coordination()`.
2489 /// The resolver returns the authored [`Classification`] when
2490 /// present and the substrate default
2491 /// [`Classification::gate_compute`] on absence. Because
2492 /// [`Classification::gate_compute`] carries
2493 /// [`crate::classification::CalmClassification::default = Monotone`],
2494 /// a bare ephemeral spec with no `:classification` slot answers
2495 /// `false` — the default-arm short-circuit propagates through TWO
2496 /// layers of `Default` ([`Classification::gate_compute`] →
2497 /// [`crate::classification::CalmClassification::default`]) to this
2498 /// predicate's answer. Distinct from the two `horizon_*` peers on
2499 /// this surface, which short-circuit through THREE layers of
2500 /// `Default` ([`Classification::gate_compute`] → [`Horizon::default`]
2501 /// → [`HorizonKind::default`]) because the horizon axis has a
2502 /// nested-struct wrapper between the classification field and the
2503 /// closed-set discriminator. A regression that dropped the
2504 /// resolver hop, probed [`Classification::has_calm`] directly
2505 /// (dropping the `.requires_coordination()` projection), or
2506 /// inverted the projection (silently promoting the Monotone
2507 /// baseline to "requires coordination") fails HERE at ONE narrow
2508 /// substrate site before drifting through every unadorned
2509 /// ephemeral spec's baseline coordination-mode answer.
2510 ///
2511 /// # Compounding
2512 ///
2513 /// The ephemeral require-tag classifier composes this primitive
2514 /// as a fixed tag `coordination-required` on
2515 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2516 /// surface's `coordination-required` fixed tag on
2517 /// `POINT_FIXED_TAG_ARMS` via
2518 /// [`Classification::calm_requires_coordination`] directly. The
2519 /// two-surface parity contract holds by construction: both
2520 /// surfaces route through the SAME
2521 /// [`Classification::calm_requires_coordination`] primitive after
2522 /// the ephemeral surface pays ONE resolver hop — a future
2523 /// [`crate::classification::CalmClassification`] variant or a
2524 /// future normalization at the substrate primitive lands at ONE
2525 /// site and both surfaces' `coordination-required` fixed tags
2526 /// inherit the shift mechanically.
2527 ///
2528 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2529 /// preserves proofs; the classification-axis derived-nullary-
2530 /// boolean probe body composes ONE resolver primitive
2531 /// ([`Self::resolved_classification`]) with ONE
2532 /// [`Classification`] primitive
2533 /// ([`Classification::calm_requires_coordination`]) so every
2534 /// downstream (`coordination-required` fixed tags on both
2535 /// surfaces in tatara-check, future scheduler / coordination-mode
2536 /// validators, future variant additions on
2537 /// [`crate::classification::CalmClassification`]) binds through
2538 /// the SAME `calm_requires_coordination()` shape rather than
2539 /// restating either the resolver walk or the closed-set
2540 /// projection composition at the callsite. THEORY.md §VI.1 —
2541 /// generation over composition; a future
2542 /// [`crate::classification::CalmClassification`] variant lands at
2543 /// ONE `ALL` entry + ONE `requires_coordination` arm on the
2544 /// closed set and both surfaces pick it up mechanically.
2545 #[must_use]
2546 pub fn calm_requires_coordination(&self) -> bool {
2547 self.resolved_classification().calm_requires_coordination()
2548 }
2549
2550 /// Derived-boolean predicate — does this ephemeral spec's
2551 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
2552 /// project to `true` under
2553 /// [`crate::classification::DataClassification::is_regulated`]?
2554 /// Byte-for-byte peer of
2555 /// [`Classification::data_is_regulated`] wrapped through the
2556 /// [`Self::resolved_classification`] resolver so an operator-
2557 /// omitted `:classification` slot on `(defephemeral …)` still
2558 /// answers via the substrate default. The ONE ephemeral-surface
2559 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2560 /// derived-nullary-boolean walk on the regulated-data question
2561 /// over the classification-data axis.
2562 ///
2563 /// # Fourth derived-nullary-boolean peer on the ephemeral surface
2564 ///
2565 /// Peer of [`Self::horizon_terminates`],
2566 /// [`Self::horizon_requires_metric_axes`], and
2567 /// [`Self::calm_requires_coordination`] on the ephemeral surface's
2568 /// (resolver-hop × derived-nullary-bool) shape — the FIRST peer
2569 /// threading the classification-data axis rather than the horizon
2570 /// or calm axes. Structural byte-for-byte peer of
2571 /// [`Self::calm_requires_coordination`]: both walk a DIRECT scalar
2572 /// closed-set field's derived projection on the resolved
2573 /// [`Classification`] (`.calm.requires_coordination()` /
2574 /// `.data_classification.is_regulated()`) — TWO layers of
2575 /// `Default` short-circuit ([`Classification::gate_compute`] →
2576 /// the direct scalar child's `#[default]`) — distinct from the
2577 /// two `horizon_*` peers which walk a NESTED-STRUCT projection
2578 /// (`.horizon.kind`) with THREE layers of `Default`. The resolver-
2579 /// hop shape is byte-identical across all four peers.
2580 ///
2581 /// # Semantics — resolver hop + derived-nullary-boolean
2582 ///
2583 /// `data_is_regulated()` returns `true` iff
2584 /// `self.resolved_classification().data_is_regulated()`. The
2585 /// resolver returns the authored [`Classification`] when present
2586 /// and the substrate default [`Classification::gate_compute`] on
2587 /// absence. Because [`Classification::gate_compute`] carries
2588 /// [`crate::classification::DataClassification::default = Internal`],
2589 /// a bare ephemeral spec with no `:classification` slot answers
2590 /// `false` — the default-arm short-circuit propagates through TWO
2591 /// layers of `Default` ([`Classification::gate_compute`] →
2592 /// [`crate::classification::DataClassification::default`]) to
2593 /// this predicate's answer, mirror-image of
2594 /// [`Self::calm_requires_coordination`]'s Monotone-default
2595 /// short-circuit through the same structural depth. Distinct
2596 /// from the two `horizon_*` peers on this surface which short-
2597 /// circuit through THREE layers of `Default` because the horizon
2598 /// axis has a nested-struct wrapper. A regression that dropped
2599 /// the resolver hop, probed [`Classification::has_data_classification`]
2600 /// directly (dropping the `.is_regulated()` projection), or
2601 /// inverted the projection (silently promoting the Internal
2602 /// baseline to "regulated") fails HERE at ONE narrow substrate
2603 /// site before drifting through every unadorned ephemeral spec's
2604 /// baseline regulatory-regime answer.
2605 ///
2606 /// # Compounding
2607 ///
2608 /// The ephemeral require-tag classifier composes this primitive
2609 /// as a fixed tag `data-regulated` on `EPHEMERAL_FIXED_TAG_ARMS`
2610 /// — byte-for-byte peer of the point surface's `data-regulated`
2611 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
2612 /// [`Classification::data_is_regulated`] directly. The two-
2613 /// surface parity contract holds by construction: both surfaces
2614 /// route through the SAME
2615 /// [`Classification::data_is_regulated`] primitive after the
2616 /// ephemeral surface pays ONE resolver hop — a future
2617 /// [`crate::classification::DataClassification`] variant or a
2618 /// future normalization at the substrate primitive lands at ONE
2619 /// site and both surfaces' `data-regulated` fixed tags inherit
2620 /// the shift mechanically.
2621 ///
2622 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2623 /// preserves proofs; the classification-data-axis derived-nullary-
2624 /// boolean probe body composes ONE resolver primitive
2625 /// ([`Self::resolved_classification`]) with ONE
2626 /// [`Classification`] primitive
2627 /// ([`Classification::data_is_regulated`]) so every downstream
2628 /// (`data-regulated` fixed tags on both surfaces in tatara-check,
2629 /// future compliance-baseline / regulatory-regime validators,
2630 /// future variant additions on
2631 /// [`crate::classification::DataClassification`]) binds through
2632 /// the SAME `data_is_regulated()` shape rather than restating
2633 /// either the resolver walk or the closed-set projection
2634 /// composition at the callsite. THEORY.md §VI.1 — generation
2635 /// over composition; a future
2636 /// [`crate::classification::DataClassification`] variant lands
2637 /// at ONE `ALL` entry + ONE `is_regulated` arm on the closed set
2638 /// and both surfaces pick it up mechanically.
2639 #[must_use]
2640 pub fn data_is_regulated(&self) -> bool {
2641 self.resolved_classification().data_is_regulated()
2642 }
2643
2644 /// Derived-boolean predicate — does this ephemeral spec's
2645 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
2646 /// project to `true` under
2647 /// [`crate::classification::DataClassification::is_restricted`]?
2648 /// Byte-for-byte peer of
2649 /// [`Classification::data_is_restricted`] wrapped through the
2650 /// [`Self::resolved_classification`] resolver so an operator-
2651 /// omitted `:classification` slot on `(defephemeral …)` still
2652 /// answers via the substrate default. The ONE ephemeral-surface
2653 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2654 /// derived-nullary-boolean walk on the restricted-data question
2655 /// over the classification-data axis.
2656 ///
2657 /// # Fifth derived-nullary-boolean peer on the ephemeral surface
2658 ///
2659 /// Peer of [`Self::horizon_terminates`],
2660 /// [`Self::horizon_requires_metric_axes`],
2661 /// [`Self::calm_requires_coordination`], and
2662 /// [`Self::data_is_regulated`] on the ephemeral surface's
2663 /// (resolver-hop × derived-nullary-bool) shape — the SECOND peer
2664 /// threading the classification-data axis after
2665 /// [`Self::data_is_regulated`] opened it, pinning the data axis
2666 /// as a proven-repeatable structural sub-corner across TWO sibling
2667 /// closed-set projections (`is_regulated` / `is_restricted`).
2668 /// Structural byte-for-byte peer of
2669 /// [`Self::data_is_regulated`]: both walk the SAME DIRECT scalar
2670 /// closed-set field's derived projection on the resolved
2671 /// [`Classification`] (`.data_classification.is_regulated()` /
2672 /// `.is_restricted()`) — TWO layers of `Default` short-circuit
2673 /// ([`Classification::gate_compute`] → [`crate::classification::DataClassification::default = Internal`])
2674 /// — distinct from the two `horizon_*` peers which walk a NESTED-
2675 /// STRUCT projection (`.horizon.kind`) with THREE layers of
2676 /// `Default`. The resolver-hop shape is byte-identical across all
2677 /// five peers.
2678 ///
2679 /// # Semantics — resolver hop + derived-nullary-boolean
2680 ///
2681 /// `data_is_restricted()` returns `true` iff
2682 /// `self.resolved_classification().data_is_restricted()`. The
2683 /// resolver returns the authored [`Classification`] when present
2684 /// and the substrate default [`Classification::gate_compute`] on
2685 /// absence. Because [`Classification::gate_compute`] carries
2686 /// [`crate::classification::DataClassification::default = Internal`],
2687 /// a bare ephemeral spec with no `:classification` slot answers
2688 /// `true` — the default-arm short-circuit propagates through TWO
2689 /// layers of `Default` ([`Classification::gate_compute`] →
2690 /// [`crate::classification::DataClassification::default`]) to
2691 /// this predicate's answer. FIRST direct-scalar ephemeral-surface
2692 /// peer whose absent-classification default answers `true`, not
2693 /// `false` (`data_is_regulated` and `calm_requires_coordination`
2694 /// both project `false` on the same absent classification),
2695 /// mirror-image of [`Self::horizon_terminates`]'s `Bounded`-default
2696 /// `true` baseline on the nested-struct sub-corner. A regression
2697 /// that dropped the resolver hop, probed
2698 /// [`Classification::has_data_classification`] directly (dropping
2699 /// the `.is_restricted()` projection), or inverted the projection
2700 /// (silently demoting the Internal baseline to "unrestricted")
2701 /// fails HERE at ONE narrow substrate site before drifting
2702 /// through every unadorned ephemeral spec's baseline access-
2703 /// control-mandatory answer.
2704 ///
2705 /// # Compounding
2706 ///
2707 /// The ephemeral require-tag classifier composes this primitive
2708 /// as a fixed tag `data-restricted` on `EPHEMERAL_FIXED_TAG_ARMS`
2709 /// — byte-for-byte peer of the point surface's `data-restricted`
2710 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
2711 /// [`Classification::data_is_restricted`] directly. The two-
2712 /// surface parity contract holds by construction: both surfaces
2713 /// route through the SAME
2714 /// [`Classification::data_is_restricted`] primitive after the
2715 /// ephemeral surface pays ONE resolver hop — a future
2716 /// [`crate::classification::DataClassification`] variant or a
2717 /// future normalization at the substrate primitive lands at ONE
2718 /// site and both surfaces' `data-restricted` fixed tags inherit
2719 /// the shift mechanically. The closed-set-internal implication
2720 /// `is_regulated() ⇒ is_restricted()` composes through the
2721 /// resolver hop to
2722 /// `data_is_regulated() ⇒ data_is_restricted()` at this surface
2723 /// too.
2724 ///
2725 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2726 /// preserves proofs; the classification-data-axis derived-nullary-
2727 /// boolean probe body composes ONE resolver primitive
2728 /// ([`Self::resolved_classification`]) with ONE
2729 /// [`Classification`] primitive
2730 /// ([`Classification::data_is_restricted`]) so every downstream
2731 /// (`data-restricted` fixed tags on both surfaces in tatara-check,
2732 /// future compliance-baseline / access-control-mandatory
2733 /// validators, future variant additions on
2734 /// [`crate::classification::DataClassification`]) binds through
2735 /// the SAME `data_is_restricted()` shape rather than restating
2736 /// either the resolver walk or the closed-set projection
2737 /// composition at the callsite. THEORY.md §VI.1 — generation
2738 /// over composition; a future
2739 /// [`crate::classification::DataClassification`] variant lands
2740 /// at ONE `ALL` entry + ONE `is_restricted` arm on the closed set
2741 /// and both surfaces pick it up mechanically.
2742 #[must_use]
2743 pub fn data_is_restricted(&self) -> bool {
2744 self.resolved_classification().data_is_restricted()
2745 }
2746
2747 /// Derived-boolean predicate — does this ephemeral spec's
2748 /// resolved [`Classification`]'s
2749 /// [`crate::classification::ConvergencePointType`] project to
2750 /// `true` under
2751 /// [`crate::classification::ConvergencePointType::is_endomorphic`]?
2752 /// Byte-for-byte peer of
2753 /// [`Classification::point_is_endomorphic`] wrapped through the
2754 /// [`Self::resolved_classification`] resolver so an operator-
2755 /// omitted `:classification` slot on `(defephemeral …)` still
2756 /// answers via the substrate default. The ONE ephemeral-surface
2757 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2758 /// derived-nullary-boolean walk on the 1→1 topology-bucket
2759 /// question over the classification-`point_type` axis.
2760 ///
2761 /// # Sixth derived-nullary-boolean peer on the ephemeral surface
2762 ///
2763 /// Peer of [`Self::horizon_terminates`],
2764 /// [`Self::horizon_requires_metric_axes`],
2765 /// [`Self::calm_requires_coordination`],
2766 /// [`Self::data_is_regulated`], and [`Self::data_is_restricted`]
2767 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
2768 /// shape — the FIRST peer threading the classification-`point_type`
2769 /// axis after the two `horizon_*`, one `calm_*`, and two `data_*`
2770 /// peers populated the horizon, calm, and data axes. Direct-scalar
2771 /// peer of the sibling `data_*` and `calm_*` arms but distinct by
2772 /// ONE structural degree at the underlying [`Classification`]
2773 /// primitive: [`crate::classification::ConvergencePointType`] has
2774 /// NO [`Default`] impl, so the absent-`:classification` baseline
2775 /// answers `false` via the resolver's substrate default
2776 /// [`Classification::gate_compute`] carrying its chosen
2777 /// `point_type: Gate` field (not via a `#[default]` short-circuit
2778 /// on the point-type axis itself). The resolver-hop shape is
2779 /// byte-identical across all six peers.
2780 ///
2781 /// # Semantics — resolver hop + derived-nullary-boolean
2782 ///
2783 /// `point_is_endomorphic()` returns `true` iff
2784 /// `self.resolved_classification().point_is_endomorphic()`. The
2785 /// resolver returns the authored [`Classification`] when present
2786 /// and the substrate default [`Classification::gate_compute`] on
2787 /// absence. Because [`Classification::gate_compute`] carries
2788 /// [`crate::classification::ConvergencePointType::Gate`] (a
2789 /// convergent barrier point, not a 1→1 endomorphism), a bare
2790 /// ephemeral spec with no `:classification` slot answers `false`.
2791 /// A regression that dropped the resolver hop, probed the wrong
2792 /// closed-set arm, or inverted the projection fails HERE at ONE
2793 /// narrow substrate site before drifting through every unadorned
2794 /// ephemeral spec's DAG-composition answer.
2795 ///
2796 /// # Compounding
2797 ///
2798 /// The ephemeral require-tag classifier composes this primitive
2799 /// as a fixed tag `endomorphic-point` on
2800 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
2801 /// surface's `endomorphic-point` fixed tag on
2802 /// `POINT_FIXED_TAG_ARMS` via
2803 /// [`Classification::point_is_endomorphic`] directly. The two-
2804 /// surface parity contract holds by construction: both surfaces
2805 /// route through the SAME
2806 /// [`Classification::point_is_endomorphic`] primitive after the
2807 /// ephemeral surface pays ONE resolver hop — a future
2808 /// [`crate::classification::ConvergencePointType`] variant or a
2809 /// future normalization at the substrate primitive lands at ONE
2810 /// site and both surfaces' `endomorphic-point` fixed tags inherit
2811 /// the shift mechanically. Sibling projections
2812 /// [`crate::classification::ConvergencePointType::is_diffusive`]
2813 /// and [`crate::classification::ConvergencePointType::is_convergent`]
2814 /// compose byte-identically as future seventh + eighth ephemeral-
2815 /// surface peers; when all three land the three-way partition
2816 /// contract sealed on the closed set by
2817 /// `convergence_point_type_buckets_cover_every_variant` composes
2818 /// through the resolver-hop layer as a substrate-wide theorem.
2819 ///
2820 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2821 /// preserves proofs; the classification-`point_type`-axis derived-
2822 /// nullary-boolean probe body composes ONE resolver primitive
2823 /// ([`Self::resolved_classification`]) with ONE
2824 /// [`Classification`] primitive
2825 /// ([`Classification::point_is_endomorphic`]) so every downstream
2826 /// (`endomorphic-point` fixed tags on both surfaces in tatara-check,
2827 /// future DAG composition / edge-cardinality validators, future
2828 /// variant additions on
2829 /// [`crate::classification::ConvergencePointType`]) binds through
2830 /// the SAME `point_is_endomorphic()` shape rather than restating
2831 /// either the resolver walk or the closed-set projection
2832 /// composition at the callsite. THEORY.md §VI.1 — generation over
2833 /// composition; a future
2834 /// [`crate::classification::ConvergencePointType`] variant lands
2835 /// at ONE `ALL` entry + ONE `is_endomorphic` arm on the closed
2836 /// set and both surfaces pick it up mechanically.
2837 #[must_use]
2838 pub fn point_is_endomorphic(&self) -> bool {
2839 self.resolved_classification().point_is_endomorphic()
2840 }
2841
2842 /// Derived-boolean predicate — does this ephemeral spec's
2843 /// resolved [`Classification`]'s
2844 /// [`crate::classification::ConvergencePointType`] project to
2845 /// `true` under
2846 /// [`crate::classification::ConvergencePointType::is_diffusive`]?
2847 /// Byte-for-byte peer of
2848 /// [`Classification::point_is_diffusive`] wrapped through the
2849 /// [`Self::resolved_classification`] resolver so an operator-
2850 /// omitted `:classification` slot on `(defephemeral …)` still
2851 /// answers via the substrate default. The ONE ephemeral-surface
2852 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2853 /// derived-nullary-boolean walk on the 1→N fan-out topology-bucket
2854 /// question over the classification-`point_type` axis.
2855 ///
2856 /// # Seventh derived-nullary-boolean peer on the ephemeral surface
2857 ///
2858 /// Peer of [`Self::horizon_terminates`],
2859 /// [`Self::horizon_requires_metric_axes`],
2860 /// [`Self::calm_requires_coordination`],
2861 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`], and
2862 /// [`Self::point_is_endomorphic`] on the ephemeral surface's
2863 /// (resolver-hop × derived-nullary-bool) shape — the SEVENTH peer
2864 /// overall and the SECOND peer threading the classification-
2865 /// `point_type` axis. Direct-scalar peer of
2866 /// [`Self::point_is_endomorphic`]: both compose the SAME resolver
2867 /// hop and the SAME closed-set carrier through the SAME chosen-
2868 /// field baseline discipline (`Gate.is_diffusive() = false`,
2869 /// mirror-image of `Gate.is_endomorphic() = false`). The
2870 /// resolver-hop shape is byte-identical across all seven peers.
2871 ///
2872 /// # Semantics — resolver hop + derived-nullary-boolean
2873 ///
2874 /// `point_is_diffusive()` returns `true` iff
2875 /// `self.resolved_classification().point_is_diffusive()`. The
2876 /// resolver returns the authored [`Classification`] when present
2877 /// and the substrate default [`Classification::gate_compute`] on
2878 /// absence. Because [`Classification::gate_compute`] carries
2879 /// [`crate::classification::ConvergencePointType::Gate`] (a
2880 /// convergent barrier, not a fan-out), a bare ephemeral spec with
2881 /// no `:classification` slot answers `false`. A regression that
2882 /// dropped the resolver hop, probed the wrong closed-set arm, or
2883 /// inverted the projection fails HERE at ONE narrow substrate
2884 /// site before drifting through every unadorned ephemeral spec's
2885 /// DAG-composition answer.
2886 ///
2887 /// # Compounding — first ephemeral-surface corner-peer mutex on the `point_type` axis
2888 ///
2889 /// The ephemeral require-tag classifier composes this primitive
2890 /// as a fixed tag `diffusive-point` on `EPHEMERAL_FIXED_TAG_ARMS`
2891 /// — byte-for-byte peer of the point surface's `diffusive-point`
2892 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
2893 /// [`Classification::point_is_diffusive`] directly. The two-
2894 /// surface parity contract holds by construction: both surfaces
2895 /// route through the SAME
2896 /// [`Classification::point_is_diffusive`] primitive after the
2897 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
2898 /// surface corner-peer pair on the `point_type` axis (with
2899 /// [`Self::point_is_endomorphic`]) whose two projections carry a
2900 /// non-trivial closed-set-internal MUTEX relationship
2901 /// (`point_is_endomorphic ⇒ ¬point_is_diffusive`), distinct from
2902 /// the sibling `data`-axis ephemeral corner-peer pair whose two
2903 /// projections carry a non-trivial IMPLICATION relationship. When
2904 /// the third sibling [`Self::point_is_convergent`] lands, the
2905 /// mutex closes into the full three-way XOR partition composed
2906 /// through the resolver-hop layer as a substrate-wide theorem.
2907 ///
2908 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2909 /// preserves proofs; the classification-`point_type`-axis derived-
2910 /// nullary-boolean probe body composes ONE resolver primitive
2911 /// ([`Self::resolved_classification`]) with ONE
2912 /// [`Classification`] primitive
2913 /// ([`Classification::point_is_diffusive`]) so every downstream
2914 /// (`diffusive-point` fixed tags on both surfaces in tatara-check,
2915 /// future DAG composition / edge-cardinality validators, future
2916 /// variant additions on
2917 /// [`crate::classification::ConvergencePointType`]) binds through
2918 /// the SAME `point_is_diffusive()` shape rather than restating
2919 /// either the resolver walk or the closed-set projection
2920 /// composition at the callsite. THEORY.md §VI.1 — generation over
2921 /// composition; a future
2922 /// [`crate::classification::ConvergencePointType`] variant lands
2923 /// at ONE `ALL` entry + ONE `is_diffusive` arm on the closed set
2924 /// and both surfaces pick it up mechanically.
2925 #[must_use]
2926 pub fn point_is_diffusive(&self) -> bool {
2927 self.resolved_classification().point_is_diffusive()
2928 }
2929
2930 /// Derived-boolean predicate — does this ephemeral spec's
2931 /// resolved [`Classification`]'s
2932 /// [`crate::classification::ConvergencePointType`] project to
2933 /// `true` under
2934 /// [`crate::classification::ConvergencePointType::is_convergent`]?
2935 /// Byte-for-byte peer of
2936 /// [`Classification::point_is_convergent`] wrapped through the
2937 /// [`Self::resolved_classification`] resolver so an operator-
2938 /// omitted `:classification` slot on `(defephemeral …)` still
2939 /// answers via the substrate default. The ONE ephemeral-surface
2940 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
2941 /// derived-nullary-boolean walk on the N→1 fan-in topology-bucket
2942 /// question over the classification-`point_type` axis.
2943 ///
2944 /// # Eighth derived-nullary-boolean peer on the ephemeral surface
2945 ///
2946 /// Peer of [`Self::horizon_terminates`],
2947 /// [`Self::horizon_requires_metric_axes`],
2948 /// [`Self::calm_requires_coordination`],
2949 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
2950 /// [`Self::point_is_endomorphic`], and [`Self::point_is_diffusive`]
2951 /// on the ephemeral surface's (resolver-hop × derived-nullary-
2952 /// bool) shape — the EIGHTH peer overall and the THIRD peer
2953 /// threading the classification-`point_type` axis. Direct-scalar
2954 /// peer of [`Self::point_is_endomorphic`] and
2955 /// [`Self::point_is_diffusive`]: the three compose the SAME
2956 /// resolver hop and the SAME closed-set carrier through the SAME
2957 /// chosen-field baseline discipline, but the answer flips on the
2958 /// baseline — `Gate.is_convergent() = true`, so an ephemeral spec
2959 /// with no `:classification` slot answers `true` HERE (mirror-
2960 /// inverted from the two sibling probes which answer `false`).
2961 /// The resolver-hop shape is byte-identical across all eight
2962 /// peers.
2963 ///
2964 /// # Semantics — resolver hop + derived-nullary-boolean
2965 ///
2966 /// `point_is_convergent()` returns `true` iff
2967 /// `self.resolved_classification().point_is_convergent()`. The
2968 /// resolver returns the authored [`Classification`] when present
2969 /// and the substrate default [`Classification::gate_compute`] on
2970 /// absence. Because [`Classification::gate_compute`] carries
2971 /// [`crate::classification::ConvergencePointType::Gate`] (the
2972 /// canonical convergent barrier), a bare ephemeral spec with no
2973 /// `:classification` slot answers `true` — a regression that
2974 /// dropped the resolver hop, probed the wrong closed-set arm, or
2975 /// inverted the projection fails HERE at ONE narrow substrate
2976 /// site before drifting through every unadorned ephemeral spec's
2977 /// DAG-composition answer.
2978 ///
2979 /// # Compounding — closes the three-way XOR partition on the ephemeral surface
2980 ///
2981 /// The ephemeral require-tag classifier composes this primitive
2982 /// as a fixed tag `convergent-point` on `EPHEMERAL_FIXED_TAG_ARMS`
2983 /// — byte-for-byte peer of the point surface's `convergent-point`
2984 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
2985 /// [`Classification::point_is_convergent`] directly. The two-
2986 /// surface parity contract holds by construction: both surfaces
2987 /// route through the SAME
2988 /// [`Classification::point_is_convergent`] primitive after the
2989 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
2990 /// surface peer on the `point_type` axis closing the mutex pair
2991 /// [`Self::point_is_endomorphic`] / [`Self::point_is_diffusive`]
2992 /// into the FULL three-way XOR partition contract composed
2993 /// through the resolver-hop layer as a substrate-wide theorem.
2994 ///
2995 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
2996 /// preserves proofs; the classification-`point_type`-axis derived-
2997 /// nullary-boolean probe body composes ONE resolver primitive
2998 /// ([`Self::resolved_classification`]) with ONE
2999 /// [`Classification`] primitive
3000 /// ([`Classification::point_is_convergent`]) so every downstream
3001 /// (`convergent-point` fixed tags on both surfaces in tatara-check,
3002 /// future DAG composition / edge-cardinality validators, future
3003 /// variant additions on
3004 /// [`crate::classification::ConvergencePointType`]) binds through
3005 /// the SAME `point_is_convergent()` shape rather than restating
3006 /// either the resolver walk or the closed-set projection
3007 /// composition at the callsite. THEORY.md §VI.1 — generation over
3008 /// composition; a future
3009 /// [`crate::classification::ConvergencePointType`] variant lands
3010 /// at ONE `ALL` entry + ONE `is_convergent` arm on the closed set
3011 /// and both surfaces pick it up mechanically.
3012 #[must_use]
3013 pub fn point_is_convergent(&self) -> bool {
3014 self.resolved_classification().point_is_convergent()
3015 }
3016
3017 /// Derived-boolean predicate — does this ephemeral spec's
3018 /// resolved [`Classification`]'s
3019 /// [`crate::classification::SubstrateType`] project to `true`
3020 /// under [`crate::classification::SubstrateType::is_resource`]?
3021 /// Byte-for-byte peer of
3022 /// [`Classification::substrate_is_resource`] wrapped through the
3023 /// [`Self::resolved_classification`] resolver so an operator-
3024 /// omitted `:classification` slot on `(defephemeral …)` still
3025 /// answers via the substrate default. The ONE ephemeral-surface
3026 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3027 /// derived-nullary-boolean walk on the resource-plane bucket
3028 /// question over the classification-`substrate` axis.
3029 ///
3030 /// # Ninth derived-nullary-boolean peer on the ephemeral surface
3031 ///
3032 /// Peer of [`Self::horizon_terminates`],
3033 /// [`Self::horizon_requires_metric_axes`],
3034 /// [`Self::calm_requires_coordination`],
3035 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3036 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3037 /// and [`Self::point_is_convergent`] on the ephemeral surface's
3038 /// (resolver-hop × derived-nullary-bool) shape — the NINTH peer
3039 /// overall and the FIRST peer threading the classification-
3040 /// `substrate` axis (the fourth of six classification axes
3041 /// participating on this corner, after `horizon`, `calm`,
3042 /// `data_classification`, and `point_type`). The resolver-hop
3043 /// shape is byte-identical across all nine peers.
3044 ///
3045 /// # Semantics — resolver hop + derived-nullary-boolean
3046 ///
3047 /// `substrate_is_resource()` returns `true` iff
3048 /// `self.resolved_classification().substrate_is_resource()`. The
3049 /// resolver returns the authored [`Classification`] when present
3050 /// and the substrate default [`Classification::gate_compute`] on
3051 /// absence. Because [`Classification::gate_compute`] carries
3052 /// [`crate::classification::SubstrateType::Compute`] (the
3053 /// canonical resource-plane substrate), a bare ephemeral spec
3054 /// with no `:classification` slot answers `true` — a regression
3055 /// that dropped the resolver hop, probed the wrong closed-set
3056 /// arm, or inverted the projection fails HERE at ONE narrow
3057 /// substrate site before drifting through every unadorned
3058 /// ephemeral spec's plane-baseline answer.
3059 ///
3060 /// # Compounding — opens the substrate axis on the ephemeral surface
3061 ///
3062 /// The ephemeral require-tag classifier composes this primitive
3063 /// as a fixed tag `resource-substrate` on
3064 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3065 /// surface's `resource-substrate` fixed tag on
3066 /// `POINT_FIXED_TAG_ARMS` via
3067 /// [`Classification::substrate_is_resource`] directly. The two-
3068 /// surface parity contract holds by construction: both surfaces
3069 /// route through the SAME
3070 /// [`Classification::substrate_is_resource`] primitive after the
3071 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
3072 /// surface peer on the `substrate` axis — future sibling
3073 /// projections [`crate::classification::SubstrateType::is_policy`]
3074 /// and [`crate::classification::SubstrateType::is_telemetry`]
3075 /// compose byte-identically as future tenth + eleventh peers,
3076 /// closing the axis into a proven-repeatable three-peer sub-
3077 /// corner exactly as the `point_type` axis was closed on this
3078 /// surface by
3079 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3080 ///
3081 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3082 /// preserves proofs; the classification-`substrate`-axis derived-
3083 /// nullary-boolean probe body composes ONE resolver primitive
3084 /// ([`Self::resolved_classification`]) with ONE
3085 /// [`Classification`] primitive
3086 /// ([`Classification::substrate_is_resource`]) so every
3087 /// downstream (`resource-substrate` fixed tags on both surfaces
3088 /// in tatara-check, future plane-baseline / compliance-baseline
3089 /// selectors, future variant additions on
3090 /// [`crate::classification::SubstrateType`]) binds through the
3091 /// SAME `substrate_is_resource()` shape rather than restating
3092 /// either the resolver walk or the closed-set projection
3093 /// composition at the callsite. THEORY.md §VI.1 — generation
3094 /// over composition; a future
3095 /// [`crate::classification::SubstrateType`] variant lands at ONE
3096 /// `ALL` entry + ONE `is_resource` arm on the closed set and
3097 /// both surfaces pick it up mechanically.
3098 #[must_use]
3099 pub fn substrate_is_resource(&self) -> bool {
3100 self.resolved_classification().substrate_is_resource()
3101 }
3102
3103 /// Derived-boolean predicate — does this ephemeral spec's
3104 /// resolved [`Classification`]'s
3105 /// [`crate::classification::SubstrateType`] project to `true`
3106 /// under [`crate::classification::SubstrateType::is_policy`]?
3107 /// Byte-for-byte peer of
3108 /// [`Classification::substrate_is_policy`] wrapped through the
3109 /// [`Self::resolved_classification`] resolver so an operator-
3110 /// omitted `:classification` slot on `(defephemeral …)` still
3111 /// answers via the substrate default. The ONE ephemeral-surface
3112 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3113 /// derived-nullary-boolean walk on the policy-plane bucket
3114 /// question over the classification-`substrate` axis.
3115 ///
3116 /// # Tenth derived-nullary-boolean peer on the ephemeral surface
3117 ///
3118 /// Peer of [`Self::horizon_terminates`],
3119 /// [`Self::horizon_requires_metric_axes`],
3120 /// [`Self::calm_requires_coordination`],
3121 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3122 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3123 /// [`Self::point_is_convergent`], and
3124 /// [`Self::substrate_is_resource`] on the ephemeral surface's
3125 /// (resolver-hop × derived-nullary-bool) shape — the TENTH peer
3126 /// overall and the SECOND peer threading the classification-
3127 /// `substrate` axis, promoting that axis on this surface from a
3128 /// proven-repeatable one-off to a proven-repeatable pair.
3129 /// FIRST ephemeral-surface substrate-axis corner-peer pair
3130 /// carrying a non-trivial closed-set-internal MUTEX relationship
3131 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`), structural
3132 /// twin of the sibling `point_type`-axis MUTEX pair sealed on
3133 /// this surface by
3134 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
3135 /// The resolver-hop shape is byte-identical across all ten peers.
3136 ///
3137 /// # Semantics — resolver hop + derived-nullary-boolean
3138 ///
3139 /// `substrate_is_policy()` returns `true` iff
3140 /// `self.resolved_classification().substrate_is_policy()`. The
3141 /// resolver returns the authored [`Classification`] when present
3142 /// and the substrate default [`Classification::gate_compute`] on
3143 /// absence. Because [`Classification::gate_compute`] carries
3144 /// [`crate::classification::SubstrateType::Compute`] (the
3145 /// canonical resource-plane substrate, NOT a policy plane), a
3146 /// bare ephemeral spec with no `:classification` slot answers
3147 /// `false` — a regression that dropped the resolver hop, probed
3148 /// the wrong closed-set arm, or inverted the projection fails
3149 /// HERE at ONE narrow substrate site before drifting through
3150 /// every unadorned ephemeral spec's plane-baseline answer.
3151 ///
3152 /// # Compounding — second substrate-axis peer on the ephemeral surface
3153 ///
3154 /// The ephemeral require-tag classifier composes this primitive
3155 /// as a fixed tag `policy-substrate` on
3156 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3157 /// surface's `policy-substrate` fixed tag on
3158 /// `POINT_FIXED_TAG_ARMS` via
3159 /// [`Classification::substrate_is_policy`] directly. The two-
3160 /// surface parity contract holds by construction: both surfaces
3161 /// route through the SAME
3162 /// [`Classification::substrate_is_policy`] primitive after the
3163 /// ephemeral surface pays ONE resolver hop. SECOND ephemeral-
3164 /// surface peer on the `substrate` axis — sibling projection
3165 /// [`crate::classification::SubstrateType::is_telemetry`]
3166 /// composes byte-identically as a future eleventh peer, closing
3167 /// the axis into a proven-repeatable three-peer sub-corner
3168 /// exactly as the `point_type` axis was closed on this surface
3169 /// by
3170 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3171 ///
3172 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3173 /// preserves proofs; the classification-`substrate`-axis derived-
3174 /// nullary-boolean probe body composes ONE resolver primitive
3175 /// ([`Self::resolved_classification`]) with ONE
3176 /// [`Classification`] primitive
3177 /// ([`Classification::substrate_is_policy`]) so every
3178 /// downstream (`policy-substrate` fixed tags on both surfaces
3179 /// in tatara-check, future plane-baseline / compliance-baseline
3180 /// selectors, future variant additions on
3181 /// [`crate::classification::SubstrateType`]) binds through the
3182 /// SAME `substrate_is_policy()` shape rather than restating
3183 /// either the resolver walk or the closed-set projection
3184 /// composition at the callsite. THEORY.md §VI.1 — generation
3185 /// over composition; a future
3186 /// [`crate::classification::SubstrateType`] variant lands at ONE
3187 /// `ALL` entry + ONE `is_policy` arm on the closed set and
3188 /// both surfaces pick it up mechanically.
3189 #[must_use]
3190 pub fn substrate_is_policy(&self) -> bool {
3191 self.resolved_classification().substrate_is_policy()
3192 }
3193
3194 /// Derived-boolean predicate — does this ephemeral spec's
3195 /// resolved [`Classification`]'s
3196 /// [`crate::classification::SubstrateType`] project to `true`
3197 /// under [`crate::classification::SubstrateType::is_telemetry`]?
3198 /// Byte-for-byte peer of
3199 /// [`Classification::substrate_is_telemetry`] wrapped through
3200 /// the [`Self::resolved_classification`] resolver so an operator-
3201 /// omitted `:classification` slot on `(defephemeral …)` still
3202 /// answers via the substrate default. The ONE ephemeral-surface
3203 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
3204 /// derived-nullary-boolean walk on the telemetry-plane bucket
3205 /// question over the classification-`substrate` axis.
3206 ///
3207 /// # Eleventh derived-nullary-boolean peer on the ephemeral surface — CLOSES the substrate axis
3208 ///
3209 /// Peer of [`Self::horizon_terminates`],
3210 /// [`Self::horizon_requires_metric_axes`],
3211 /// [`Self::calm_requires_coordination`],
3212 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
3213 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
3214 /// [`Self::point_is_convergent`], [`Self::substrate_is_resource`],
3215 /// and [`Self::substrate_is_policy`] on the ephemeral surface's
3216 /// (resolver-hop × derived-nullary-bool) shape — the ELEVENTH
3217 /// peer overall and the THIRD peer threading the classification-
3218 /// `substrate` axis. This peer CLOSES the substrate axis on the
3219 /// ephemeral surface into the FULL three-way XOR partition
3220 /// contract `substrate_is_resource ⊕ substrate_is_policy ⊕
3221 /// substrate_is_telemetry` — sealed on this surface by
3222 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
3223 /// the resolver-hop peer of the parent-composed
3224 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`.
3225 /// Structural twin of the sibling `point_type`-axis ternary lift
3226 /// sealed on this surface by
3227 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3228 /// The resolver-hop shape is byte-identical across all eleven
3229 /// peers.
3230 ///
3231 /// # Semantics — resolver hop + derived-nullary-boolean
3232 ///
3233 /// `substrate_is_telemetry()` returns `true` iff
3234 /// `self.resolved_classification().substrate_is_telemetry()`.
3235 /// The resolver returns the authored [`Classification`] when
3236 /// present and the substrate default [`Classification::gate_compute`]
3237 /// on absence. Because [`Classification::gate_compute`] carries
3238 /// [`crate::classification::SubstrateType::Compute`] (the
3239 /// canonical resource-plane substrate, NOT a telemetry plane),
3240 /// a bare ephemeral spec with no `:classification` slot answers
3241 /// `false` — a regression that dropped the resolver hop, probed
3242 /// the wrong closed-set arm, or inverted the projection fails
3243 /// HERE at ONE narrow substrate site before drifting through
3244 /// every unadorned ephemeral spec's plane-baseline answer.
3245 ///
3246 /// # Compounding — CLOSES the substrate axis on the ephemeral surface
3247 ///
3248 /// The ephemeral require-tag classifier composes this primitive
3249 /// as a fixed tag `telemetry-substrate` on
3250 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3251 /// surface's `telemetry-substrate` fixed tag on
3252 /// `POINT_FIXED_TAG_ARMS` via
3253 /// [`Classification::substrate_is_telemetry`] directly. The two-
3254 /// surface parity contract holds by construction: both surfaces
3255 /// route through the SAME
3256 /// [`Classification::substrate_is_telemetry`] primitive after the
3257 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
3258 /// surface peer on the `substrate` axis — closes the axis into a
3259 /// proven-repeatable three-peer sub-corner exactly as the
3260 /// `point_type` axis was closed on this surface by
3261 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
3262 ///
3263 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3264 /// preserves proofs; the classification-`substrate`-axis derived-
3265 /// nullary-boolean probe body composes ONE resolver primitive
3266 /// ([`Self::resolved_classification`]) with ONE
3267 /// [`Classification`] primitive
3268 /// ([`Classification::substrate_is_telemetry`]) so every
3269 /// downstream (`telemetry-substrate` fixed tags on both surfaces
3270 /// in tatara-check, future plane-baseline / compliance-baseline
3271 /// selectors, future variant additions on
3272 /// [`crate::classification::SubstrateType`]) binds through the
3273 /// SAME `substrate_is_telemetry()` shape rather than restating
3274 /// either the resolver walk or the closed-set projection
3275 /// composition at the callsite. THEORY.md §VI.1 — generation
3276 /// over composition; a future
3277 /// [`crate::classification::SubstrateType`] variant lands at ONE
3278 /// `ALL` entry + ONE `is_telemetry` arm on the closed set and
3279 /// both surfaces pick it up mechanically.
3280 #[must_use]
3281 pub fn substrate_is_telemetry(&self) -> bool {
3282 self.resolved_classification().substrate_is_telemetry()
3283 }
3284
3285 /// Derived-boolean predicate — does this ephemeral spec's
3286 /// resolved [`Classification`]'s
3287 /// [`crate::classification::CalmClassification`] project to `true`
3288 /// under [`crate::classification::CalmClassification::is_monotone`]?
3289 /// Byte-for-byte peer of [`Classification::calm_is_monotone`]
3290 /// wrapped through the [`Self::resolved_classification`] resolver
3291 /// so an operator-omitted `:classification` slot on
3292 /// `(defephemeral …)` still answers via the substrate default.
3293 /// The ONE ephemeral-surface substrate primitive that owns the
3294 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3295 /// CALM-monotone-plane question — the positive framing peer of
3296 /// [`Self::calm_requires_coordination`].
3297 ///
3298 /// # Twelfth derived-nullary-boolean peer on the ephemeral surface — CLOSES the calm axis
3299 ///
3300 /// Peer of [`Self::horizon_terminates`],
3301 /// [`Self::horizon_requires_metric_axes`],
3302 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3303 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3304 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3305 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3306 /// and [`Self::substrate_is_telemetry`] on the ephemeral
3307 /// surface's (resolver-hop × derived-nullary-bool) shape — the
3308 /// TWELFTH peer overall and the SECOND peer threading the
3309 /// classification-`calm` axis. This peer CLOSES the calm axis
3310 /// on the ephemeral surface into the FULL binary XOR partition
3311 /// contract `calm_is_monotone ⊕ calm_requires_coordination` —
3312 /// sealed on this surface by
3313 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
3314 /// the resolver-hop peer of the parent-composed
3315 /// `classification_calm_probes_form_binary_xor_partition_over_all`.
3316 /// Structural twin of the sibling horizon-axis binary XOR
3317 /// sealed on the closed set by
3318 /// `horizon_kind_terminate_xor_requires_metric_axes`, lifted
3319 /// through the resolver hop to the ephemeral surface. The
3320 /// resolver-hop shape is byte-identical across all twelve peers.
3321 ///
3322 /// # Semantics — resolver hop + derived-nullary-boolean
3323 ///
3324 /// `calm_is_monotone()` returns `true` iff
3325 /// `self.resolved_classification().calm_is_monotone()`. The
3326 /// resolver returns the authored [`Classification`] when present
3327 /// and the substrate default [`Classification::gate_compute`] on
3328 /// absence. Because [`Classification::gate_compute`] carries
3329 /// [`crate::classification::CalmClassification::default =
3330 /// Monotone`] via `#[default]`, a bare ephemeral spec with no
3331 /// `:classification` slot answers `true` — every unadorned
3332 /// `(defephemeral …)` reads as gossip-eligible under the
3333 /// positive CALM framing, safe under Hellerstein's theorem
3334 /// (monotone operations distribute without coordination). A
3335 /// regression that dropped the resolver hop, probed the wrong
3336 /// closed-set arm, or inverted the projection fails HERE at ONE
3337 /// narrow substrate site before drifting through every
3338 /// unadorned ephemeral spec's positive-CALM-framing answer.
3339 /// Mirror-inverted from the sibling
3340 /// `calm_requires_coordination_probes_false_on_absent_classification`
3341 /// (both walk the SAME defaulted `calm` field, so
3342 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
3343 /// closed set's disjoint XOR partition).
3344 ///
3345 /// # Compounding — CLOSES the calm axis on the ephemeral surface
3346 ///
3347 /// The ephemeral require-tag classifier composes this primitive
3348 /// as a fixed tag `monotone-calm` on `EPHEMERAL_FIXED_TAG_ARMS`
3349 /// — byte-for-byte peer of the point surface's `monotone-calm`
3350 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3351 /// [`Classification::calm_is_monotone`] directly. The two-
3352 /// surface parity contract holds by construction: both surfaces
3353 /// route through the SAME [`Classification::calm_is_monotone`]
3354 /// primitive after the ephemeral surface pays ONE resolver hop.
3355 /// SECOND ephemeral-surface peer on the `calm` axis — CLOSES the
3356 /// axis into a proven-repeatable two-peer sub-corner exactly as
3357 /// the `horizon` axis is closed on the closed-set layer by
3358 /// `horizon_kind_terminate_xor_requires_metric_axes`.
3359 ///
3360 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3361 /// preserves proofs; the classification-`calm`-axis derived-
3362 /// nullary-boolean probe body composes ONE resolver primitive
3363 /// ([`Self::resolved_classification`]) with ONE
3364 /// [`Classification`] primitive
3365 /// ([`Classification::calm_is_monotone`]) so every downstream
3366 /// (`monotone-calm` fixed tags on both surfaces in tatara-check,
3367 /// future scheduler / gossip-eligibility validators reading the
3368 /// positive CALM framing, future variant additions on
3369 /// [`crate::classification::CalmClassification`]) binds through
3370 /// the SAME `calm_is_monotone()` shape rather than restating
3371 /// either the resolver walk or the closed-set projection
3372 /// composition at the callsite. THEORY.md §VI.1 — generation
3373 /// over composition; a future
3374 /// [`crate::classification::CalmClassification`] variant lands
3375 /// at ONE `ALL` entry + ONE `is_monotone` arm on the closed set
3376 /// and both surfaces pick it up mechanically.
3377 #[must_use]
3378 pub fn calm_is_monotone(&self) -> bool {
3379 self.resolved_classification().calm_is_monotone()
3380 }
3381
3382 /// Derived-boolean predicate — does this ephemeral spec's
3383 /// resolved [`Classification`]'s
3384 /// [`crate::classification::DataClassification`] project to `true`
3385 /// under [`crate::classification::DataClassification::is_public`]?
3386 /// Byte-for-byte peer of [`Classification::data_is_public`]
3387 /// wrapped through the [`Self::resolved_classification`] resolver
3388 /// so an operator-omitted `:classification` slot on
3389 /// `(defephemeral …)` still answers via the substrate default.
3390 /// The ONE ephemeral-surface substrate primitive that owns the
3391 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3392 /// freely-distributable-data question — the positive framing peer
3393 /// of [`Self::data_is_restricted`].
3394 ///
3395 /// # Thirteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the data axis
3396 ///
3397 /// Peer of [`Self::horizon_terminates`],
3398 /// [`Self::horizon_requires_metric_axes`],
3399 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3400 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3401 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3402 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3403 /// [`Self::substrate_is_telemetry`], and [`Self::calm_is_monotone`]
3404 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
3405 /// shape — the THIRTEENTH peer overall and the THIRD peer
3406 /// threading the classification-`data_classification` axis. This
3407 /// peer CLOSES the data axis on the ephemeral surface into the
3408 /// FULL binary XOR partition contract
3409 /// `data_is_public ⊕ data_is_restricted` — sealed on this surface
3410 /// by `ephemeral_data_probes_form_binary_xor_partition_over_all`,
3411 /// the resolver-hop peer of the parent-composed
3412 /// `classification_data_probes_form_binary_xor_partition_over_all`.
3413 /// Structural twin of the sibling calm-axis binary XOR sealed on
3414 /// this surface by
3415 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
3416 /// lifted through the resolver hop from the six-variant data-axis
3417 /// closed set to the ephemeral surface. The resolver-hop shape is
3418 /// byte-identical across all thirteen peers.
3419 ///
3420 /// # Semantics — resolver hop + derived-nullary-boolean
3421 ///
3422 /// `data_is_public()` returns `true` iff
3423 /// `self.resolved_classification().data_is_public()`. The
3424 /// resolver returns the authored [`Classification`] when present
3425 /// and the substrate default [`Classification::gate_compute`] on
3426 /// absence. Because [`Classification::gate_compute`] carries
3427 /// [`crate::classification::DataClassification::default =
3428 /// Internal`] via `#[default]`, a bare ephemeral spec with no
3429 /// `:classification` slot answers `false` — every unadorned
3430 /// `(defephemeral …)` reads as access-controlled by default (safe
3431 /// under compliance baseline: an operator must deliberately opt
3432 /// the dataset into public distribution rather than the substrate
3433 /// silently promoting an unadorned Process onto the freely-
3434 /// distributable path). A regression that dropped the resolver
3435 /// hop, probed the wrong closed-set arm, or inverted the
3436 /// projection fails HERE at ONE narrow substrate site before
3437 /// drifting through every unadorned ephemeral spec's positive-
3438 /// distribution-framing answer. Mirror-inverted from the sibling
3439 /// `data_is_restricted_probes_true_on_absent_classification`
3440 /// (both walk the SAME defaulted `data_classification` field, so
3441 /// `is_restricted = true` ⇒ `is_public = false` on the closed
3442 /// set's disjoint XOR partition).
3443 ///
3444 /// # Compounding — CLOSES the data axis on the ephemeral surface
3445 ///
3446 /// The ephemeral require-tag classifier composes this primitive
3447 /// as a fixed tag `public-data` on `EPHEMERAL_FIXED_TAG_ARMS`
3448 /// — byte-for-byte peer of the point surface's `public-data`
3449 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
3450 /// [`Classification::data_is_public`] directly. The two-
3451 /// surface parity contract holds by construction: both surfaces
3452 /// route through the SAME [`Classification::data_is_public`]
3453 /// primitive after the ephemeral surface pays ONE resolver hop.
3454 /// THIRD ephemeral-surface peer on the `data_classification` axis
3455 /// — CLOSES the axis into a proven-repeatable three-peer sub-
3456 /// corner (data_is_regulated, data_is_restricted, data_is_public)
3457 /// whose complementary XOR partition seals on the closed set by
3458 /// `data_classification_public_xor_restricted` and composes
3459 /// through the resolver hop as a substrate-wide theorem.
3460 ///
3461 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3462 /// preserves proofs; the classification-`data_classification`-axis
3463 /// derived-nullary-boolean probe body composes ONE resolver
3464 /// primitive ([`Self::resolved_classification`]) with ONE
3465 /// [`Classification`] primitive
3466 /// ([`Classification::data_is_public`]) so every downstream
3467 /// (`public-data` fixed tags on both surfaces in tatara-check,
3468 /// future compliance-baseline / audit-log-optional validators
3469 /// reading the positive distribution framing, future variant
3470 /// additions on
3471 /// [`crate::classification::DataClassification`]) binds through
3472 /// the SAME `data_is_public()` shape rather than restating either
3473 /// the resolver walk or the closed-set projection composition at
3474 /// the callsite. THEORY.md §VI.1 — generation over composition; a
3475 /// future [`crate::classification::DataClassification`] variant
3476 /// lands at ONE `ALL` entry + ONE `is_public` arm on the closed
3477 /// set and both surfaces pick it up mechanically.
3478 #[must_use]
3479 pub fn data_is_public(&self) -> bool {
3480 self.resolved_classification().data_is_public()
3481 }
3482
3483 /// Derived-boolean predicate — does this ephemeral spec's resolved
3484 /// [`Classification`]'s
3485 /// [`crate::classification::Horizon::direction`] slot (defaulted
3486 /// through [`crate::classification::OptimizationDirection::default =
3487 /// Minimize`] on absence) project to `true` under
3488 /// [`crate::classification::OptimizationDirection::prefers_lower`]?
3489 /// Byte-for-byte peer of
3490 /// [`crate::classification::Classification::direction_prefers_lower`]
3491 /// wrapped through the [`Self::resolved_classification`] resolver so
3492 /// an operator-omitted `:classification` slot on
3493 /// `(defephemeral …)` still answers via the substrate default. The
3494 /// ONE ephemeral-surface substrate primitive that owns the
3495 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3496 /// lower-is-better optimization-polarity question.
3497 ///
3498 /// # Fourteenth derived-nullary-boolean peer on the ephemeral surface — opens the optimization-direction axis
3499 ///
3500 /// Peer of the thirteen prior nullary-boolean substrate primitives
3501 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
3502 /// [`Self::horizon_requires_metric_axes`],
3503 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3504 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3505 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3506 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3507 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
3508 /// [`Self::data_is_public`]) on the ephemeral surface's
3509 /// (resolver-hop × derived-nullary-bool) shape — the FOURTEENTH
3510 /// peer overall and the FIRST peer threading the classification-
3511 /// `horizon.direction` axis on this surface. Opens the SIXTH
3512 /// classification axis into the ephemeral fixed-tag algebra after
3513 /// the horizon, calm, data, point, and substrate axes. The
3514 /// resolver-hop shape is byte-identical across all fourteen peers.
3515 ///
3516 /// # Semantics — resolver hop + derived-nullary-boolean
3517 ///
3518 /// `direction_prefers_lower()` returns `true` iff
3519 /// `self.resolved_classification().direction_prefers_lower()`. The
3520 /// resolver returns the authored [`Classification`] when present
3521 /// and the substrate default [`Classification::gate_compute`] on
3522 /// absence. Because [`Classification::gate_compute`] carries
3523 /// `horizon: Horizon::default()` whose `direction` field is `None`,
3524 /// and [`crate::classification::OptimizationDirection::default =
3525 /// Minimize`] projects `prefers_lower = true`, a bare ephemeral
3526 /// spec with no `:classification` slot answers `true` — every
3527 /// unadorned `(defephemeral …)` reads as lower-is-better under the
3528 /// substrate polarity default (safe under the asymptotic-health
3529 /// rate-window evaluator's convention: an operator must
3530 /// deliberately opt into Maximize polarity rather than the
3531 /// substrate silently flipping every unadorned Process onto the
3532 /// higher-is-better path). A regression that dropped the resolver
3533 /// hop, probed the wrong closed-set arm, or inverted the projection
3534 /// fails HERE at ONE narrow substrate site before drifting through
3535 /// every unadorned ephemeral spec's rate-window evaluator polarity.
3536 ///
3537 /// # Compounding — opens the optimization-direction axis on the ephemeral surface
3538 ///
3539 /// The ephemeral require-tag classifier composes this primitive as
3540 /// a fixed tag `prefers-lower-direction` on
3541 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3542 /// surface's `prefers-lower-direction` fixed tag on
3543 /// `POINT_FIXED_TAG_ARMS` via
3544 /// [`Classification::direction_prefers_lower`] directly. The
3545 /// two-surface parity contract holds by construction: both surfaces
3546 /// route through the SAME [`Classification::direction_prefers_lower`]
3547 /// primitive after the ephemeral surface pays ONE resolver hop.
3548 /// A future antisymmetric peer (`direction_prefers_higher`) closes
3549 /// the binary XOR partition on this axis — mirror of the calm-axis
3550 /// (`monotone-calm ⊕ coordination-required`) and data-axis
3551 /// (`public-data ⊕ data-restricted`) closures on this surface.
3552 ///
3553 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3554 /// preserves proofs; the classification-`horizon.direction`-axis
3555 /// derived-nullary-boolean probe body composes ONE resolver
3556 /// primitive ([`Self::resolved_classification`]) with ONE
3557 /// [`Classification`] primitive
3558 /// ([`Classification::direction_prefers_lower`]) so every
3559 /// downstream (the `prefers-lower-direction` fixed tags on both
3560 /// surfaces in tatara-check, future asymptotic-health rate-window
3561 /// / regression-detector evaluators, future variant additions on
3562 /// [`crate::classification::OptimizationDirection`]) binds through
3563 /// the SAME `direction_prefers_lower()` shape rather than restating
3564 /// either the resolver walk or the closed-set projection
3565 /// composition at the callsite. THEORY.md §VI.1 — generation over
3566 /// composition; a future
3567 /// [`crate::classification::OptimizationDirection`] variant lands
3568 /// at ONE `ALL` entry + ONE `prefers_lower` arm on the closed set
3569 /// and both surfaces pick it up mechanically.
3570 #[must_use]
3571 pub fn direction_prefers_lower(&self) -> bool {
3572 self.resolved_classification().direction_prefers_lower()
3573 }
3574
3575 /// POSITIVE-FRAMING PEER of [`Self::direction_prefers_lower`] —
3576 /// does this ephemeral spec's resolved [`Classification`]'s
3577 /// [`crate::classification::Horizon::direction`] slot (defaulted
3578 /// through [`crate::classification::OptimizationDirection::default =
3579 /// Minimize`] on absence) project to `true` under
3580 /// [`crate::classification::OptimizationDirection::prefers_higher`]?
3581 /// Byte-for-byte peer of
3582 /// [`crate::classification::Classification::direction_prefers_higher`]
3583 /// wrapped through the [`Self::resolved_classification`] resolver
3584 /// so an operator-omitted `:classification` slot on
3585 /// `(defephemeral …)` still answers via the substrate default. The
3586 /// ONE ephemeral-surface substrate primitive that owns the
3587 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3588 /// higher-is-better optimization-polarity question.
3589 ///
3590 /// # Fifteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the optimization-direction axis
3591 ///
3592 /// Peer of the fourteen prior nullary-boolean substrate primitives
3593 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
3594 /// [`Self::horizon_requires_metric_axes`],
3595 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3596 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3597 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3598 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3599 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
3600 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`]) on
3601 /// the ephemeral surface's (resolver-hop × derived-nullary-bool)
3602 /// shape — the FIFTEENTH peer overall and the SECOND peer
3603 /// threading the classification-`horizon.direction` axis on this
3604 /// surface. CLOSES the SIXTH classification axis into a binary XOR
3605 /// partition on the ephemeral surface after the horizon, calm,
3606 /// data, point, and substrate axes — completing the axis-coverage
3607 /// milestone on this surface: ALL SIX classification axes now
3608 /// have their partitions closed at the ephemeral-surface derived-
3609 /// nullary corner. The resolver-hop shape is byte-identical across
3610 /// all fifteen peers.
3611 ///
3612 /// # Semantics — resolver hop + derived-nullary-boolean
3613 ///
3614 /// `direction_prefers_higher()` returns `true` iff
3615 /// `self.resolved_classification().direction_prefers_higher()`.
3616 /// The resolver returns the authored [`Classification`] when
3617 /// present and the substrate default
3618 /// [`Classification::gate_compute`] on absence. Because
3619 /// [`Classification::gate_compute`] carries `horizon:
3620 /// Horizon::default()` whose `direction` field is `None`, and
3621 /// [`crate::classification::OptimizationDirection::default =
3622 /// Minimize`] projects `prefers_higher = false`, a bare ephemeral
3623 /// spec with no `:classification` slot answers `false` — every
3624 /// unadorned `(defephemeral …)` reads as lower-is-better under the
3625 /// substrate polarity default (safe under the asymptotic-health
3626 /// rate-window evaluator's convention: an operator must
3627 /// deliberately opt into Maximize polarity rather than the
3628 /// substrate silently flipping every unadorned Process onto the
3629 /// higher-is-better path). A regression that dropped the resolver
3630 /// hop, probed the wrong closed-set arm, or inverted the
3631 /// projection fails HERE at ONE narrow substrate site before
3632 /// drifting through every unadorned ephemeral spec's rate-window
3633 /// evaluator polarity.
3634 ///
3635 /// # Compounding — CLOSES the optimization-direction axis on the ephemeral surface
3636 ///
3637 /// The ephemeral require-tag classifier composes this primitive as
3638 /// a fixed tag `prefers-higher-direction` on
3639 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3640 /// surface's `prefers-higher-direction` fixed tag on
3641 /// `POINT_FIXED_TAG_ARMS` via
3642 /// [`Classification::direction_prefers_higher`] directly. The
3643 /// two-surface parity contract holds by construction: both
3644 /// surfaces route through the SAME
3645 /// [`Classification::direction_prefers_higher`] primitive after
3646 /// the ephemeral surface pays ONE resolver hop. SECOND
3647 /// optimization-direction-axis peer CLOSES the axis into the FULL
3648 /// binary XOR partition contract on this surface — the resolver-
3649 /// hop peer of the parent-composed
3650 /// `classification_direction_probes_form_binary_xor_partition_over_all`,
3651 /// mirror of the calm-axis (`monotone-calm ⊕ coordination-required`)
3652 /// and data-axis (`public-data ⊕ data-restricted`) closures on
3653 /// this surface.
3654 ///
3655 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3656 /// preserves proofs; the classification-`horizon.direction`-axis
3657 /// derived-nullary-boolean probe body composes ONE resolver
3658 /// primitive ([`Self::resolved_classification`]) with ONE
3659 /// [`Classification`] primitive
3660 /// ([`Classification::direction_prefers_higher`]) so every
3661 /// downstream (the `prefers-higher-direction` fixed tags on both
3662 /// surfaces in tatara-check, future asymptotic-health rate-window
3663 /// / regression-detector evaluators, future variant additions on
3664 /// [`crate::classification::OptimizationDirection`]) binds through
3665 /// the SAME `direction_prefers_higher()` shape rather than
3666 /// restating either the resolver walk or the closed-set projection
3667 /// composition at the callsite. THEORY.md §VI.1 — generation over
3668 /// composition; a future
3669 /// [`crate::classification::OptimizationDirection`] variant lands
3670 /// at ONE `ALL` entry + ONE `prefers_higher` arm on the closed set
3671 /// and both surfaces pick it up mechanically.
3672 #[must_use]
3673 pub fn direction_prefers_higher(&self) -> bool {
3674 self.resolved_classification().direction_prefers_higher()
3675 }
3676
3677 /// Derived-boolean predicate — does this ephemeral spec's resolved
3678 /// [`Classification`]'s `point_type` slot project to `Arity::One`
3679 /// under
3680 /// [`crate::classification::ConvergencePointType::input_arity`]?
3681 /// Byte-for-byte peer of
3682 /// [`crate::classification::Classification::input_arity_is_one`]
3683 /// wrapped through the [`Self::resolved_classification`] resolver
3684 /// so an operator-omitted `:classification` slot on
3685 /// `(defephemeral …)` still answers via the substrate default. The
3686 /// ONE ephemeral-surface substrate primitive that owns the
3687 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3688 /// single-input side of the DAG-composition input-arity projection.
3689 ///
3690 /// # Sixteenth derived-nullary-boolean peer on the ephemeral surface — opens the input-arity axis
3691 ///
3692 /// Peer of the fifteen prior nullary-boolean substrate primitives
3693 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
3694 /// [`Self::horizon_requires_metric_axes`],
3695 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3696 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3697 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3698 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3699 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
3700 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
3701 /// [`Self::direction_prefers_higher`]) on the ephemeral surface's
3702 /// (resolver-hop × derived-nullary-bool) shape — the SIXTEENTH
3703 /// peer overall and the FIRST peer threading the classification-
3704 /// `point_type`-derived input-arity axis on this surface. Opens
3705 /// the SEVENTH classification axis into the ephemeral fixed-tag
3706 /// algebra after the horizon, calm, data, point-type, substrate,
3707 /// and optimization-direction axes. First peer on the derived-
3708 /// typed-projection stratum of the ephemeral surface — composes
3709 /// an extra closed-set-level projection hop
3710 /// ([`crate::classification::ConvergencePointType::input_arity`])
3711 /// compared to the sibling `point_is_*` triple that walks the raw
3712 /// `point_type` slot through the resolver. The resolver-hop shape
3713 /// is byte-identical across all sixteen peers.
3714 ///
3715 /// # Semantics — resolver hop + derived-nullary-boolean
3716 ///
3717 /// `input_arity_is_one()` returns `true` iff
3718 /// `self.resolved_classification().input_arity_is_one()`. The
3719 /// resolver returns the authored [`Classification`] when present
3720 /// and the substrate default [`Classification::gate_compute`] on
3721 /// absence. Because [`Classification::gate_compute`] carries
3722 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
3723 /// ephemeral spec with no `:classification` slot answers `false` —
3724 /// every unadorned `(defephemeral …)` lands in the multi-input
3725 /// bucket under the substrate default (`Gate` gates a
3726 /// many-to-one bucket dispatch, so the single-input bucket only
3727 /// applies to operator-authored specs on the `Transform | Fork |
3728 /// Broadcast | Observe` arms). A regression that dropped the
3729 /// resolver hop, probed the wrong closed-set arm, or crossed the
3730 /// wires with the sibling
3731 /// [`crate::classification::ConvergencePointType::output_arity`]
3732 /// projection (which disagrees on six of the eight variants) fails
3733 /// HERE at ONE narrow substrate site before drifting through
3734 /// every unadorned ephemeral spec's DAG-composition input-arity
3735 /// audit.
3736 ///
3737 /// # Compounding — opens the input-arity axis on the ephemeral surface
3738 ///
3739 /// The ephemeral require-tag classifier will compose this
3740 /// primitive as a fixed tag `single-input-arity` on
3741 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3742 /// surface's `single-input-arity` fixed tag on
3743 /// `POINT_FIXED_TAG_ARMS` via
3744 /// [`Classification::input_arity_is_one`] directly. The
3745 /// two-surface parity contract holds by construction: both
3746 /// surfaces route through the SAME
3747 /// [`Classification::input_arity_is_one`] primitive after the
3748 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
3749 /// peer ([`Self::input_arity_is_many`]) closes the binary XOR
3750 /// partition on this axis — mirror of the calm-axis
3751 /// (`monotone-calm ⊕ coordination-required`), data-axis
3752 /// (`public-data ⊕ data-restricted`), and optimization-direction-
3753 /// axis (`prefers-lower-direction ⊕ prefers-higher-direction`)
3754 /// closures on this surface.
3755 ///
3756 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3757 /// preserves proofs; the classification-`point_type`-derived
3758 /// input-arity-axis derived-nullary-boolean probe body composes
3759 /// ONE resolver primitive ([`Self::resolved_classification`])
3760 /// with ONE [`Classification`] primitive
3761 /// ([`Classification::input_arity_is_one`]) so every downstream
3762 /// (the future `single-input-arity` fixed tag on the ephemeral
3763 /// surface in tatara-check, future DAG-composition input-arity
3764 /// validators keying on the single-input framing, future variant
3765 /// additions on
3766 /// [`crate::classification::ConvergencePointType`]) binds through
3767 /// the SAME `input_arity_is_one()` shape rather than restating
3768 /// either the resolver walk or the two-hop closed-set projection
3769 /// composition at the callsite. THEORY.md §VI.1 — generation over
3770 /// composition; a future
3771 /// [`crate::classification::ConvergencePointType`] variant lands
3772 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
3773 /// and both surfaces pick it up mechanically.
3774 #[must_use]
3775 pub fn input_arity_is_one(&self) -> bool {
3776 self.resolved_classification().input_arity_is_one()
3777 }
3778
3779 /// ANTISYMMETRIC PEER of [`Self::input_arity_is_one`] — does
3780 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
3781 /// slot project to `Arity::Many` under
3782 /// [`crate::classification::ConvergencePointType::input_arity`]?
3783 /// Byte-for-byte peer of
3784 /// [`crate::classification::Classification::input_arity_is_many`]
3785 /// wrapped through the [`Self::resolved_classification`] resolver
3786 /// so an operator-omitted `:classification` slot on
3787 /// `(defephemeral …)` still answers via the substrate default. The
3788 /// ONE ephemeral-surface substrate primitive that owns the
3789 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3790 /// multi-input side of the DAG-composition input-arity projection.
3791 ///
3792 /// # Seventeenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the input-arity axis
3793 ///
3794 /// Peer of the sixteen prior nullary-boolean substrate primitives
3795 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
3796 /// [`Self::horizon_requires_metric_axes`],
3797 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3798 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3799 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3800 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3801 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
3802 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
3803 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`])
3804 /// on the ephemeral surface's (resolver-hop × derived-nullary-
3805 /// bool) shape — the SEVENTEENTH peer overall and the SECOND peer
3806 /// threading the classification-`point_type`-derived input-arity
3807 /// axis on this surface. CLOSES the SEVENTH classification axis
3808 /// into the FULL binary XOR partition contract
3809 /// `input_arity_is_one ⊕ input_arity_is_many` on the ephemeral
3810 /// surface — the resolver-hop peer of the parent-composed
3811 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`.
3812 /// The resolver-hop shape is byte-identical across all seventeen
3813 /// peers.
3814 ///
3815 /// # Semantics — resolver hop + derived-nullary-boolean
3816 ///
3817 /// `input_arity_is_many()` returns `true` iff
3818 /// `self.resolved_classification().input_arity_is_many()`. The
3819 /// resolver returns the authored [`Classification`] when present
3820 /// and the substrate default [`Classification::gate_compute`] on
3821 /// absence. Because [`Classification::gate_compute`] carries
3822 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
3823 /// ephemeral spec with no `:classification` slot answers `true` —
3824 /// every unadorned `(defephemeral …)` lands in the multi-input
3825 /// bucket under the substrate default. Direct antisymmetric
3826 /// mirror of [`Self::input_arity_is_one`] on the SAME resolver
3827 /// walk + SAME projection through the SAME closed set.
3828 ///
3829 /// # Compounding — CLOSES the input-arity axis on the ephemeral surface
3830 ///
3831 /// The ephemeral require-tag classifier will compose this
3832 /// primitive as a fixed tag `multi-input-arity` on
3833 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3834 /// surface's `multi-input-arity` fixed tag on
3835 /// `POINT_FIXED_TAG_ARMS` via
3836 /// [`Classification::input_arity_is_many`] directly. The
3837 /// two-surface parity contract holds by construction: both
3838 /// surfaces route through the SAME
3839 /// [`Classification::input_arity_is_many`] primitive after the
3840 /// ephemeral surface pays ONE resolver hop. SECOND input-arity-
3841 /// axis peer CLOSES the axis into the FULL binary XOR partition
3842 /// contract on this surface — the resolver-hop peer of the
3843 /// parent-composed
3844 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`,
3845 /// mirror of the calm-axis (`monotone-calm ⊕
3846 /// coordination-required`), data-axis (`public-data ⊕
3847 /// data-restricted`), and optimization-direction-axis
3848 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
3849 /// closures on this surface — the SEVENTH classification axis to
3850 /// reach the closed XOR partition landmark on the ephemeral
3851 /// resolver-hop surface, opening the derived-typed-projection
3852 /// stratum on this surface for the first time.
3853 ///
3854 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3855 /// preserves proofs; the classification-`point_type`-derived
3856 /// input-arity-axis derived-nullary-boolean probe body composes
3857 /// ONE resolver primitive ([`Self::resolved_classification`])
3858 /// with ONE [`Classification`] primitive
3859 /// ([`Classification::input_arity_is_many`]) so every downstream
3860 /// (the future `multi-input-arity` fixed tag on the ephemeral
3861 /// surface in tatara-check, future DAG-composition input-arity
3862 /// validators keying on the multi-input framing, future variant
3863 /// additions on
3864 /// [`crate::classification::ConvergencePointType`]) binds through
3865 /// the SAME `input_arity_is_many()` shape rather than restating
3866 /// either `!self.input_arity_is_one()` or the two-hop
3867 /// `self.resolved_classification().point_type.input_arity().is_many()`
3868 /// chain at each callsite. THEORY.md §VI.1 — generation over
3869 /// composition; a future
3870 /// [`crate::classification::ConvergencePointType`] variant lands
3871 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
3872 /// and both surfaces pick it up mechanically.
3873 #[must_use]
3874 pub fn input_arity_is_many(&self) -> bool {
3875 self.resolved_classification().input_arity_is_many()
3876 }
3877
3878 /// Derived-boolean predicate — does this ephemeral spec's resolved
3879 /// [`Classification`]'s `point_type` slot project to `Arity::One`
3880 /// under
3881 /// [`crate::classification::ConvergencePointType::output_arity`]?
3882 /// Byte-for-byte peer of
3883 /// [`crate::classification::Classification::output_arity_is_one`]
3884 /// wrapped through the [`Self::resolved_classification`] resolver
3885 /// so an operator-omitted `:classification` slot on
3886 /// `(defephemeral …)` still answers via the substrate default. The
3887 /// ONE ephemeral-surface substrate primitive that owns the
3888 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
3889 /// single-output side of the DAG-composition output-arity projection.
3890 ///
3891 /// # Eighteenth derived-nullary-boolean peer on the ephemeral surface — opens the output-arity axis
3892 ///
3893 /// Peer of the seventeen prior nullary-boolean substrate primitives
3894 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
3895 /// [`Self::horizon_requires_metric_axes`],
3896 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
3897 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
3898 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
3899 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
3900 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
3901 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
3902 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
3903 /// [`Self::input_arity_is_many`]) on the ephemeral surface's
3904 /// (resolver-hop × derived-nullary-bool) shape — the EIGHTEENTH
3905 /// peer overall and the FIRST peer threading the classification-
3906 /// `point_type`-derived OUTPUT-arity axis on this surface. Opens
3907 /// the EIGHTH classification axis into the ephemeral fixed-tag
3908 /// algebra after the horizon, calm, data, point-type, substrate,
3909 /// optimization-direction, and input-arity axes. SECOND peer on
3910 /// the derived-typed-projection stratum of the ephemeral surface
3911 /// (after [`Self::input_arity_is_one`]) — composes an extra
3912 /// closed-set-level projection hop
3913 /// ([`crate::classification::ConvergencePointType::output_arity`])
3914 /// compared to the sibling `point_is_*` triple that walks the raw
3915 /// `point_type` slot through the resolver. The resolver-hop shape
3916 /// is byte-identical across all eighteen peers.
3917 ///
3918 /// # Distinctness from the input-arity axis
3919 ///
3920 /// The input-arity and output-arity axes carve the eight-variant
3921 /// [`crate::classification::ConvergencePointType`] closed set into
3922 /// DISTINCT partitions — six of the eight variants (`Fork |
3923 /// Broadcast | Join | Gate | Select | Reduce`) DISAGREE between the
3924 /// two projections, and only the two endomorphic variants
3925 /// (`Transform | Observe` — both `(One, One)`) agree. The ephemeral
3926 /// resolver-hop surface inherits this distinctness verbatim: the
3927 /// absent-classification baseline (`gate_compute` → `point_type:
3928 /// Gate`) FLIPS between the two axes — `input_arity_is_one` is
3929 /// `false` on the baseline but `output_arity_is_one` is `true`.
3930 /// So `output_arity_is_one` is NOT a redundant restatement of
3931 /// `input_arity_is_one` even after both wrap through the SAME
3932 /// resolver.
3933 ///
3934 /// # Semantics — resolver hop + derived-nullary-boolean
3935 ///
3936 /// `output_arity_is_one()` returns `true` iff
3937 /// `self.resolved_classification().output_arity_is_one()`. The
3938 /// resolver returns the authored [`Classification`] when present
3939 /// and the substrate default [`Classification::gate_compute`] on
3940 /// absence. Because [`Classification::gate_compute`] carries
3941 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
3942 /// ephemeral spec with no `:classification` slot answers `true` —
3943 /// every unadorned `(defephemeral …)` lands in the single-output
3944 /// bucket under the substrate default (`Gate` gates a many-to-one
3945 /// bucket dispatch, so the multi-output bucket only applies to
3946 /// operator-authored specs on the `Fork | Broadcast` arms). A
3947 /// regression that dropped the resolver hop, probed the wrong
3948 /// closed-set arm, or crossed the wires with the sibling
3949 /// [`crate::classification::ConvergencePointType::input_arity`]
3950 /// projection (which disagrees on six of the eight variants) fails
3951 /// HERE at ONE narrow substrate site before drifting through every
3952 /// unadorned ephemeral spec's DAG-composition output-arity audit.
3953 ///
3954 /// # Compounding — opens the output-arity axis on the ephemeral surface
3955 ///
3956 /// The ephemeral require-tag classifier will compose this
3957 /// primitive as a fixed tag `single-output-arity` on
3958 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
3959 /// surface's `single-output-arity` fixed tag on
3960 /// `POINT_FIXED_TAG_ARMS` via
3961 /// [`Classification::output_arity_is_one`] directly. The
3962 /// two-surface parity contract holds by construction: both
3963 /// surfaces route through the SAME
3964 /// [`Classification::output_arity_is_one`] primitive after the
3965 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
3966 /// peer ([`Self::output_arity_is_many`]) closes the binary XOR
3967 /// partition on this axis — mirror of the input-arity-axis
3968 /// (`input_arity_is_one ⊕ input_arity_is_many`), the calm-axis
3969 /// (`monotone-calm ⊕ coordination-required`), the data-axis
3970 /// (`public-data ⊕ data-restricted`), and the optimization-
3971 /// direction-axis (`prefers-lower-direction ⊕
3972 /// prefers-higher-direction`) closures on this surface,
3973 /// completing the DAG-composition arity PAIR on the ephemeral
3974 /// derived-typed-projection stratum.
3975 ///
3976 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3977 /// preserves proofs; the classification-`point_type`-derived
3978 /// output-arity-axis derived-nullary-boolean probe body composes
3979 /// ONE resolver primitive ([`Self::resolved_classification`])
3980 /// with ONE [`Classification`] primitive
3981 /// ([`Classification::output_arity_is_one`]) so every downstream
3982 /// (the future `single-output-arity` fixed tag on the ephemeral
3983 /// surface in tatara-check, future DAG-composition output-arity
3984 /// validators keying on the single-output framing, future variant
3985 /// additions on
3986 /// [`crate::classification::ConvergencePointType`]) binds through
3987 /// the SAME `output_arity_is_one()` shape rather than restating
3988 /// either the resolver walk or the two-hop closed-set projection
3989 /// composition at the callsite. THEORY.md §VI.1 — generation over
3990 /// composition; a future
3991 /// [`crate::classification::ConvergencePointType`] variant lands
3992 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
3993 /// and both surfaces pick it up mechanically.
3994 #[must_use]
3995 pub fn output_arity_is_one(&self) -> bool {
3996 self.resolved_classification().output_arity_is_one()
3997 }
3998
3999 /// ANTISYMMETRIC PEER of [`Self::output_arity_is_one`] — does
4000 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
4001 /// slot project to `Arity::Many` under
4002 /// [`crate::classification::ConvergencePointType::output_arity`]?
4003 /// Byte-for-byte peer of
4004 /// [`crate::classification::Classification::output_arity_is_many`]
4005 /// wrapped through the [`Self::resolved_classification`] resolver
4006 /// so an operator-omitted `:classification` slot on
4007 /// `(defephemeral …)` still answers via the substrate default. The
4008 /// ONE ephemeral-surface substrate primitive that owns the
4009 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
4010 /// multi-output side of the DAG-composition output-arity projection.
4011 ///
4012 /// # Nineteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the output-arity axis
4013 ///
4014 /// Peer of the eighteen prior nullary-boolean substrate primitives
4015 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
4016 /// [`Self::horizon_requires_metric_axes`],
4017 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
4018 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
4019 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
4020 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
4021 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
4022 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
4023 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
4024 /// [`Self::input_arity_is_many`], [`Self::output_arity_is_one`])
4025 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4026 /// bool) shape — the NINETEENTH peer overall and the SECOND peer
4027 /// threading the classification-`point_type`-derived OUTPUT-arity
4028 /// axis on this surface. CLOSES the EIGHTH classification axis
4029 /// into the FULL binary XOR partition contract
4030 /// `output_arity_is_one ⊕ output_arity_is_many` on the ephemeral
4031 /// surface — the resolver-hop peer of the parent-composed
4032 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`.
4033 /// The resolver-hop shape is byte-identical across all nineteen
4034 /// peers. Completes the DAG-composition arity PAIR on the
4035 /// ephemeral derived-typed-projection stratum
4036 /// (`input_arity_is_{one,many}` + `output_arity_is_{one,many}` on
4037 /// the SAME resolver walk through the SAME closed set).
4038 ///
4039 /// # Semantics — resolver hop + derived-nullary-boolean
4040 ///
4041 /// `output_arity_is_many()` returns `true` iff
4042 /// `self.resolved_classification().output_arity_is_many()`. The
4043 /// resolver returns the authored [`Classification`] when present
4044 /// and the substrate default [`Classification::gate_compute`] on
4045 /// absence. Because [`Classification::gate_compute`] carries
4046 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
4047 /// ephemeral spec with no `:classification` slot answers `false` —
4048 /// every unadorned `(defephemeral …)` lands in the single-output
4049 /// bucket under the substrate default. Direct antisymmetric
4050 /// mirror of [`Self::output_arity_is_one`] on the SAME resolver
4051 /// walk + SAME projection through the SAME closed set.
4052 ///
4053 /// # Compounding — CLOSES the output-arity axis on the ephemeral surface
4054 ///
4055 /// The ephemeral require-tag classifier will compose this
4056 /// primitive as a fixed tag `multi-output-arity` on
4057 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4058 /// surface's `multi-output-arity` fixed tag on
4059 /// `POINT_FIXED_TAG_ARMS` via
4060 /// [`Classification::output_arity_is_many`] directly. The
4061 /// two-surface parity contract holds by construction: both
4062 /// surfaces route through the SAME
4063 /// [`Classification::output_arity_is_many`] primitive after the
4064 /// ephemeral surface pays ONE resolver hop. SECOND output-arity-
4065 /// axis peer CLOSES the axis into the FULL binary XOR partition
4066 /// contract on this surface — the resolver-hop peer of the
4067 /// parent-composed
4068 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`,
4069 /// mirror of the input-arity-axis (`input_arity_is_one ⊕
4070 /// input_arity_is_many`), the calm-axis (`monotone-calm ⊕
4071 /// coordination-required`), the data-axis (`public-data ⊕
4072 /// data-restricted`), and the optimization-direction-axis
4073 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
4074 /// closures on this surface — the EIGHTH classification axis to
4075 /// reach the closed XOR partition landmark on the ephemeral
4076 /// resolver-hop surface, completing the DAG-composition arity
4077 /// PAIR on the derived-typed-projection stratum of this surface.
4078 ///
4079 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4080 /// preserves proofs; the classification-`point_type`-derived
4081 /// output-arity-axis derived-nullary-boolean probe body composes
4082 /// ONE resolver primitive ([`Self::resolved_classification`])
4083 /// with ONE [`Classification`] primitive
4084 /// ([`Classification::output_arity_is_many`]) so every downstream
4085 /// (the future `multi-output-arity` fixed tag on the ephemeral
4086 /// surface in tatara-check, future DAG-composition output-arity
4087 /// validators keying on the multi-output framing, future variant
4088 /// additions on
4089 /// [`crate::classification::ConvergencePointType`]) binds through
4090 /// the SAME `output_arity_is_many()` shape rather than restating
4091 /// either `!self.output_arity_is_one()` or the two-hop
4092 /// `self.resolved_classification().point_type.output_arity().is_many()`
4093 /// chain at each callsite. THEORY.md §VI.1 — generation over
4094 /// composition; a future
4095 /// [`crate::classification::ConvergencePointType`] variant lands
4096 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
4097 /// and both surfaces pick it up mechanically.
4098 #[must_use]
4099 pub fn output_arity_is_many(&self) -> bool {
4100 self.resolved_classification().output_arity_is_many()
4101 }
4102
4103 /// True iff this ephemeral spec's [`Self::routing`] slot is
4104 /// populated AND the inner [`RoutingSpec`]'s derived
4105 /// [`RoutingForm`] equals `kind` — the substrate primitive that
4106 /// owns the (`&EphemeralSpec`, [`RoutingForm`]) → `bool` presence-
4107 /// probe shape on the sugar-surface type.
4108 ///
4109 /// # Peer to [`crate::routing::RoutingSpec::has_form`]
4110 ///
4111 /// [`RoutingSpec::has_form`] carries the same `(&self, RoutingForm)
4112 /// -> bool` signature on the inner routing carrier reached through
4113 /// the Option gate; this peer composes byte-identical semantics on
4114 /// [`EphemeralSpec`]'s direct `routing: Option<RoutingSpec>` slot,
4115 /// so both surfaces' `routing-form-<kind>` require-tag families
4116 /// route through the SAME `RoutingSpec::has_form` primitive. A
4117 /// future normalization at the probe shape (a widened return
4118 /// carrying the derived [`RoutingForm`] variant, a debug-build
4119 /// assertion on operator-set vs defaulted overrides on the
4120 /// `stable_name_claim` bool, a fleet-wide warn on `Stable`
4121 /// combined with content-hashed hostnames) lands at ONE site per
4122 /// surface and every downstream `routing-form-<kind>` require-tag
4123 /// family + closed-set audit dispatcher picks it up mechanically.
4124 ///
4125 /// # Semantics — Option-gated derived-scalar match
4126 ///
4127 /// [`EphemeralSpec::routing`] is an `Option<RoutingSpec>`: `None`
4128 /// on an in-cluster-only ephemeral env (no per-instance edges
4129 /// declared), `Some(_)` when the operator authored the
4130 /// `:routing (…)` slot. `has_routing_form(kind)` returns `true`
4131 /// iff the slot is `Some(spec)` AND `spec.has_form(kind)` — the
4132 /// Option-parent gate short-circuits `false` on `None` regardless
4133 /// of `kind`, and the reachable arm reads the DERIVED
4134 /// [`RoutingForm`] through the ONE substrate composer
4135 /// [`RoutingForm::from_is_stable`] over the child
4136 /// `stable_name_claim` bool (a `false` default projects to
4137 /// [`RoutingForm::Instance`], a `true` operator override projects
4138 /// to [`RoutingForm::Stable`]).
4139 ///
4140 /// # Corner — (Option-parent × derived-scalar-child)
4141 ///
4142 /// SAME corner as the point surface's `routing-form-<kind>`
4143 /// family (via [`crate::routing::RoutingSpec::has_form`] reached
4144 /// through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`)
4145 /// — both surfaces' Option-parent hop threads through the SAME
4146 /// `Option<RoutingSpec>` field name on their respective sugar
4147 /// structs. The [`From<EphemeralSpec>`] lowering copies
4148 /// `e.routing → ProcessSpec::routing` byte-for-byte at the
4149 /// [`From`] impl in this module (see the `routing: e.routing`
4150 /// line), so the SAME `Option<RoutingSpec>` reaches both
4151 /// surfaces' `routing-form-<kind>` families through the SAME
4152 /// [`RoutingSpec::has_form`] walk. Distinct from
4153 /// [`Self::has_teardown_policy`] on this same surface, which
4154 /// walks a required-scalar-child through no Option-parent hop.
4155 ///
4156 /// # Compounding
4157 ///
4158 /// The ephemeral require-tag classifier composes this primitive
4159 /// with the closed-set `FromStr` autoderived on [`RoutingForm`]
4160 /// through the `strip_and_classify_prefixed_kind` substrate to
4161 /// publish a `routing-form-<kind>` prefix family byte-for-byte
4162 /// symmetrical with the point surface's family via
4163 /// [`crate::routing::RoutingSpec::has_form`]. A future third
4164 /// [`RoutingForm`] variant added to `ALL` (a hypothetical
4165 /// `Anchored` for "hold the claim only for a specific
4166 /// generation") reaches BOTH surfaces' `routing-form-<kind>`
4167 /// prefix families through the SAME closed-set walk with no
4168 /// per-caller edit — the two-surface symmetry means adding a
4169 /// variant on the closed set publishes it in lockstep across
4170 /// every downstream consumer.
4171 ///
4172 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
4173 /// preserves proofs — the Option-gated derived-scalar-carrier
4174 /// presence-probe body lives at ONE substrate site per surface
4175 /// so every downstream (`routing-form-<kind>` require-tag families
4176 /// on both surfaces in tatara-check, closed-set audit dispatchers,
4177 /// future variant additions on [`RoutingForm`]) binds through the
4178 /// SAME `has(kind)` shape rather than restating the
4179 /// `spec.routing.as_ref().is_some_and(|r| r.has_form(kind))`
4180 /// closure body at each call site). THEORY.md §VI.1 (generation
4181 /// over composition — a future variant lands at ONE `ALL` entry +
4182 /// one `as_str` arm on the closed set and the probe picks it up
4183 /// mechanically without further per-consumer edits).
4184 #[must_use]
4185 pub fn has_routing_form(&self, kind: RoutingForm) -> bool {
4186 self.routing.as_ref().is_some_and(|r| r.has_form(kind))
4187 }
4188
4189 /// True iff at least one declared export in `self.exports` would
4190 /// fire on the given terminal-reached [`ProcessPhase`] — the peer
4191 /// of [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4192 /// on the [`EphemeralSpec`] surface.
4193 ///
4194 /// # Semantics — byte-identical to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4195 ///
4196 /// Both surfaces walk the SAME slice-level substrate primitive
4197 /// [`ExportSpecSliceExt::has_applicable_at`] on their respective
4198 /// `Vec<ExportSpec>` slot: [`EphemeralSpec`]'s `exports` field is
4199 /// copied byte-for-byte into `EphemeralLifetime::exports` at the
4200 /// `From<EphemeralSpec>` lowering, so a `has_applicable_exports_at`
4201 /// query on the authored ephemeral spec answers identically to a
4202 /// `has_applicable_exports` query on the lowered `EphemeralLifetime`.
4203 /// A regression at the compound `(when, phase) → fires_on(phase)`
4204 /// walk fails at [`ExportSpecSliceExt::has_applicable_at`]'s tests
4205 /// rather than as silent drift at either surface's inherent method.
4206 ///
4207 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4208 ///
4209 /// Same shape, same axis, same body — the point-domain surface
4210 /// composes through `spec.lifetime.resolved_ephemeral().is_some_and(
4211 /// |e| e.exports.has_applicable_at(phase))`; the ephemeral sugar
4212 /// surface reads `self.exports.has_applicable_at(phase)` directly
4213 /// because `EphemeralSpec` stores `exports: Vec<ExportSpec>` as a
4214 /// top-level field. Both routes bind through THIS ONE slice-level
4215 /// primitive so a future normalization (widening the trigger from
4216 /// a stored discriminator to a computed predicate, adding a phase
4217 /// that composes across multiple trigger arms, threading a
4218 /// per-export justification back for editor tooltips) lands at ONE
4219 /// site and every downstream inherits the shift by construction.
4220 ///
4221 /// # Compounding
4222 ///
4223 /// The ephemeral require-tag classifier composes this primitive
4224 /// with the closed-set [`ProcessPhase`]'s autoderived `FromStr`
4225 /// through the `strip_and_classify_prefixed_kind` substrate to
4226 /// publish an `exports-fire-on-<phase>` closed-set prefix family
4227 /// byte-for-byte symmetrical with the point surface's family via
4228 /// `spec.lifetime.resolved_ephemeral().is_some_and(|e|
4229 /// e.exports.has_applicable_at(phase))`. A future twelfth
4230 /// [`ProcessPhase`] variant reaches BOTH surfaces' prefix families
4231 /// through the ONE [`crate::export::ExportTrigger::fires_on`]
4232 /// exhaustive match — either the new phase inherits a per-trigger
4233 /// fire rule at that single substrate site or it collapses to
4234 /// `false` for every trigger (the current non-terminal tail),
4235 /// without a per-caller edit anywhere else.
4236 ///
4237 /// A future normalization at the compound `(when, phase) →
4238 /// fires_on(phase)` walk (a widening that returns the applicable
4239 /// exports themselves rather than a bool, a debug-build assertion
4240 /// on redundant `Always`-triggered exports coexisting with an
4241 /// `OnAttested` peer, a fleet-wide warn on empty-export ephemerals
4242 /// declaring `OnAttested` postconditions) lands at the ONE
4243 /// slice-level substrate primitive [`ExportSpecSliceExt::has_applicable_at`]
4244 /// both this method and [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
4245 /// compose against — so the two struct-level union methods stay
4246 /// symmetric by construction.
4247 ///
4248 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
4249 /// proofs — the walk composes the SAME slice-level substrate
4250 /// primitive on both this ephemeral surface and the
4251 /// [`crate::lifetime::EphemeralLifetime`] surface, so a regression
4252 /// at the compound `(when, phase) → fires_on(phase)` chain fails
4253 /// at ONE site rather than as silent drift between the two peers).
4254 /// THEORY.md §VI.1 (generation over composition — a future
4255 /// [`ProcessPhase`] variant or a future [`crate::export::ExportTrigger`]
4256 /// variant reaches both `exports-fire-on-<phase>` require-tag
4257 /// surfaces mechanically through the SAME closed-set walk).
4258 #[must_use]
4259 pub fn has_applicable_exports_at(&self, phase: ProcessPhase) -> bool {
4260 self.exports.has_applicable_at(phase)
4261 }
4262}
4263
4264impl From<EphemeralSpec> for ProcessSpec {
4265 fn from(e: EphemeralSpec) -> Self {
4266 let classification = e.classification.unwrap_or_else(default_ephemeral_class);
4267 let mut spec = Self {
4268 identity: crate::spec::IdentitySpec {
4269 parent: e.parent,
4270 name_override: None,
4271 },
4272 classification,
4273 intent: Intent {
4274 aplicacao: Some(e.aplicacao),
4275 ..Intent::default()
4276 },
4277 boundary: Boundary {
4278 preconditions: e.preconditions,
4279 postconditions: e.postconditions,
4280 timeout: e.verify_timeout,
4281 },
4282 compliance: Default::default(),
4283 depends_on: vec![],
4284 signals: Default::default(),
4285 // Routes through the ONE substrate composer
4286 // [`Lifetime::ephemeral`] — pre-lift this was one of
4287 // ELEVEN+ hand-authored `Lifetime { ephemeral: Some(<e>),
4288 // .. }` sites past the ★★ PRIME-DIRECTIVE ≥ 2 threshold.
4289 // See the composer's doc-comment for the full migration
4290 // rationale.
4291 lifetime: Lifetime::ephemeral(EphemeralLifetime {
4292 ttl: e.ttl,
4293 teardown_policy: e.teardown,
4294 max_concurrent: e.max_concurrent,
4295 exports: e.exports,
4296 }),
4297 // R5 — propagate routing template (None = no edges).
4298 routing: e.routing,
4299 // EncapsulatesSpec isn't exposed via EphemeralSpec sugar;
4300 // operators wanting Adopt/Observe author the full
4301 // (defpoint …) form. Sugar path stays greenfield-Manage.
4302 encapsulates: None,
4303 suspended: false,
4304 };
4305 // Belt-and-suspenders: make sure exactly-one Intent invariant holds.
4306 spec.intent.nix = None;
4307 spec.intent.flux = None;
4308 spec.intent.lisp = None;
4309 spec.intent.container = None;
4310 spec.intent.guest = None;
4311 spec
4312 }
4313}
4314
4315fn default_ephemeral_class() -> Classification {
4316 // Delegates through the substrate `(Gate, Compute)` baseline owner
4317 // so the shape lives at ONE workspace-wide site — see
4318 // [`Classification::gate_compute`] for the pre-lift ten-callsite
4319 // duplication history and the sibling-default correspondence
4320 // pinned there.
4321 Classification::gate_compute()
4322}
4323
4324/// Compile a `(defephemeral …)` Lisp source into named `EphemeralSpec` values.
4325pub fn compile_ephemeral_source(
4326 src: &str,
4327) -> tatara_lisp::Result<Vec<tatara_lisp::NamedDefinition<EphemeralSpec>>> {
4328 tatara_lisp::compile_named::<EphemeralSpec>(src)
4329}
4330
4331#[cfg(test)]
4332mod tests {
4333 use super::*;
4334 use crate::boundary::{assert_slice_refinement_composition_laws, ConditionKind};
4335 use crate::classification::{
4336 Arity, CalmClassification, ConvergencePointType, DataClassification, Horizon, HorizonKind,
4337 OptimizationDirection, SubstrateType,
4338 };
4339 use crate::intent::IntentVariant;
4340 use crate::lifetime::LifetimeVariant;
4341
4342 /// LANDMARK PIN — the (ephemeral-surface test-fixture ×
4343 /// [`Classification::gate_compute_with_axis`] on horizon-nested
4344 /// axes) sweep equivalence. Nine ephemeral-surface probe-sweep
4345 /// tests in this module (`has_horizon_kind_*`,
4346 /// `has_optimization_direction_*`, `horizon_terminates_*`,
4347 /// `horizon_requires_metric_axes_*`, `horizon_terminates_xor_*`)
4348 /// pre-sweep restated the SAME `let mut c =
4349 /// Classification::gate_compute(); c.horizon = Horizon { <slot>:
4350 /// populated, ..Horizon::default() }` five-line fixture at each
4351 /// callsite, mutating exactly ONE horizon-nested slot to
4352 /// `populated`; post-sweep each callsite reads
4353 /// [`Classification::gate_compute_with_axis(populated)`] — one
4354 /// line — and the four-baseline-slot restatement lives at ONE
4355 /// substrate primitive. This pin asserts byte-parity between the
4356 /// pre-sweep hand-authored `Horizon` struct-literal shape (both
4357 /// the [`HorizonKind::kind`] mutation shape AND the
4358 /// [`OptimizationDirection`]-into-`Some(_)` mutation shape) and
4359 /// the post-sweep composer output on every variant of each closed
4360 /// set, so a regression that either (a) changed
4361 /// [`ClassificationAxis for HorizonKind`] to stomp a non-`kind`
4362 /// sub-slot, (b) changed [`ClassificationAxis for OptimizationDirection`]
4363 /// to drop the `Some(...)` wrap, or (c) reintroduced a whole-
4364 /// `Horizon`-reset shape that dropped a sibling sub-slot would
4365 /// fail HERE at ONE landmark site before landing at the peer
4366 /// probe-sweep pins that use the composer.
4367 ///
4368 /// Byte-for-byte peer of the sibling landmark
4369 /// `with_axis_optimization_direction_overlay_wraps_variant_in_some`
4370 /// on the point-surface classification-module tests — this pin
4371 /// carries the same substrate contract through to the ephemeral-
4372 /// surface tests that consume the composer.
4373 #[test]
4374 fn gate_compute_with_axis_on_horizon_nested_axes_matches_hand_authored_shape() {
4375 for kind in HorizonKind::ALL {
4376 let via_composer = Classification::gate_compute_with_axis(kind);
4377 let mut via_hand_authored = Classification::gate_compute();
4378 via_hand_authored.horizon = Horizon {
4379 kind,
4380 ..Horizon::default()
4381 };
4382 assert_eq!(
4383 via_composer, via_hand_authored,
4384 "HorizonKind::{kind:?}: composer vs pre-sweep hand-authored struct-literal drift",
4385 );
4386 }
4387 for direction in OptimizationDirection::ALL {
4388 let via_composer = Classification::gate_compute_with_axis(direction);
4389 let mut via_hand_authored = Classification::gate_compute();
4390 via_hand_authored.horizon = Horizon {
4391 direction: Some(direction),
4392 ..Horizon::default()
4393 };
4394 assert_eq!(
4395 via_composer, via_hand_authored,
4396 "OptimizationDirection::{direction:?}: composer vs pre-sweep hand-authored struct-literal drift",
4397 );
4398 }
4399 }
4400
4401 /// Primitive-owner pin — `EphemeralSpec::with_classification_axis`
4402 /// on a `classification: None` carrier produces an ephemeral spec
4403 /// whose `classification` slot is
4404 /// `Some(Classification::gate_compute_with_axis(axis))` byte-for-
4405 /// byte on every axis-variant, and preserves every non-
4406 /// classification slot at its pre-call value. A regression that
4407 /// (a) failed to wrap the composed [`Classification`] in `Some(_)`
4408 /// on the `None`-arm, (b) mutated a sibling slot on `EphemeralSpec`
4409 /// through the axis overlay, or (c) picked a different `None`-arm
4410 /// fill-through than the sibling
4411 /// [`Self::resolved_classification`] resolver would fail HERE.
4412 #[test]
4413 fn with_classification_axis_on_none_arm_fills_through_gate_compute() {
4414 fn baseline() -> EphemeralSpec {
4415 EphemeralSpec {
4416 aplicacao: demo_overlay(),
4417 ttl: "2h".into(),
4418 teardown: TeardownPolicy::OnAttested,
4419 max_concurrent: 3,
4420 postconditions: vec![],
4421 preconditions: vec![],
4422 verify_timeout: Some("30m".into()),
4423 classification: None,
4424 parent: Some("seph.1".into()),
4425 exports: vec![],
4426 routing: None,
4427 }
4428 }
4429 // Direct-scalar axes: composer output matches
4430 // `Classification::gate_compute_with_axis(axis)` byte-for-byte,
4431 // wrapped in `Some(_)`.
4432 for kind in ConvergencePointType::ALL {
4433 let via_composer = baseline().with_classification_axis(kind);
4434 assert_eq!(
4435 via_composer.classification,
4436 Some(Classification::gate_compute_with_axis(kind)),
4437 "ConvergencePointType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4438 );
4439 }
4440 for kind in SubstrateType::ALL {
4441 let via_composer = baseline().with_classification_axis(kind);
4442 assert_eq!(
4443 via_composer.classification,
4444 Some(Classification::gate_compute_with_axis(kind)),
4445 "SubstrateType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4446 );
4447 }
4448 for kind in CalmClassification::ALL {
4449 let via_composer = baseline().with_classification_axis(kind);
4450 assert_eq!(
4451 via_composer.classification,
4452 Some(Classification::gate_compute_with_axis(kind)),
4453 "CalmClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4454 );
4455 }
4456 for kind in DataClassification::ALL {
4457 let via_composer = baseline().with_classification_axis(kind);
4458 assert_eq!(
4459 via_composer.classification,
4460 Some(Classification::gate_compute_with_axis(kind)),
4461 "DataClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4462 );
4463 }
4464 // Horizon-nested axes: same shape through the trait's
4465 // sub-slot overlay.
4466 for kind in HorizonKind::ALL {
4467 let via_composer = baseline().with_classification_axis(kind);
4468 assert_eq!(
4469 via_composer.classification,
4470 Some(Classification::gate_compute_with_axis(kind)),
4471 "HorizonKind::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4472 );
4473 }
4474 for direction in OptimizationDirection::ALL {
4475 let via_composer = baseline().with_classification_axis(direction);
4476 assert_eq!(
4477 via_composer.classification,
4478 Some(Classification::gate_compute_with_axis(direction)),
4479 "OptimizationDirection::{direction:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
4480 );
4481 }
4482 // Non-classification slots: every one preserved byte-for-byte
4483 // across the overlay on every axis. Compare through JSON
4484 // round-trip since `AplicacaoIntent` / `ExportSpec` /
4485 // `RoutingSpec` do not carry `PartialEq`.
4486 for kind in ConvergencePointType::ALL {
4487 let via_composer = baseline().with_classification_axis(kind);
4488 let baseline_ref = baseline();
4489 assert_eq!(
4490 serde_json::to_string(&via_composer.aplicacao).unwrap(),
4491 serde_json::to_string(&baseline_ref.aplicacao).unwrap(),
4492 "aplicacao slot drifted under axis overlay for kind={kind:?}",
4493 );
4494 assert_eq!(via_composer.ttl, baseline_ref.ttl);
4495 assert_eq!(via_composer.teardown, baseline_ref.teardown);
4496 assert_eq!(via_composer.max_concurrent, baseline_ref.max_concurrent);
4497 assert_eq!(
4498 via_composer.postconditions.len(),
4499 baseline_ref.postconditions.len()
4500 );
4501 assert_eq!(
4502 via_composer.preconditions.len(),
4503 baseline_ref.preconditions.len()
4504 );
4505 assert_eq!(via_composer.verify_timeout, baseline_ref.verify_timeout);
4506 assert_eq!(via_composer.parent, baseline_ref.parent);
4507 assert_eq!(via_composer.exports.len(), baseline_ref.exports.len());
4508 assert!(via_composer.routing.is_none());
4509 }
4510 }
4511
4512 /// Primitive-owner pin —
4513 /// `EphemeralSpec::with_classification_axis` on a
4514 /// `classification: Some(prior)` carrier composes the axis
4515 /// overlay onto `prior` via [`ClassificationAxis::overlay`],
4516 /// preserving every OTHER axis slot on `prior`. Distinct from the
4517 /// `None`-arm pin above: the `Some(prior)` arm does NOT reset
4518 /// through [`Classification::gate_compute`], and consecutive
4519 /// `.with_classification_axis(...)` calls compose arbitrary
4520 /// N-axis conjunctions on the ephemeral surface with the same
4521 /// order-independence guarantee [`Classification::with_axis`]
4522 /// carries on distinct-slot axes.
4523 #[test]
4524 fn with_classification_axis_on_some_arm_chains_onto_prior() {
4525 fn baseline() -> EphemeralSpec {
4526 EphemeralSpec {
4527 aplicacao: demo_overlay(),
4528 ttl: "1h".into(),
4529 teardown: TeardownPolicy::Always,
4530 max_concurrent: 0,
4531 postconditions: vec![],
4532 preconditions: vec![],
4533 verify_timeout: None,
4534 classification: None,
4535 parent: None,
4536 exports: vec![],
4537 routing: None,
4538 }
4539 }
4540 // Prior authored point_type = Fork; overlay substrate = Storage
4541 // preserves the Fork point_type on the composed classification.
4542 let seeded = baseline().with_classification_axis(ConvergencePointType::Fork);
4543 let composed = seeded.with_classification_axis(SubstrateType::Storage);
4544 let classification = composed
4545 .classification
4546 .as_ref()
4547 .expect("with_classification_axis populates Some(_)");
4548 assert_eq!(classification.point_type, ConvergencePointType::Fork);
4549 assert_eq!(classification.substrate, SubstrateType::Storage);
4550 // Order independence on distinct-slot axes: swapping the axis
4551 // chain reads the SAME final classification.
4552 let forward = baseline()
4553 .with_classification_axis(ConvergencePointType::Fork)
4554 .with_classification_axis(SubstrateType::Storage)
4555 .with_classification_axis(CalmClassification::NonMonotone)
4556 .with_classification_axis(DataClassification::Pii)
4557 .classification
4558 .unwrap();
4559 let reverse = baseline()
4560 .with_classification_axis(DataClassification::Pii)
4561 .with_classification_axis(CalmClassification::NonMonotone)
4562 .with_classification_axis(SubstrateType::Storage)
4563 .with_classification_axis(ConvergencePointType::Fork)
4564 .classification
4565 .unwrap();
4566 assert_eq!(
4567 forward, reverse,
4568 "with_classification_axis chain must be order-independent on distinct-slot axes",
4569 );
4570 // Nested horizon-sub-slot overlays compose onto the same
4571 // carrier without stomping each other: the (kind, direction)
4572 // pair rides both chains.
4573 let paired = baseline()
4574 .with_classification_axis(HorizonKind::Asymptotic)
4575 .with_classification_axis(OptimizationDirection::Maximize)
4576 .classification
4577 .unwrap();
4578 assert_eq!(paired.horizon.kind, HorizonKind::Asymptotic);
4579 assert_eq!(
4580 paired.horizon.direction,
4581 Some(OptimizationDirection::Maximize)
4582 );
4583 }
4584
4585 /// Primitive-owner pin —
4586 /// `EphemeralSpec::with_classification_axis` composes byte-for-
4587 /// byte with the pre-sweep hand-authored two-shape callsite
4588 /// pattern that recurred at ~36 sites in
4589 /// `tatara-reconciler::bin::tatara-check`: either
4590 /// `let mut c = Classification::gate_compute(); c.<axis> =
4591 /// populated; EphemeralSpec { classification: Some(c), ..
4592 /// baseline }`, or the newer `let c =
4593 /// Classification::gate_compute_with_axis(populated); EphemeralSpec
4594 /// { classification: Some(c), ..baseline }`. Both restated
4595 /// pre-sweep shapes classify identically to
4596 /// `baseline.with_classification_axis(populated)` on every
4597 /// [`ClassificationAxis`] impl. A regression that drifted the
4598 /// composer body away from the pre-sweep shape (a stray reset of a
4599 /// non-classification slot, a stomping of a nested horizon sub-
4600 /// slot on the direct-scalar axes) fails HERE at ONE landmark site
4601 /// before drifting through the ~36 swept callsites in tatara-
4602 /// check.rs.
4603 #[test]
4604 fn with_classification_axis_matches_pre_sweep_hand_authored_shape() {
4605 fn baseline() -> EphemeralSpec {
4606 EphemeralSpec {
4607 aplicacao: demo_overlay(),
4608 ttl: "1h".into(),
4609 teardown: TeardownPolicy::Always,
4610 max_concurrent: 0,
4611 postconditions: vec![],
4612 preconditions: vec![],
4613 verify_timeout: None,
4614 classification: None,
4615 parent: None,
4616 exports: vec![],
4617 routing: None,
4618 }
4619 }
4620 // Direct-scalar axes: `<eph>.with_classification_axis(kind)`
4621 // matches the pre-sweep two-shape callsite pattern on every
4622 // ConvergencePointType variant.
4623 for kind in ConvergencePointType::ALL {
4624 let via_composer = baseline().with_classification_axis(kind);
4625 let mut hand_classification = Classification::gate_compute();
4626 hand_classification.point_type = kind;
4627 let via_hand = EphemeralSpec {
4628 classification: Some(hand_classification),
4629 ..baseline()
4630 };
4631 assert_eq!(
4632 via_composer.classification, via_hand.classification,
4633 "ConvergencePointType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
4634 );
4635 }
4636 for kind in SubstrateType::ALL {
4637 let via_composer = baseline().with_classification_axis(kind);
4638 let mut hand_classification = Classification::gate_compute();
4639 hand_classification.substrate = kind;
4640 let via_hand = EphemeralSpec {
4641 classification: Some(hand_classification),
4642 ..baseline()
4643 };
4644 assert_eq!(
4645 via_composer.classification, via_hand.classification,
4646 "SubstrateType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
4647 );
4648 }
4649 for kind in CalmClassification::ALL {
4650 let via_composer = baseline().with_classification_axis(kind);
4651 let mut hand_classification = Classification::gate_compute();
4652 hand_classification.calm = kind;
4653 let via_hand = EphemeralSpec {
4654 classification: Some(hand_classification),
4655 ..baseline()
4656 };
4657 assert_eq!(
4658 via_composer.classification, via_hand.classification,
4659 "CalmClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
4660 );
4661 }
4662 for kind in DataClassification::ALL {
4663 let via_composer = baseline().with_classification_axis(kind);
4664 let mut hand_classification = Classification::gate_compute();
4665 hand_classification.data_classification = kind;
4666 let via_hand = EphemeralSpec {
4667 classification: Some(hand_classification),
4668 ..baseline()
4669 };
4670 assert_eq!(
4671 via_composer.classification, via_hand.classification,
4672 "DataClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
4673 );
4674 }
4675 // Horizon-nested axes: composer matches the newer
4676 // `gate_compute_with_axis` shape used on the horizon-nested
4677 // sweep sites in tatara-check.rs.
4678 for kind in HorizonKind::ALL {
4679 let via_composer = baseline().with_classification_axis(kind);
4680 let via_hand = EphemeralSpec {
4681 classification: Some(Classification::gate_compute_with_axis(kind)),
4682 ..baseline()
4683 };
4684 assert_eq!(
4685 via_composer.classification, via_hand.classification,
4686 "HorizonKind::{kind:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
4687 );
4688 }
4689 for direction in OptimizationDirection::ALL {
4690 let via_composer = baseline().with_classification_axis(direction);
4691 let via_hand = EphemeralSpec {
4692 classification: Some(Classification::gate_compute_with_axis(direction)),
4693 ..baseline()
4694 };
4695 assert_eq!(
4696 via_composer.classification, via_hand.classification,
4697 "OptimizationDirection::{direction:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
4698 );
4699 }
4700 }
4701
4702 fn demo_overlay() -> AplicacaoIntent {
4703 AplicacaoIntent {
4704 chart_ref: "oci://ghcr.io/pleme-io/charts/lareira-demo-app".into(),
4705 version: "0.5.5".into(),
4706 profile: "all-in-one".into(),
4707 values_overlay: serde_json::json!({
4708 "cluster": { "name": "ephemeral-test-01", "namespace": "demo-test" },
4709 "data": { "mysql": { "persistence": { "enabled": false } } },
4710 "compliance": { "overlays": [] }
4711 }),
4712 release_name: Some("demo-app-consolidated".into()),
4713 target_namespace: Some("demo-test".into()),
4714 install_timeout: Some("25m".into()),
4715 }
4716 }
4717
4718 #[test]
4719 fn defaults_resolve_for_ephemeral_spec() {
4720 let e = EphemeralSpec {
4721 aplicacao: demo_overlay(),
4722 ttl: crate::lifetime::default_ephemeral_ttl(),
4723 teardown: TeardownPolicy::default(),
4724 max_concurrent: crate::lifetime::default_ephemeral_max_concurrent(),
4725 postconditions: vec![],
4726 preconditions: vec![],
4727 verify_timeout: None,
4728 classification: None,
4729 parent: None,
4730 exports: vec![],
4731 routing: None,
4732 };
4733 let ps: ProcessSpec = e.into();
4734 // Intent must resolve to Aplicacao.
4735 match ps.intent.variant().unwrap() {
4736 IntentVariant::Aplicacao(a) => {
4737 assert_eq!(a.profile, "all-in-one");
4738 assert_eq!(a.install_timeout.as_deref(), Some("25m"));
4739 }
4740 other => panic!("expected Aplicacao, got {other:?}"),
4741 }
4742 // Lifetime must resolve to Ephemeral with defaults.
4743 match ps.lifetime.variant().unwrap() {
4744 LifetimeVariant::Ephemeral(e) => {
4745 assert_eq!(e.ttl, "1h");
4746 assert_eq!(e.teardown_policy, TeardownPolicy::Always);
4747 }
4748 other => panic!("expected ephemeral, got {other:?}"),
4749 }
4750 // Default classification gates the Process at Compute/Internal.
4751 assert_eq!(ps.classification.point_type, ConvergencePointType::Gate);
4752 assert_eq!(ps.classification.substrate, SubstrateType::Compute);
4753 }
4754
4755 #[test]
4756 fn ephemeral_lisp_round_trip() {
4757 let src = r#"
4758 (defephemeral closed-loop-attest
4759 :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
4760 :version "0.5.5"
4761 :profile "all-in-one"
4762 :values-overlay (:cluster (:name "ephemeral-test-01")
4763 :data (:mysql (:persistence (:enabled #f)))
4764 :compliance (:overlays []))
4765 :release-name "demo-app-consolidated"
4766 :target-namespace "demo-test"
4767 :install-timeout "25m")
4768 :ttl "1h"
4769 :teardown OnAttested
4770 :max-concurrent 1
4771 :postconditions
4772 ((:kind HelmReleaseReleased
4773 :params (:name "demo-app-consolidated"
4774 :namespace "demo-test"))
4775 (:kind ClosedLoopAuth
4776 :params (:issuer (:service "demo-app-issuer" :port 8080)
4777 :consumer (:service "demo-app-gateway" :port 8000)
4778 :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
4779 "#;
4780 let defs = compile_ephemeral_source(src).expect("compile");
4781 assert_eq!(defs.len(), 1);
4782 let d = &defs[0];
4783 assert_eq!(d.name, "closed-loop-attest");
4784
4785 // Aplicacao body landed correctly.
4786 assert_eq!(
4787 d.spec.aplicacao.chart_ref,
4788 "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
4789 );
4790 assert_eq!(d.spec.aplicacao.profile, "all-in-one");
4791 assert_eq!(
4792 d.spec.aplicacao.target_namespace.as_deref(),
4793 Some("demo-test")
4794 );
4795 // values-overlay JSON is preserved.
4796 assert_eq!(
4797 d.spec.aplicacao.values_overlay["cluster"]["name"],
4798 "ephemeral-test-01"
4799 );
4800 // Boolean #f is preserved as a typed JSON bool (not the string "false").
4801 // tatara-lisp uses Scheme syntax for bools — `#t` / `#f`.
4802 assert_eq!(
4803 d.spec.aplicacao.values_overlay["data"]["mysql"]["persistence"]["enabled"],
4804 false
4805 );
4806
4807 // Lifetime knobs.
4808 assert_eq!(d.spec.ttl, "1h");
4809 assert_eq!(d.spec.teardown, TeardownPolicy::OnAttested);
4810 assert_eq!(d.spec.max_concurrent, 1);
4811
4812 // Two postconditions, both typed.
4813 assert_eq!(d.spec.postconditions.len(), 2);
4814 assert_eq!(
4815 d.spec.postconditions[0].kind,
4816 ConditionKind::HelmReleaseReleased
4817 );
4818 assert_eq!(d.spec.postconditions[1].kind, ConditionKind::ClosedLoopAuth);
4819
4820 // Lowers to ProcessSpec with the right shape.
4821 let ps: ProcessSpec = d.spec.clone().into();
4822 assert!(matches!(
4823 ps.intent.variant().unwrap(),
4824 IntentVariant::Aplicacao(_)
4825 ));
4826 assert!(matches!(
4827 ps.lifetime.variant().unwrap(),
4828 LifetimeVariant::Ephemeral(_)
4829 ));
4830 assert_eq!(ps.boundary.postconditions.len(), 2);
4831 }
4832
4833 /// End-to-end: the `:exports` slot on `(defephemeral …)` compiles
4834 /// into typed `ExportSpec` values via the Universal-Deserialize
4835 /// fallthrough — no per-domain keyword handlers needed.
4836 ///
4837 /// Receipts (empty-body source) is exercised via the Rust serde
4838 /// path only (see `export::tests::export_spec_serde_round_trip`).
4839 /// tatara-lisp's empty-kw-form `(:)` currently parses as a single-
4840 /// element array rather than a JSON `{}`; the same limitation
4841 /// affects `(:permanent)` on Lifetime. Tracked: extend the reader
4842 /// to accept `(:foo (:))` ⇒ `{"foo": {}}` as a typed-empty form,
4843 /// then re-enable Receipts here.
4844 #[test]
4845 fn exports_lisp_round_trip() {
4846 use crate::export::{ArtifactVariant, ChannelVariant, ExportTrigger, ReportFormat};
4847 let src = r#"
4848 (defephemeral closed-loop-attest
4849 :aplicacao (:chart-ref "oci://x"
4850 :version "1.0.0"
4851 :profile "minimal"
4852 :values-overlay ())
4853 :ttl "30m"
4854 :teardown OnAttested
4855 :exports
4856 ((:source (:test-report (:configmap "junit-results"
4857 :key "junit.xml"
4858 :format Junit))
4859 :channel (:nats-subject (:subject "pleme.pleme-dev.ephemeral.r1.test-report"
4860 :stream "EPHEMERAL_TEST_REPORTS"))
4861 :when OnAttested)
4862 (:source (:test-report (:configmap "junit-results"
4863 :key "junit.xml"
4864 :format Junit))
4865 :channel (:http-event (:signal-type "test-report"))
4866 :when Always)
4867 (:source (:run-marker (:labels (:run-id "r1" :phase "end")))
4868 :channel (:http-event (:signal-type "ephemeral-marker"))
4869 :when Always)))
4870 "#;
4871 let defs = compile_ephemeral_source(src).expect("compile");
4872 assert_eq!(defs.len(), 1);
4873 let d = &defs[0];
4874 assert_eq!(d.spec.exports.len(), 3);
4875
4876 // First export — TestReport → NATS subject + OnAttested
4877 let r = &d.spec.exports[0];
4878 match r.source.variant().unwrap() {
4879 ArtifactVariant::TestReport(tr) => {
4880 assert_eq!(tr.configmap, "junit-results");
4881 assert_eq!(tr.format, ReportFormat::Junit);
4882 }
4883 other => panic!("expected TestReport, got {other:?}"),
4884 }
4885 match r.channel.variant().unwrap() {
4886 ChannelVariant::NatsSubject(n) => {
4887 assert_eq!(n.subject, "pleme.pleme-dev.ephemeral.r1.test-report");
4888 assert_eq!(n.stream, "EPHEMERAL_TEST_REPORTS");
4889 }
4890 other => panic!("expected NatsSubject, got {other:?}"),
4891 }
4892 assert_eq!(r.when, ExportTrigger::OnAttested);
4893
4894 // Second export — TestReport → HTTP + Always
4895 let t = &d.spec.exports[1];
4896 match t.channel.variant().unwrap() {
4897 ChannelVariant::HttpEvent(h) => assert_eq!(h.signal_type, "test-report"),
4898 other => panic!("expected HttpEvent, got {other:?}"),
4899 }
4900 assert_eq!(t.when, ExportTrigger::Always);
4901
4902 // Third export — RunMarker (BTreeMap<String,String> round-trip).
4903 // tatara-lisp lowercases + normalizes keyword keys before
4904 // handing off to serde_json — kebab `:run-id` may land as
4905 // either `run-id` or `runId` depending on the reader path.
4906 // Accept either; the round-trip property under test is
4907 // "label survives compile" not "exact case-form".
4908 let m = &d.spec.exports[2];
4909 match m.source.variant().unwrap() {
4910 ArtifactVariant::RunMarker(rm) => {
4911 assert_eq!(rm.labels.len(), 2);
4912 let run_id = rm
4913 .labels
4914 .get("run-id")
4915 .or_else(|| rm.labels.get("runId"))
4916 .or_else(|| rm.labels.get("run_id"))
4917 .expect("run-id label present under some normalization");
4918 assert_eq!(run_id, "r1");
4919 assert_eq!(rm.labels.get("phase").map(String::as_str), Some("end"));
4920 }
4921 other => panic!("expected RunMarker, got {other:?}"),
4922 }
4923
4924 // Lowered ProcessSpec carries the exports through unchanged.
4925 let ps: ProcessSpec = d.spec.clone().into();
4926 assert_eq!(ps.lifetime.ephemeral.as_ref().unwrap().exports.len(), 3);
4927 }
4928
4929 // ── EphemeralSpec::has_condition_kind substrate pins ─────────────
4930 //
4931 // Fail-before-pass-after granularity:
4932 // `EphemeralSpec::has_condition_kind` did not exist before this
4933 // commit — the (preconditions ∪ postconditions .iter().any(|c|
4934 // c.kind == K)) union-probe shape lived at ONE struct-level site
4935 // (`Boundary::has_condition_kind` on the point surface's nested
4936 // [`Boundary`] slot). The lift adds the peer inherent method on the
4937 // [`EphemeralSpec`] sugar-surface so both struct-level union
4938 // callers compose against the SAME slice-level substrate primitive
4939 // [`ConditionSliceExt::has_kind`] in lockstep. A regression that
4940 // (a) hard-coded the arm to a single kind, (b) dropped the pre-
4941 // condition side of the OR (a re-inheritance of the pre-lift
4942 // ephemeral `closed-loop-auth` post-only shape at the union-tag
4943 // level), or (c) probed the wrong slot fails HERE at the substrate
4944 // primitive rather than as silent operator-facing drift at the
4945 // ephemeral `condition-<kind>` require-tag surface.
4946
4947 fn empty_ephemeral() -> EphemeralSpec {
4948 EphemeralSpec {
4949 aplicacao: AplicacaoIntent::chart_only("oci://ghcr.io/x", "1"),
4950 ttl: "1h".into(),
4951 teardown: TeardownPolicy::Always,
4952 max_concurrent: 0,
4953 postconditions: vec![],
4954 preconditions: vec![],
4955 verify_timeout: None,
4956 classification: None,
4957 parent: None,
4958 exports: vec![],
4959 routing: None,
4960 }
4961 }
4962
4963 fn cond(kind: ConditionKind) -> Condition {
4964 Condition {
4965 kind,
4966 params: serde_json::json!({}),
4967 }
4968 }
4969
4970 /// EMPTY-SPEC pin — a default [`EphemeralSpec`] (empty
4971 /// preconditions, empty postconditions) returns `false` for EVERY
4972 /// [`ConditionKind`]. Sweep `ConditionKind::ALL` so a new variant
4973 /// added without a matching arm in the presence probe surfaces at
4974 /// rustc's exhaustiveness gate on the ALL literal (arity forced by
4975 /// `[Self; 8]`) rather than as a silent false-positive at every
4976 /// downstream `condition-<kind>` ephemeral require-tag callsite.
4977 /// Byte-for-byte peer of
4978 /// `has_condition_kind_returns_false_on_empty_boundary_for_every_kind`
4979 /// on the [`Boundary`] surface.
4980 #[test]
4981 fn has_condition_kind_returns_false_on_empty_ephemeral_for_every_kind() {
4982 let spec = empty_ephemeral();
4983 for kind in ConditionKind::ALL {
4984 assert!(
4985 !spec.has_condition_kind(kind),
4986 "empty ephemeral spec must return false for {kind:?}",
4987 );
4988 }
4989 }
4990
4991 /// POSTCONDITION-only pin — an ephemeral spec that carries the
4992 /// kind on ONLY postconditions returns `true` for that kind,
4993 /// `false` for every other variant. Sweep the ALL × ALL cross so
4994 /// a regression that hard-coded the arm to a single kind or
4995 /// probed the wrong slot fails HERE at the substrate primitive.
4996 #[test]
4997 fn has_condition_kind_reads_ephemeral_postconditions_per_kind() {
4998 for populated in ConditionKind::ALL {
4999 let mut spec = empty_ephemeral();
5000 spec.postconditions.push(cond(populated));
5001 for query in ConditionKind::ALL {
5002 let expected = query == populated;
5003 assert_eq!(
5004 spec.has_condition_kind(query),
5005 expected,
5006 "ephemeral postcondition populated={populated:?}: \
5007 query {query:?} drifted",
5008 );
5009 }
5010 }
5011 }
5012
5013 /// PRECONDITION-only pin — mirrors the postcondition sweep on the
5014 /// other half of the union. Locks the union semantics on both
5015 /// halves separately so a regression that dropped the pre-
5016 /// condition side of the OR fails here even though the
5017 /// postcondition-side pin above passes.
5018 #[test]
5019 fn has_condition_kind_reads_ephemeral_preconditions_per_kind() {
5020 for populated in ConditionKind::ALL {
5021 let mut spec = empty_ephemeral();
5022 spec.preconditions.push(cond(populated));
5023 for query in ConditionKind::ALL {
5024 let expected = query == populated;
5025 assert_eq!(
5026 spec.has_condition_kind(query),
5027 expected,
5028 "ephemeral precondition populated={populated:?}: \
5029 query {query:?} drifted",
5030 );
5031 }
5032 }
5033 }
5034
5035 /// UNION pin — a kind that appears on preconditions returns
5036 /// `true` even when postconditions carries a DIFFERENT kind, and
5037 /// vice versa. Pins the OR-composition of the two halves so a
5038 /// regression that collapsed the union to an intersection (AND)
5039 /// silently reclassifies pre-only or post-only kinds as absent.
5040 /// Byte-for-byte peer of
5041 /// `has_condition_kind_unions_pre_and_post_condition_arms` on the
5042 /// [`Boundary`] surface.
5043 #[test]
5044 fn has_condition_kind_unions_pre_and_post_ephemeral_condition_arms() {
5045 let mut spec = empty_ephemeral();
5046 spec.preconditions
5047 .push(cond(ConditionKind::KustomizationHealthy));
5048 spec.postconditions
5049 .push(cond(ConditionKind::ClosedLoopAuth));
5050 assert!(
5051 spec.has_condition_kind(ConditionKind::KustomizationHealthy),
5052 "pre-only kind must resolve through the union",
5053 );
5054 assert!(
5055 spec.has_condition_kind(ConditionKind::ClosedLoopAuth),
5056 "post-only kind must resolve through the union",
5057 );
5058 assert!(
5059 !spec.has_condition_kind(ConditionKind::PromQL),
5060 "an absent kind must return false even with populated halves",
5061 );
5062 }
5063
5064 /// COMPOSITION pin — [`EphemeralSpec::has_condition_kind`] equals
5065 /// the OR of the two slice-level probes on the pre/post fields.
5066 /// The struct-level union body composes ONLY [`ConditionSliceExt::has_kind`]
5067 /// on each half; a regression that inlined a wide-net predicate
5068 /// (`.iter().any(|c| c.kind != kind).not()`, an `all` instead of
5069 /// `any`) drifts from the slice-level primitive here. Byte-for-
5070 /// byte peer of the
5071 /// `boundary_has_condition_kind_equals_or_of_half_slice_probes`
5072 /// composition pin on the [`Boundary`] surface.
5073 #[test]
5074 fn ephemeral_has_condition_kind_equals_or_of_half_slice_probes() {
5075 // Sweep every ConditionKind on both halves independently so the
5076 // cross of half-slice probes reaches the OR-composition body
5077 // exhaustively.
5078 for populated in ConditionKind::ALL {
5079 let mut spec = empty_ephemeral();
5080 spec.preconditions.push(cond(populated));
5081 spec.postconditions.push(cond(ConditionKind::PromQL));
5082 for query in ConditionKind::ALL {
5083 let via_or_of_halves =
5084 spec.preconditions.has_kind(query) || spec.postconditions.has_kind(query);
5085 assert_eq!(
5086 spec.has_condition_kind(query),
5087 via_or_of_halves,
5088 "populated={populated:?} query={query:?}: struct-level \
5089 union drifted from OR of slice-level probes",
5090 );
5091 }
5092 }
5093 }
5094
5095 // ── EphemeralSpec::has_(pre|post)condition_kind substrate pins ──
5096 //
5097 // Fail-before-pass-after granularity: the two half-slice arms did
5098 // not exist on the ephemeral surface before this commit — the
5099 // ephemeral require-tag classifier in `tatara-check` and the
5100 // `closed-loop-auth` fixed-tag arm reached
5101 // `spec.postconditions.has_kind(K)` through direct field access,
5102 // asymmetric with the union-arm [`EphemeralSpec::has_condition_kind`]
5103 // that already routed through the named struct method. The lift
5104 // closes the (precondition, postcondition, union) triad on the
5105 // ephemeral sugar surface so a future normalization at the
5106 // presence-probe shape lands at ONE site per surface for all
5107 // three arms.
5108
5109 /// EMPTY-SPEC pin — an ephemeral spec with no preconditions and
5110 /// no postconditions returns `false` for EVERY [`ConditionKind`]
5111 /// on both half-slice arms. Sweep `ConditionKind::ALL` so a new
5112 /// variant added without a matching arm surfaces at rustc's
5113 /// exhaustiveness gate on the ALL literal (arity forced by the
5114 /// closed-set array) rather than as a silent false-positive at
5115 /// every downstream require-tag callsite on the ephemeral
5116 /// surface.
5117 #[test]
5118 fn ephemeral_has_precondition_and_postcondition_kind_return_false_on_empty_spec() {
5119 let spec = empty_ephemeral();
5120 for kind in ConditionKind::ALL {
5121 assert!(
5122 !spec.has_precondition_kind(kind),
5123 "empty ephemeral must return false on precondition arm for {kind:?}",
5124 );
5125 assert!(
5126 !spec.has_postcondition_kind(kind),
5127 "empty ephemeral must return false on postcondition arm for {kind:?}",
5128 );
5129 }
5130 }
5131
5132 /// SLICE-SELECTIVITY pin (precondition arm) — an ephemeral spec
5133 /// with a kind on the precondition side ONLY resolves `true` at
5134 /// [`EphemeralSpec::has_precondition_kind`] and `false` at
5135 /// [`EphemeralSpec::has_postcondition_kind`]. Locks the (side-
5136 /// select, kind-select) partition so a regression that pointed
5137 /// the precondition arm at `self.postconditions` (a copy-paste
5138 /// from the sibling arm during the lift) surfaces HERE.
5139 #[test]
5140 fn ephemeral_has_precondition_kind_reads_preconditions_slice_only() {
5141 for populated in ConditionKind::ALL {
5142 let mut spec = empty_ephemeral();
5143 spec.preconditions.push(cond(populated));
5144 for query in ConditionKind::ALL {
5145 let expected_pre = query == populated;
5146 assert_eq!(
5147 spec.has_precondition_kind(query),
5148 expected_pre,
5149 "precondition-only populated={populated:?}: query {query:?} \
5150 drifted on ephemeral precondition arm",
5151 );
5152 assert!(
5153 !spec.has_postcondition_kind(query),
5154 "precondition-only populated={populated:?}: query {query:?} must \
5155 return false on ephemeral postcondition arm (postconditions is empty)",
5156 );
5157 }
5158 }
5159 }
5160
5161 /// SLICE-SELECTIVITY pin (postcondition arm) — mirror of the
5162 /// precondition-only sweep on the other half. Locks the
5163 /// postcondition arm's binding to `self.postconditions` so a
5164 /// regression that pointed it at `self.preconditions` fails HERE
5165 /// even though the precondition-arm pin above passes.
5166 #[test]
5167 fn ephemeral_has_postcondition_kind_reads_postconditions_slice_only() {
5168 for populated in ConditionKind::ALL {
5169 let mut spec = empty_ephemeral();
5170 spec.postconditions.push(cond(populated));
5171 for query in ConditionKind::ALL {
5172 let expected_post = query == populated;
5173 assert_eq!(
5174 spec.has_postcondition_kind(query),
5175 expected_post,
5176 "postcondition-only populated={populated:?}: query {query:?} \
5177 drifted on ephemeral postcondition arm",
5178 );
5179 assert!(
5180 !spec.has_precondition_kind(query),
5181 "postcondition-only populated={populated:?}: query {query:?} must \
5182 return false on ephemeral precondition arm (preconditions is empty)",
5183 );
5184 }
5185 }
5186 }
5187
5188 /// COMPOSITION-LAW pin — [`EphemeralSpec::has_condition_kind`]
5189 /// equals `has_precondition_kind(k) || has_postcondition_kind(k)`
5190 /// at EVERY (pre-populated, post-populated, query) triple on
5191 /// `ConditionKind::ALL`. Byte-for-byte peer of the
5192 /// `boundary_has_condition_kind_composes_precondition_and_postcondition_arms`
5193 /// composition-law pin on the [`Boundary`] surface — the
5194 /// two-surface parity contract binds the ephemeral sugar type
5195 /// and the point-domain boundary type through the SAME
5196 /// (`condition_kind = precondition_kind ∨ postcondition_kind`)
5197 /// composition, so every downstream `condition-<K>` require-tag
5198 /// classifier on either surface inherits the composition
5199 /// mechanically.
5200 #[test]
5201 fn ephemeral_has_condition_kind_composes_precondition_and_postcondition_arms() {
5202 for pre_kind in ConditionKind::ALL {
5203 for post_kind in ConditionKind::ALL {
5204 let mut spec = empty_ephemeral();
5205 spec.preconditions.push(cond(pre_kind));
5206 spec.postconditions.push(cond(post_kind));
5207 for query in ConditionKind::ALL {
5208 let via_arms =
5209 spec.has_precondition_kind(query) || spec.has_postcondition_kind(query);
5210 assert_eq!(
5211 spec.has_condition_kind(query),
5212 via_arms,
5213 "ephemeral union arm drifted from OR of half-slice arms: \
5214 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5215 );
5216 }
5217 }
5218 }
5219 }
5220
5221 /// SUBSTRATE-DELEGATION pin — the two half-slice arms on the
5222 /// ephemeral surface delegate verbatim to
5223 /// [`crate::boundary::ConditionSliceExt::has_kind`] on the
5224 /// underlying [`Vec<Condition>`] slice, no inline reimplementation.
5225 /// Sweep the full `ConditionKind::ALL` × `ConditionKind::ALL`
5226 /// cross so a regression that inlined a divergent walk at either
5227 /// arm surfaces HERE at the substrate boundary rather than as
5228 /// silent skew between the struct-level arm and the slice-level
5229 /// primitive.
5230 #[test]
5231 fn ephemeral_has_precondition_and_postcondition_kind_delegate_to_slice_has_kind() {
5232 for populated in ConditionKind::ALL {
5233 let mut spec = empty_ephemeral();
5234 spec.preconditions.push(cond(populated));
5235 spec.postconditions.push(cond(populated));
5236 for query in ConditionKind::ALL {
5237 assert_eq!(
5238 spec.has_precondition_kind(query),
5239 spec.preconditions.has_kind(query),
5240 "ephemeral precondition arm must delegate to preconditions.has_kind: \
5241 populated={populated:?} query={query:?}",
5242 );
5243 assert_eq!(
5244 spec.has_postcondition_kind(query),
5245 spec.postconditions.has_kind(query),
5246 "ephemeral postcondition arm must delegate to postconditions.has_kind: \
5247 populated={populated:?} query={query:?}",
5248 );
5249 }
5250 }
5251 }
5252
5253 // ── EphemeralSpec::find_(pre|post|)condition_kind widened triad ──
5254 //
5255 // Fail-before-pass-after granularity: the three widened
5256 // `find_*_kind` arms did not exist on the ephemeral surface before
5257 // this commit — the (widened `Option<&Condition>` return) axis
5258 // lived at ONE struct-level site (`Boundary::find_condition_kind`
5259 // on the point surface's nested [`Boundary`] slot). The lift adds
5260 // the peer inherent methods on the [`EphemeralSpec`] sugar-surface
5261 // so both struct-level widened callers compose against the SAME
5262 // slice-level substrate primitive
5263 // [`crate::boundary::ConditionSliceExt::find_kind`] in lockstep.
5264 // A regression that (a) hard-coded the arm to a single kind, (b)
5265 // reversed the walk order on the union (postcondition first), or
5266 // (c) collapsed `or_else` to `and_then` (silently narrowing the
5267 // union to an intersection) fails HERE at the substrate primitive
5268 // rather than as silent operator-facing drift at the ephemeral
5269 // require-tag surface.
5270
5271 /// EMPTY-SPEC pin (find-triad) — a default [`EphemeralSpec`]
5272 /// (empty preconditions, empty postconditions) returns `None`
5273 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
5274 /// `ConditionKind::ALL` × three-arm cross so a new variant added
5275 /// without a matching arm surfaces at rustc's exhaustiveness gate
5276 /// on the ALL literal (arity forced by the closed-set array)
5277 /// rather than as a silent false-`Some` at every downstream
5278 /// widened callsite on the ephemeral surface.
5279 #[test]
5280 fn ephemeral_find_condition_kind_triad_returns_none_on_empty_spec() {
5281 let spec = empty_ephemeral();
5282 for kind in ConditionKind::ALL {
5283 assert!(
5284 spec.find_precondition_kind(kind).is_none(),
5285 "empty ephemeral must return None on precondition find arm for {kind:?}",
5286 );
5287 assert!(
5288 spec.find_postcondition_kind(kind).is_none(),
5289 "empty ephemeral must return None on postcondition find arm for {kind:?}",
5290 );
5291 assert!(
5292 spec.find_condition_kind(kind).is_none(),
5293 "empty ephemeral must return None on union find arm for {kind:?}",
5294 );
5295 }
5296 }
5297
5298 /// SUBSTRATE-DELEGATION pin (ephemeral find-triad) — the three
5299 /// widened `find_*_kind` methods on [`EphemeralSpec`] delegate
5300 /// verbatim to [`crate::boundary::ConditionSliceExt::find_kind`]
5301 /// on the underlying [`Vec<Condition>`] slices, no inline
5302 /// reimplementation. The `find_condition_kind` union walks
5303 /// preconditions first then postconditions via `Option::or_else`.
5304 /// Sweep `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
5305 /// so a regression that (a) inlined a divergent walk at either
5306 /// half-slice arm, (b) reversed the union walk order on the
5307 /// ephemeral surface only (breaking two-surface parity with
5308 /// [`crate::boundary::Boundary::find_condition_kind`]), or (c)
5309 /// collapsed `or_else` to `and_then` surfaces HERE at the substrate
5310 /// boundary. Byte-for-byte peer of the point-domain
5311 /// `find_condition_kind_triad_delegates_to_slice_find_kind` pin.
5312 #[test]
5313 fn ephemeral_find_condition_kind_triad_delegates_to_slice_find_kind() {
5314 for pre_kind in ConditionKind::ALL {
5315 for post_kind in ConditionKind::ALL {
5316 let mut spec = empty_ephemeral();
5317 spec.preconditions.push(cond(pre_kind));
5318 spec.postconditions.push(cond(post_kind));
5319 for query in ConditionKind::ALL {
5320 let via_pre = spec.preconditions.find_kind(query);
5321 let via_post = spec.postconditions.find_kind(query);
5322 assert_eq!(
5323 spec.find_precondition_kind(query).map(|c| c.kind),
5324 via_pre.map(|c| c.kind),
5325 "ephemeral precondition find arm must delegate: \
5326 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5327 );
5328 assert_eq!(
5329 spec.find_postcondition_kind(query).map(|c| c.kind),
5330 via_post.map(|c| c.kind),
5331 "ephemeral postcondition find arm must delegate: \
5332 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5333 );
5334 let expected_union = via_pre.or(via_post).map(|c| c.kind);
5335 assert_eq!(
5336 spec.find_condition_kind(query).map(|c| c.kind),
5337 expected_union,
5338 "ephemeral union find arm must equal precondition.or_else(postcondition): \
5339 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5340 );
5341 }
5342 }
5343 }
5344 }
5345
5346 /// PRECONDITION-PRECEDENCE pin (ephemeral) — a kind authored on
5347 /// BOTH sides returns the precondition-side [`Condition`] from
5348 /// `find_condition_kind`. Byte-for-byte peer of the point-domain
5349 /// `find_condition_kind_returns_precondition_side_on_dual_populated`
5350 /// pin, so the two-surface parity contract binds the walk order
5351 /// on both surfaces through ONE composition law. Uses two params-
5352 /// distinguishable [`Condition`]s so a regression on the ephemeral
5353 /// surface only that reversed the walk order surfaces at the
5354 /// returned params payload rather than silently at the presence
5355 /// bit.
5356 #[test]
5357 fn ephemeral_find_condition_kind_returns_precondition_side_on_dual_populated() {
5358 let mut spec = empty_ephemeral();
5359 spec.preconditions.push(Condition {
5360 kind: ConditionKind::ClosedLoopAuth,
5361 params: serde_json::json!({ "side": "pre" }),
5362 });
5363 spec.postconditions.push(Condition {
5364 kind: ConditionKind::ClosedLoopAuth,
5365 params: serde_json::json!({ "side": "post" }),
5366 });
5367 let hit = spec
5368 .find_condition_kind(ConditionKind::ClosedLoopAuth)
5369 .expect("dual-populated ephemeral spec must resolve Some");
5370 assert_eq!(
5371 hit.params.get("side").and_then(serde_json::Value::as_str),
5372 Some("pre"),
5373 "ephemeral find_condition_kind must walk preconditions first",
5374 );
5375 }
5376
5377 /// STRUCT-LEVEL DELEGATION pin (ephemeral has ↔ find) — the three
5378 /// [`EphemeralSpec`] `has_*_kind` arms equal their widened peers'
5379 /// `.is_some()` projection at EVERY (pre-populated, post-populated,
5380 /// query) triple on `ConditionKind::ALL`. Byte-for-byte peer of
5381 /// the point-domain
5382 /// `boundary_has_triad_equals_find_triad_is_some_projection` pin,
5383 /// so both surfaces' has/find refinement bridge stays symmetric by
5384 /// construction — a future consumer that reads
5385 /// `spec.has_condition_kind(k)` as sugar for
5386 /// `spec.find_condition_kind(k).is_some()` on either surface stays
5387 /// typed against the SAME truth table across the two-surface
5388 /// parity contract.
5389 #[test]
5390 fn ephemeral_has_triad_equals_find_triad_is_some_projection() {
5391 for pre_kind in ConditionKind::ALL {
5392 for post_kind in ConditionKind::ALL {
5393 let mut spec = empty_ephemeral();
5394 spec.preconditions.push(cond(pre_kind));
5395 spec.postconditions.push(cond(post_kind));
5396 for query in ConditionKind::ALL {
5397 assert_eq!(
5398 spec.has_precondition_kind(query),
5399 spec.find_precondition_kind(query).is_some(),
5400 "ephemeral precondition has/find bridge drifted: \
5401 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5402 );
5403 assert_eq!(
5404 spec.has_postcondition_kind(query),
5405 spec.find_postcondition_kind(query).is_some(),
5406 "ephemeral postcondition has/find bridge drifted: \
5407 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5408 );
5409 assert_eq!(
5410 spec.has_condition_kind(query),
5411 spec.find_condition_kind(query).is_some(),
5412 "ephemeral union has/find bridge drifted: \
5413 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5414 );
5415 }
5416 }
5417 }
5418 }
5419
5420 // ── EphemeralSpec::iter_(pre|post|)condition_kind widened triad ──
5421 //
5422 // Fail-before-pass-after granularity: the three widened
5423 // `iter_*_kind` arms did not exist on the ephemeral surface before
5424 // this commit — the (widened `impl Iterator<Item = &Condition>`
5425 // stream) axis lived at ONE struct-level site
5426 // (`Boundary::iter_condition_kind` on the point surface's nested
5427 // [`Boundary`] slot). The lift adds the peer inherent methods on
5428 // the [`EphemeralSpec`] sugar-surface so both struct-level widened
5429 // callers compose against the SAME slice-level substrate primitive
5430 // [`crate::boundary::ConditionSliceExt::iter_kind`] in lockstep.
5431 // A regression that (a) hard-coded the arm to a single kind, (b)
5432 // reversed the chain order on the union (postcondition first), or
5433 // (c) collapsed the chain to a `.zip(...)` (silently narrowing the
5434 // union to an intersection-by-position) fails HERE at the
5435 // substrate primitive rather than as silent operator-facing drift
5436 // at the ephemeral require-tag surface.
5437
5438 /// EMPTY-SPEC pin (iter-triad) — a default [`EphemeralSpec`]
5439 /// (empty preconditions, empty postconditions) yields nothing
5440 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
5441 /// `ConditionKind::ALL` × three-arm cross so a new variant added
5442 /// without a matching arm surfaces at rustc's exhaustiveness gate
5443 /// on the ALL literal rather than as a silent phantom-yield at
5444 /// every downstream widened callsite on the ephemeral surface.
5445 #[test]
5446 fn ephemeral_iter_condition_kind_triad_yields_nothing_on_empty_spec() {
5447 let spec = empty_ephemeral();
5448 for kind in ConditionKind::ALL {
5449 assert_eq!(
5450 spec.iter_precondition_kind(kind).count(),
5451 0,
5452 "empty ephemeral must yield nothing on precondition iter arm for {kind:?}",
5453 );
5454 assert_eq!(
5455 spec.iter_postcondition_kind(kind).count(),
5456 0,
5457 "empty ephemeral must yield nothing on postcondition iter arm for {kind:?}",
5458 );
5459 assert_eq!(
5460 spec.iter_condition_kind(kind).count(),
5461 0,
5462 "empty ephemeral must yield nothing on union iter arm for {kind:?}",
5463 );
5464 }
5465 }
5466
5467 /// SUBSTRATE-DELEGATION pin (ephemeral iter-triad) — the three
5468 /// widened `iter_*_kind` methods on [`EphemeralSpec`] delegate
5469 /// verbatim to [`crate::boundary::ConditionSliceExt::iter_kind`]
5470 /// on the underlying [`Vec<Condition>`] slices, no inline
5471 /// reimplementation. The `iter_condition_kind` union chains
5472 /// preconditions first then postconditions via
5473 /// [`Iterator::chain`]. Sweep
5474 /// `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
5475 /// so a regression that (a) inlined a divergent walk at either
5476 /// half-slice arm, (b) reversed the chain order on the ephemeral
5477 /// surface only (breaking two-surface parity with
5478 /// [`crate::boundary::Boundary::iter_condition_kind`]), or (c)
5479 /// collapsed the chain to a `.zip(...)` surfaces HERE at the
5480 /// substrate boundary. Byte-for-byte peer of the point-domain
5481 /// `iter_condition_kind_triad_delegates_to_slice_iter_kind` pin.
5482 #[test]
5483 fn ephemeral_iter_condition_kind_triad_delegates_to_slice_iter_kind() {
5484 for pre_kind in ConditionKind::ALL {
5485 for post_kind in ConditionKind::ALL {
5486 let mut spec = empty_ephemeral();
5487 spec.preconditions.push(cond(pre_kind));
5488 spec.postconditions.push(cond(post_kind));
5489 for query in ConditionKind::ALL {
5490 let via_pre: Vec<_> = spec
5491 .preconditions
5492 .iter_kind(query)
5493 .map(|c| c.kind)
5494 .collect();
5495 let via_post: Vec<_> = spec
5496 .postconditions
5497 .iter_kind(query)
5498 .map(|c| c.kind)
5499 .collect();
5500 assert_eq!(
5501 spec.iter_precondition_kind(query)
5502 .map(|c| c.kind)
5503 .collect::<Vec<_>>(),
5504 via_pre,
5505 "ephemeral precondition iter arm must delegate: \
5506 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5507 );
5508 assert_eq!(
5509 spec.iter_postcondition_kind(query)
5510 .map(|c| c.kind)
5511 .collect::<Vec<_>>(),
5512 via_post,
5513 "ephemeral postcondition iter arm must delegate: \
5514 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5515 );
5516 let mut expected_union = via_pre.clone();
5517 expected_union.extend(via_post.iter().copied());
5518 assert_eq!(
5519 spec.iter_condition_kind(query)
5520 .map(|c| c.kind)
5521 .collect::<Vec<_>>(),
5522 expected_union,
5523 "ephemeral union iter arm must chain precondition ⨟ postcondition: \
5524 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5525 );
5526 }
5527 }
5528 }
5529 }
5530
5531 /// PRECONDITION-PRECEDENCE pin (ephemeral iter) — a kind
5532 /// authored on BOTH sides yields precondition-side matches
5533 /// FIRST in the union chain. Byte-for-byte peer of the
5534 /// point-domain
5535 /// `iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated`
5536 /// pin — the two-surface parity contract binds the chain order
5537 /// on both surfaces through ONE composition law. Uses two
5538 /// params-distinguishable [`Condition`]s so a regression on the
5539 /// ephemeral surface only that reversed the chain order surfaces
5540 /// at the returned params payload rather than silently at the
5541 /// count.
5542 #[test]
5543 fn ephemeral_iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated()
5544 {
5545 let mut spec = empty_ephemeral();
5546 spec.preconditions.push(Condition {
5547 kind: ConditionKind::ClosedLoopAuth,
5548 params: serde_json::json!({ "side": "pre-1" }),
5549 });
5550 spec.postconditions.push(Condition {
5551 kind: ConditionKind::ClosedLoopAuth,
5552 params: serde_json::json!({ "side": "post-1" }),
5553 });
5554 spec.postconditions.push(Condition {
5555 kind: ConditionKind::ClosedLoopAuth,
5556 params: serde_json::json!({ "side": "post-2" }),
5557 });
5558 let sides: Vec<_> = spec
5559 .iter_condition_kind(ConditionKind::ClosedLoopAuth)
5560 .map(|c| {
5561 c.params
5562 .get("side")
5563 .and_then(serde_json::Value::as_str)
5564 .unwrap_or_default()
5565 .to_owned()
5566 })
5567 .collect();
5568 assert_eq!(
5569 sides,
5570 vec!["pre-1".to_owned(), "post-1".to_owned(), "post-2".to_owned(),],
5571 "ephemeral iter_condition_kind must yield every precondition-side match before \
5572 any postcondition-side match (chain order pinned by two-surface parity)",
5573 );
5574 }
5575
5576 /// STRUCT-LEVEL DELEGATION pin (find ↔ iter on EphemeralSpec) —
5577 /// the three [`EphemeralSpec`] `find_*_kind` arms equal their
5578 /// widened peers' `.next()` projection at EVERY (pre-populated,
5579 /// post-populated, query) triple on `ConditionKind::ALL`.
5580 /// Byte-for-byte peer of the point-domain
5581 /// `boundary_find_triad_equals_iter_triad_next_projection` pin,
5582 /// so both surfaces' find/iter refinement bridge stays symmetric
5583 /// by construction across the two-surface parity contract.
5584 #[test]
5585 fn ephemeral_find_triad_equals_iter_triad_next_projection() {
5586 for pre_kind in ConditionKind::ALL {
5587 for post_kind in ConditionKind::ALL {
5588 let mut spec = empty_ephemeral();
5589 spec.preconditions.push(cond(pre_kind));
5590 spec.postconditions.push(cond(post_kind));
5591 for query in ConditionKind::ALL {
5592 assert_eq!(
5593 spec.find_precondition_kind(query).map(|c| c.kind),
5594 spec.iter_precondition_kind(query).next().map(|c| c.kind),
5595 "ephemeral precondition find/iter bridge drifted: \
5596 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5597 );
5598 assert_eq!(
5599 spec.find_postcondition_kind(query).map(|c| c.kind),
5600 spec.iter_postcondition_kind(query).next().map(|c| c.kind),
5601 "ephemeral postcondition find/iter bridge drifted: \
5602 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5603 );
5604 assert_eq!(
5605 spec.find_condition_kind(query).map(|c| c.kind),
5606 spec.iter_condition_kind(query).next().map(|c| c.kind),
5607 "ephemeral union find/iter bridge drifted: \
5608 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5609 );
5610 }
5611 }
5612 }
5613 }
5614
5615 // ── EphemeralSpec count triad — scalar cardinality peers ─────────
5616 //
5617 // Byte-for-byte peers of the point-domain `Boundary`
5618 // `count_(pre|post|)condition_kind` triad, tested at the ephemeral
5619 // sugar surface. Same SUM composition on the union arm, same
5620 // slice-level substrate delegation, same composition-law bridge
5621 // against the widened iter refinement.
5622
5623 /// EMPTY-SPEC pin (count-triad) — a default [`EphemeralSpec`]
5624 /// counts `0` from every arm of the count triad for EVERY
5625 /// [`ConditionKind`].
5626 #[test]
5627 fn ephemeral_count_condition_kind_triad_returns_zero_on_empty_spec() {
5628 let spec = empty_ephemeral();
5629 for kind in ConditionKind::ALL {
5630 assert_eq!(
5631 spec.count_precondition_kind(kind),
5632 0,
5633 "empty ephemeral must count 0 on precondition arm for {kind:?}",
5634 );
5635 assert_eq!(
5636 spec.count_postcondition_kind(kind),
5637 0,
5638 "empty ephemeral must count 0 on postcondition arm for {kind:?}",
5639 );
5640 assert_eq!(
5641 spec.count_condition_kind(kind),
5642 0,
5643 "empty ephemeral must count 0 on union arm for {kind:?}",
5644 );
5645 }
5646 }
5647
5648 /// SUBSTRATE-DELEGATION pin (ephemeral count-triad) — the three
5649 /// widened `count_*_kind` methods on [`EphemeralSpec`] delegate
5650 /// verbatim to [`crate::boundary::ConditionSliceExt::count_kind`]
5651 /// on the underlying [`Vec<Condition>`] slices. The
5652 /// `count_condition_kind` union SUMS preconditions and
5653 /// postconditions. Byte-for-byte peer of the point-domain
5654 /// `boundary_count_condition_kind_triad_delegates_and_sums_slice_count_kind`
5655 /// pin; a regression that (a) subtracted rather than summed, (b)
5656 /// collapsed the sum to [`std::cmp::max`], or (c) inlined a
5657 /// divergent count at either half-slice arm on the ephemeral
5658 /// surface only (breaking two-surface parity with [`Boundary`])
5659 /// surfaces HERE.
5660 #[test]
5661 fn ephemeral_count_condition_kind_triad_delegates_and_sums_slice_count_kind() {
5662 for pre_kind in ConditionKind::ALL {
5663 for post_kind in ConditionKind::ALL {
5664 let mut spec = empty_ephemeral();
5665 spec.preconditions.push(cond(pre_kind));
5666 spec.postconditions.push(cond(post_kind));
5667 for query in ConditionKind::ALL {
5668 let via_pre = spec.preconditions.count_kind(query);
5669 let via_post = spec.postconditions.count_kind(query);
5670 assert_eq!(
5671 spec.count_precondition_kind(query),
5672 via_pre,
5673 "ephemeral precondition count arm must delegate: \
5674 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5675 );
5676 assert_eq!(
5677 spec.count_postcondition_kind(query),
5678 via_post,
5679 "ephemeral postcondition count arm must delegate: \
5680 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5681 );
5682 assert_eq!(
5683 spec.count_condition_kind(query),
5684 via_pre + via_post,
5685 "ephemeral union count arm must SUM pre + post: \
5686 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5687 );
5688 }
5689 }
5690 }
5691 }
5692
5693 /// STRUCT-LEVEL DELEGATION pin (count ↔ iter on EphemeralSpec) —
5694 /// the three [`EphemeralSpec`] `count_*_kind` arms equal their
5695 /// widened peers' `.count()` projection at EVERY (pre-populated
5696 /// twice, post-populated, query) triple. Byte-for-byte peer of
5697 /// the point-domain
5698 /// `boundary_count_triad_equals_iter_triad_count_projection`
5699 /// pin. Uses two-preconditions authoring so the union arm's SUM
5700 /// composition witnesses a nontrivial cardinality (rather than
5701 /// coinciding with the presence bit).
5702 #[test]
5703 fn ephemeral_count_triad_equals_iter_triad_count_projection() {
5704 for pre_kind in ConditionKind::ALL {
5705 for post_kind in ConditionKind::ALL {
5706 let mut spec = empty_ephemeral();
5707 spec.preconditions.push(cond(pre_kind));
5708 spec.preconditions.push(cond(pre_kind));
5709 spec.postconditions.push(cond(post_kind));
5710 for query in ConditionKind::ALL {
5711 assert_eq!(
5712 spec.count_precondition_kind(query),
5713 spec.iter_precondition_kind(query).count(),
5714 "ephemeral precondition count/iter bridge drifted: \
5715 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5716 );
5717 assert_eq!(
5718 spec.count_postcondition_kind(query),
5719 spec.iter_postcondition_kind(query).count(),
5720 "ephemeral postcondition count/iter bridge drifted: \
5721 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5722 );
5723 assert_eq!(
5724 spec.count_condition_kind(query),
5725 spec.iter_condition_kind(query).count(),
5726 "ephemeral union count/iter bridge drifted: \
5727 pre={pre_kind:?} post={post_kind:?} query={query:?}",
5728 );
5729 }
5730 }
5731 }
5732 }
5733
5734 // ── EphemeralSpec distinct-set triad — substrate-delegation pin ──
5735 //
5736 // The (precondition, postcondition, condition-union) distinct-set
5737 // triad on [`EphemeralSpec`] delegates to the slice-level substrate
5738 // primitive [`crate::boundary::ConditionSliceExt::distinct_kinds`]
5739 // on each half-slice and composes the union via
5740 // [`Self::has_condition_kind`] over [`ConditionKind::ALL`] — byte-
5741 // for-byte peer of the point-surface distinct-set triad on
5742 // [`crate::boundary::Boundary`]. The two-surface parity contract
5743 // now covers FIVE refinements on the condition axis: the four
5744 // point-probe refinements (has / find / iter / count) AND the ONE
5745 // closed-set-inversion refinement (distinct-set) on both surfaces.
5746
5747 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-kind-count
5748 /// triad) — the three `distinct_*_kind_count` methods on
5749 /// [`EphemeralSpec`] delegate to the slice-level substrate
5750 /// primitive [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
5751 /// over the two `Vec<Condition>` slots and compose the union
5752 /// scalar via `ConditionKind::ALL.filter(|k|
5753 /// has_condition_kind(*k)).count()`. Byte-for-byte peer of the
5754 /// point-surface pin
5755 /// `distinct_condition_kind_count_triad_delegates_to_slice_distinct_kind_count`
5756 /// on [`crate::boundary::Boundary`] — the two-surface parity
5757 /// contract now binds every downstream scalar-cardinality consumer
5758 /// on either surface to the SAME closed-set walk through ONE
5759 /// substrate rather than through per-surface `.distinct_*_kinds().len()`
5760 /// re-materializations that pay for a heap allocation.
5761 #[test]
5762 fn ephemeral_distinct_condition_kind_count_triad_delegates_and_matches_distinct_kinds_len() {
5763 // Empty spec — every arm returns 0.
5764 let spec = empty_ephemeral();
5765 for kind in ConditionKind::ALL {
5766 assert_eq!(
5767 spec.distinct_precondition_kind_count(),
5768 0,
5769 "empty ephemeral spec must return 0 on distinct_precondition_kind_count, kind={kind:?}",
5770 );
5771 assert_eq!(
5772 spec.distinct_postcondition_kind_count(),
5773 0,
5774 "empty ephemeral spec must return 0 on distinct_postcondition_kind_count, kind={kind:?}",
5775 );
5776 assert_eq!(
5777 spec.distinct_condition_kind_count(),
5778 0,
5779 "empty ephemeral spec must return 0 on distinct_condition_kind_count, kind={kind:?}",
5780 );
5781 }
5782
5783 for pre_kind in ConditionKind::ALL {
5784 for post_kind in ConditionKind::ALL {
5785 let mut spec = empty_ephemeral();
5786 spec.preconditions.push(cond(pre_kind));
5787 spec.postconditions.push(cond(post_kind));
5788
5789 assert_eq!(
5790 spec.distinct_precondition_kind_count(),
5791 spec.preconditions.distinct_kind_count(),
5792 "EphemeralSpec::distinct_precondition_kind_count must delegate verbatim to \
5793 preconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
5794 );
5795 assert_eq!(
5796 spec.distinct_precondition_kind_count(),
5797 spec.distinct_precondition_kinds().len(),
5798 "EphemeralSpec::distinct_precondition_kind_count must equal \
5799 distinct_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
5800 );
5801 assert_eq!(
5802 spec.distinct_postcondition_kind_count(),
5803 spec.postconditions.distinct_kind_count(),
5804 "EphemeralSpec::distinct_postcondition_kind_count must delegate verbatim to \
5805 postconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
5806 );
5807 assert_eq!(
5808 spec.distinct_postcondition_kind_count(),
5809 spec.distinct_postcondition_kinds().len(),
5810 "EphemeralSpec::distinct_postcondition_kind_count must equal \
5811 distinct_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
5812 );
5813 let expected_union_count = if pre_kind == post_kind { 1 } else { 2 };
5814 assert_eq!(
5815 spec.distinct_condition_kind_count(),
5816 expected_union_count,
5817 "EphemeralSpec::distinct_condition_kind_count must count distinct union kinds \
5818 for pre={pre_kind:?} post={post_kind:?}",
5819 );
5820 assert_eq!(
5821 spec.distinct_condition_kind_count(),
5822 spec.distinct_condition_kinds().len(),
5823 "EphemeralSpec::distinct_condition_kind_count must equal \
5824 distinct_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
5825 );
5826 }
5827 }
5828 }
5829
5830 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-set triad)
5831 /// — the three `distinct_*_kinds` methods on [`EphemeralSpec`]
5832 /// delegate to the slice-level substrate primitive over the two
5833 /// `Vec<Condition>` slots and compose the union via
5834 /// `ConditionKind::ALL.filter(|k| has_condition_kind(*k))`. Byte-
5835 /// for-byte peer of the point-surface pin
5836 /// `distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds`
5837 /// on [`crate::boundary::Boundary`] — the two-surface parity
5838 /// contract binds every downstream distinct-set consumer on either
5839 /// surface to the SAME closed-set-inversion primitive through ONE
5840 /// substrate rather than through per-surface re-authored sweeps.
5841 #[test]
5842 fn ephemeral_distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds() {
5843 for pre_kind in ConditionKind::ALL {
5844 for post_kind in ConditionKind::ALL {
5845 let mut spec = empty_ephemeral();
5846 spec.preconditions.push(cond(pre_kind));
5847 spec.postconditions.push(cond(post_kind));
5848
5849 assert_eq!(
5850 spec.distinct_precondition_kinds(),
5851 spec.preconditions.distinct_kinds(),
5852 "EphemeralSpec::distinct_precondition_kinds must delegate verbatim to \
5853 preconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
5854 );
5855 assert_eq!(
5856 spec.distinct_postcondition_kinds(),
5857 spec.postconditions.distinct_kinds(),
5858 "EphemeralSpec::distinct_postcondition_kinds must delegate verbatim to \
5859 postconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
5860 );
5861 let expected_union: Vec<_> = ConditionKind::ALL
5862 .into_iter()
5863 .filter(|k| pre_kind == *k || post_kind == *k)
5864 .collect();
5865 assert_eq!(
5866 spec.distinct_condition_kinds(),
5867 expected_union,
5868 "EphemeralSpec::distinct_condition_kinds must equal ConditionKind::ALL-ordered \
5869 set-union of the two half-slice distinct-sets for pre={pre_kind:?} post={post_kind:?}",
5870 );
5871 }
5872 }
5873 }
5874
5875 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set triad) —
5876 /// the three `missing_*_kinds` methods on [`EphemeralSpec`]
5877 /// delegate to the slice-level substrate primitive
5878 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over the
5879 /// two `Vec<Condition>` slots and compose the union via
5880 /// `ConditionKind::ALL.filter(|k| !has_condition_kind(*k))`. Sweep
5881 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
5882 /// `missing_condition_kinds_triad_delegates_to_slice_missing_kinds`
5883 /// on the point-domain [`crate::boundary::Boundary`] surface —
5884 /// both peers compose against the SAME slice-level substrate
5885 /// primitive so a regression at the per-slice complement walk
5886 /// fails at that primitive's tests rather than as silent drift at
5887 /// either struct-level arm.
5888 #[test]
5889 fn ephemeral_missing_condition_kinds_triad_delegates_to_slice_missing_kinds() {
5890 // Empty ephemeral spec — every arm returns ConditionKind::ALL.
5891 let empty = empty_ephemeral();
5892 let all_kinds = ConditionKind::ALL.to_vec();
5893 assert_eq!(
5894 empty.missing_precondition_kinds(),
5895 all_kinds,
5896 "empty ephemeral spec must return ConditionKind::ALL on missing_precondition_kinds",
5897 );
5898 assert_eq!(
5899 empty.missing_postcondition_kinds(),
5900 all_kinds,
5901 "empty ephemeral spec must return ConditionKind::ALL on missing_postcondition_kinds",
5902 );
5903 assert_eq!(
5904 empty.missing_condition_kinds(),
5905 all_kinds,
5906 "empty ephemeral spec must return ConditionKind::ALL on missing_condition_kinds",
5907 );
5908
5909 for pre_kind in ConditionKind::ALL {
5910 for post_kind in ConditionKind::ALL {
5911 let mut spec = empty_ephemeral();
5912 spec.preconditions.push(cond(pre_kind));
5913 spec.postconditions.push(cond(post_kind));
5914
5915 assert_eq!(
5916 spec.missing_precondition_kinds(),
5917 spec.preconditions.missing_kinds(),
5918 "EphemeralSpec::missing_precondition_kinds must delegate verbatim to \
5919 preconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
5920 );
5921 assert_eq!(
5922 spec.missing_postcondition_kinds(),
5923 spec.postconditions.missing_kinds(),
5924 "EphemeralSpec::missing_postcondition_kinds must delegate verbatim to \
5925 postconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
5926 );
5927 // Union: a kind is missing from the union iff it is
5928 // missing from BOTH half-slices (SET-INTERSECTION).
5929 let expected_union: Vec<_> = ConditionKind::ALL
5930 .into_iter()
5931 .filter(|k| pre_kind != *k && post_kind != *k)
5932 .collect();
5933 assert_eq!(
5934 spec.missing_condition_kinds(),
5935 expected_union,
5936 "EphemeralSpec::missing_condition_kinds must equal ConditionKind::ALL-ordered \
5937 set-INTERSECTION of the two half-slice missing-sets for pre={pre_kind:?} post={post_kind:?}",
5938 );
5939 // Partition invariant (distinct ∪ missing == ALL, disjoint).
5940 let distinct = spec.distinct_condition_kinds();
5941 let missing = spec.missing_condition_kinds();
5942 for kind in ConditionKind::ALL {
5943 assert!(
5944 distinct.contains(&kind) ^ missing.contains(&kind),
5945 "EphemeralSpec (distinct, missing) partition violated on {kind:?} for pre={pre_kind:?} post={post_kind:?}",
5946 );
5947 }
5948 assert_eq!(
5949 distinct.len() + missing.len(),
5950 ConditionKind::ALL.len(),
5951 "EphemeralSpec (distinct, missing) cardinality partition drift for pre={pre_kind:?} post={post_kind:?}",
5952 );
5953 }
5954 }
5955 }
5956
5957 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-kind-count triad)
5958 /// — the three `missing_*_kind_count` methods on [`EphemeralSpec`]
5959 /// delegate to the slice-level substrate primitive
5960 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
5961 /// the two `Vec<Condition>` slots and compose the union scalar via
5962 /// `ConditionKind::ALL.iter().filter(|k|
5963 /// !has_condition_kind(**k)).count()`. Sweep
5964 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
5965 /// `missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count`
5966 /// on the point-domain [`crate::boundary::Boundary`] surface —
5967 /// both peers compose against the SAME slice-level substrate
5968 /// primitive so a regression at the per-slice negated closed-set
5969 /// walk fails at that primitive's tests rather than as silent drift
5970 /// at either struct-level scalar-cardinality arm. Also pins the
5971 /// scalar-partition invariant `distinct_kind_count +
5972 /// missing_kind_count == ConditionKind::ALL.len()` per arrangement.
5973 #[test]
5974 fn ephemeral_missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count() {
5975 // Empty ephemeral spec — every arm returns ConditionKind::ALL.len().
5976 let empty = empty_ephemeral();
5977 let total = ConditionKind::ALL.len();
5978 assert_eq!(
5979 empty.missing_precondition_kind_count(),
5980 total,
5981 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_precondition_kind_count",
5982 );
5983 assert_eq!(
5984 empty.missing_postcondition_kind_count(),
5985 total,
5986 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_postcondition_kind_count",
5987 );
5988 assert_eq!(
5989 empty.missing_condition_kind_count(),
5990 total,
5991 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_condition_kind_count",
5992 );
5993
5994 for pre_kind in ConditionKind::ALL {
5995 for post_kind in ConditionKind::ALL {
5996 let mut spec = empty_ephemeral();
5997 spec.preconditions.push(cond(pre_kind));
5998 spec.postconditions.push(cond(post_kind));
5999
6000 // Half-slice arms delegate byte-for-byte to the slice
6001 // substrate primitive.
6002 assert_eq!(
6003 spec.missing_precondition_kind_count(),
6004 spec.preconditions.missing_kind_count(),
6005 "EphemeralSpec::missing_precondition_kind_count must delegate verbatim to \
6006 preconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6007 );
6008 assert_eq!(
6009 spec.missing_precondition_kind_count(),
6010 spec.missing_precondition_kinds().len(),
6011 "EphemeralSpec::missing_precondition_kind_count must equal \
6012 missing_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6013 );
6014 assert_eq!(
6015 spec.missing_postcondition_kind_count(),
6016 spec.postconditions.missing_kind_count(),
6017 "EphemeralSpec::missing_postcondition_kind_count must delegate verbatim to \
6018 postconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
6019 );
6020 assert_eq!(
6021 spec.missing_postcondition_kind_count(),
6022 spec.missing_postcondition_kinds().len(),
6023 "EphemeralSpec::missing_postcondition_kind_count must equal \
6024 missing_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6025 );
6026 // Union arm equals missing_condition_kinds().len().
6027 assert_eq!(
6028 spec.missing_condition_kind_count(),
6029 spec.missing_condition_kinds().len(),
6030 "EphemeralSpec::missing_condition_kind_count must equal \
6031 missing_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
6032 );
6033 // Scalar-partition invariant: distinct + missing == ALL.
6034 assert_eq!(
6035 spec.distinct_condition_kind_count() + spec.missing_condition_kind_count(),
6036 ConditionKind::ALL.len(),
6037 "EphemeralSpec (distinct, missing) scalar partition drift for pre={pre_kind:?} post={post_kind:?}",
6038 );
6039 }
6040 }
6041 }
6042
6043 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-distinct-kind
6044 /// triad) — the three `first_distinct_*_kind` methods on
6045 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
6046 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] over
6047 /// the two `Vec<Condition>` slots and compose the union via
6048 /// `ConditionKind::ALL.iter().copied().find(|k|
6049 /// has_condition_kind(*k))`. Byte-for-byte peer of
6050 /// `first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind`
6051 /// on the point-domain [`crate::boundary::Boundary`] surface — both
6052 /// peers compose against the SAME slice-level substrate primitive
6053 /// so a regression at the per-slice short-circuit walk fails at
6054 /// that primitive's tests rather than as silent drift at either
6055 /// struct-level earliest-element arm.
6056 #[test]
6057 fn ephemeral_first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind() {
6058 // Empty ephemeral spec — every arm returns None.
6059 let empty = empty_ephemeral();
6060 assert_eq!(
6061 empty.first_distinct_precondition_kind(),
6062 None,
6063 "empty ephemeral spec must return None on first_distinct_precondition_kind",
6064 );
6065 assert_eq!(
6066 empty.first_distinct_postcondition_kind(),
6067 None,
6068 "empty ephemeral spec must return None on first_distinct_postcondition_kind",
6069 );
6070 assert_eq!(
6071 empty.first_distinct_condition_kind(),
6072 None,
6073 "empty ephemeral spec must return None on first_distinct_condition_kind",
6074 );
6075
6076 for pre_kind in ConditionKind::ALL {
6077 for post_kind in ConditionKind::ALL {
6078 let mut spec = empty_ephemeral();
6079 spec.preconditions.push(cond(pre_kind));
6080 spec.postconditions.push(cond(post_kind));
6081
6082 assert_eq!(
6083 spec.first_distinct_precondition_kind(),
6084 spec.preconditions.first_distinct_kind(),
6085 "EphemeralSpec::first_distinct_precondition_kind must delegate verbatim to \
6086 preconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6087 );
6088 assert_eq!(
6089 spec.first_distinct_precondition_kind(),
6090 spec.distinct_precondition_kinds().first().copied(),
6091 "EphemeralSpec::first_distinct_precondition_kind must equal \
6092 distinct_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6093 );
6094 assert_eq!(
6095 spec.first_distinct_postcondition_kind(),
6096 spec.postconditions.first_distinct_kind(),
6097 "EphemeralSpec::first_distinct_postcondition_kind must delegate verbatim to \
6098 postconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6099 );
6100 assert_eq!(
6101 spec.first_distinct_postcondition_kind(),
6102 spec.distinct_postcondition_kinds().first().copied(),
6103 "EphemeralSpec::first_distinct_postcondition_kind must equal \
6104 distinct_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6105 );
6106 let expected_union = ConditionKind::ALL
6107 .into_iter()
6108 .find(|k| pre_kind == *k || post_kind == *k);
6109 assert_eq!(
6110 spec.first_distinct_condition_kind(),
6111 expected_union,
6112 "EphemeralSpec::first_distinct_condition_kind must equal earliest ALL entry \
6113 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6114 );
6115 assert_eq!(
6116 spec.first_distinct_condition_kind(),
6117 spec.distinct_condition_kinds().first().copied(),
6118 "EphemeralSpec::first_distinct_condition_kind must equal \
6119 distinct_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6120 );
6121 }
6122 }
6123 }
6124
6125 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-missing-kind triad)
6126 /// — the three `first_missing_*_kind` methods on [`EphemeralSpec`]
6127 /// delegate to the slice-level substrate primitive
6128 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`] over
6129 /// the two `Vec<Condition>` slots and compose the union via
6130 /// `ConditionKind::ALL.iter().copied().find(|k|
6131 /// !has_condition_kind(*k))`. Byte-for-byte peer of
6132 /// `first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind`
6133 /// on the point-domain [`crate::boundary::Boundary`] surface.
6134 #[test]
6135 fn ephemeral_first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind() {
6136 // Empty ephemeral spec — every arm returns Some(ConditionKind::ALL[0]).
6137 let empty = empty_ephemeral();
6138 let first = Some(ConditionKind::ALL[0]);
6139 assert_eq!(
6140 empty.first_missing_precondition_kind(),
6141 first,
6142 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_precondition_kind",
6143 );
6144 assert_eq!(
6145 empty.first_missing_postcondition_kind(),
6146 first,
6147 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_postcondition_kind",
6148 );
6149 assert_eq!(
6150 empty.first_missing_condition_kind(),
6151 first,
6152 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_condition_kind",
6153 );
6154
6155 for pre_kind in ConditionKind::ALL {
6156 for post_kind in ConditionKind::ALL {
6157 let mut spec = empty_ephemeral();
6158 spec.preconditions.push(cond(pre_kind));
6159 spec.postconditions.push(cond(post_kind));
6160
6161 assert_eq!(
6162 spec.first_missing_precondition_kind(),
6163 spec.preconditions.first_missing_kind(),
6164 "EphemeralSpec::first_missing_precondition_kind must delegate verbatim to \
6165 preconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6166 );
6167 assert_eq!(
6168 spec.first_missing_precondition_kind(),
6169 spec.missing_precondition_kinds().first().copied(),
6170 "EphemeralSpec::first_missing_precondition_kind must equal \
6171 missing_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6172 );
6173 assert_eq!(
6174 spec.first_missing_postcondition_kind(),
6175 spec.postconditions.first_missing_kind(),
6176 "EphemeralSpec::first_missing_postcondition_kind must delegate verbatim to \
6177 postconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6178 );
6179 assert_eq!(
6180 spec.first_missing_postcondition_kind(),
6181 spec.missing_postcondition_kinds().first().copied(),
6182 "EphemeralSpec::first_missing_postcondition_kind must equal \
6183 missing_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6184 );
6185 let expected_union = ConditionKind::ALL
6186 .into_iter()
6187 .find(|k| pre_kind != *k && post_kind != *k);
6188 assert_eq!(
6189 spec.first_missing_condition_kind(),
6190 expected_union,
6191 "EphemeralSpec::first_missing_condition_kind must equal earliest ALL entry \
6192 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6193 );
6194 assert_eq!(
6195 spec.first_missing_condition_kind(),
6196 spec.missing_condition_kinds().first().copied(),
6197 "EphemeralSpec::first_missing_condition_kind must equal \
6198 missing_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
6199 );
6200 }
6201 }
6202 }
6203
6204 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-distinct-kind
6205 /// triad) — the three `last_distinct_*_kind` methods on
6206 /// [`EphemeralSpec`] delegate to the slice-level substrate
6207 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
6208 /// over the two `Vec<Condition>` slots and compose the union via
6209 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
6210 /// has_condition_kind(*k))`. Byte-for-byte peer of
6211 /// `last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind`
6212 /// on the point-domain [`crate::boundary::Boundary`] surface —
6213 /// both peers compose against the SAME slice-level substrate
6214 /// primitive so a regression at the per-slice REVERSED short-
6215 /// circuit walk fails at that primitive's tests rather than as
6216 /// silent drift at either struct-level latest-element arm.
6217 #[test]
6218 fn ephemeral_last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind() {
6219 // Empty ephemeral spec — every arm returns None.
6220 let empty = empty_ephemeral();
6221 assert_eq!(
6222 empty.last_distinct_precondition_kind(),
6223 None,
6224 "empty ephemeral spec must return None on last_distinct_precondition_kind",
6225 );
6226 assert_eq!(
6227 empty.last_distinct_postcondition_kind(),
6228 None,
6229 "empty ephemeral spec must return None on last_distinct_postcondition_kind",
6230 );
6231 assert_eq!(
6232 empty.last_distinct_condition_kind(),
6233 None,
6234 "empty ephemeral spec must return None on last_distinct_condition_kind",
6235 );
6236
6237 for pre_kind in ConditionKind::ALL {
6238 for post_kind in ConditionKind::ALL {
6239 let mut spec = empty_ephemeral();
6240 spec.preconditions.push(cond(pre_kind));
6241 spec.postconditions.push(cond(post_kind));
6242
6243 assert_eq!(
6244 spec.last_distinct_precondition_kind(),
6245 spec.preconditions.last_distinct_kind(),
6246 "EphemeralSpec::last_distinct_precondition_kind must delegate verbatim to \
6247 preconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6248 );
6249 assert_eq!(
6250 spec.last_distinct_precondition_kind(),
6251 spec.distinct_precondition_kinds().last().copied(),
6252 "EphemeralSpec::last_distinct_precondition_kind must equal \
6253 distinct_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6254 );
6255 assert_eq!(
6256 spec.last_distinct_postcondition_kind(),
6257 spec.postconditions.last_distinct_kind(),
6258 "EphemeralSpec::last_distinct_postcondition_kind must delegate verbatim to \
6259 postconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
6260 );
6261 assert_eq!(
6262 spec.last_distinct_postcondition_kind(),
6263 spec.distinct_postcondition_kinds().last().copied(),
6264 "EphemeralSpec::last_distinct_postcondition_kind must equal \
6265 distinct_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6266 );
6267 let expected_union = ConditionKind::ALL
6268 .into_iter()
6269 .rev()
6270 .find(|k| pre_kind == *k || post_kind == *k);
6271 assert_eq!(
6272 spec.last_distinct_condition_kind(),
6273 expected_union,
6274 "EphemeralSpec::last_distinct_condition_kind must equal latest ALL entry \
6275 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6276 );
6277 assert_eq!(
6278 spec.last_distinct_condition_kind(),
6279 spec.distinct_condition_kinds().last().copied(),
6280 "EphemeralSpec::last_distinct_condition_kind must equal \
6281 distinct_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6282 );
6283 }
6284 }
6285 }
6286
6287 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-missing-kind triad)
6288 /// — the three `last_missing_*_kind` methods on [`EphemeralSpec`]
6289 /// delegate to the slice-level substrate primitive
6290 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] over
6291 /// the two `Vec<Condition>` slots and compose the union via
6292 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
6293 /// !has_condition_kind(*k))`. Byte-for-byte peer of
6294 /// `last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind`
6295 /// on the point-domain [`crate::boundary::Boundary`] surface.
6296 #[test]
6297 fn ephemeral_last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind() {
6298 // Empty ephemeral spec — every arm returns Some(*ConditionKind::ALL.last().unwrap()).
6299 let empty = empty_ephemeral();
6300 let last = ConditionKind::ALL.last().copied();
6301 assert_eq!(
6302 empty.last_missing_precondition_kind(),
6303 last,
6304 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_precondition_kind",
6305 );
6306 assert_eq!(
6307 empty.last_missing_postcondition_kind(),
6308 last,
6309 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_postcondition_kind",
6310 );
6311 assert_eq!(
6312 empty.last_missing_condition_kind(),
6313 last,
6314 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_condition_kind",
6315 );
6316
6317 for pre_kind in ConditionKind::ALL {
6318 for post_kind in ConditionKind::ALL {
6319 let mut spec = empty_ephemeral();
6320 spec.preconditions.push(cond(pre_kind));
6321 spec.postconditions.push(cond(post_kind));
6322
6323 assert_eq!(
6324 spec.last_missing_precondition_kind(),
6325 spec.preconditions.last_missing_kind(),
6326 "EphemeralSpec::last_missing_precondition_kind must delegate verbatim to \
6327 preconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6328 );
6329 assert_eq!(
6330 spec.last_missing_precondition_kind(),
6331 spec.missing_precondition_kinds().last().copied(),
6332 "EphemeralSpec::last_missing_precondition_kind must equal \
6333 missing_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6334 );
6335 assert_eq!(
6336 spec.last_missing_postcondition_kind(),
6337 spec.postconditions.last_missing_kind(),
6338 "EphemeralSpec::last_missing_postcondition_kind must delegate verbatim to \
6339 postconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
6340 );
6341 assert_eq!(
6342 spec.last_missing_postcondition_kind(),
6343 spec.missing_postcondition_kinds().last().copied(),
6344 "EphemeralSpec::last_missing_postcondition_kind must equal \
6345 missing_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6346 );
6347 let expected_union = ConditionKind::ALL
6348 .into_iter()
6349 .rev()
6350 .find(|k| pre_kind != *k && post_kind != *k);
6351 assert_eq!(
6352 spec.last_missing_condition_kind(),
6353 expected_union,
6354 "EphemeralSpec::last_missing_condition_kind must equal latest ALL entry \
6355 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
6356 );
6357 assert_eq!(
6358 spec.last_missing_condition_kind(),
6359 spec.missing_condition_kinds().last().copied(),
6360 "EphemeralSpec::last_missing_condition_kind must equal \
6361 missing_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
6362 );
6363 }
6364 }
6365 }
6366
6367 // ── assert_slice_refinement_composition_laws — mirror invocations ──
6368 //
6369 // The substrate testkit primitive
6370 // [`crate::boundary::assert_slice_refinement_composition_laws`]
6371 // pins the FOUR composition laws that bind the
6372 // [`crate::boundary::ConditionSliceExt`] refinement algebra
6373 // (find ↔ iter, count ↔ iter, has ↔ find, has ↔ count) at ONE
6374 // call site per authored arrangement, sweeping
6375 // [`ConditionKind::ALL`]. The two ephemeral-surface tests below
6376 // dispatch the primitive against the two `Vec<Condition>` slots
6377 // ([`EphemeralSpec::preconditions`] +
6378 // [`EphemeralSpec::postconditions`]) authored through the
6379 // ephemeral-surface test-fixture — byte-for-byte peer of the
6380 // point-surface `slice_refinement_composition_laws_hold_across_authored_arrangements`
6381 // + `slice_refinement_composition_laws_hold_on_interleaved_duplicates`
6382 // pins on the [`crate::boundary::Boundary`] surface. Two-surface
6383 // parity contract: the substrate primitive holds on every slice
6384 // reachable through either the point-surface `.preconditions` /
6385 // `.postconditions` fields OR the ephemeral-surface's
6386 // eponymous field pair.
6387
6388 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate
6389 /// primitive [`assert_slice_refinement_composition_laws`] holds
6390 /// on both [`EphemeralSpec::preconditions`] and
6391 /// [`EphemeralSpec::postconditions`] slices for every populated-
6392 /// pair authored through the ephemeral-surface test-fixture.
6393 /// Byte-for-byte peer of
6394 /// `slice_refinement_composition_laws_hold_across_authored_arrangements`
6395 /// on the point surface.
6396 #[test]
6397 fn ephemeral_slice_refinement_composition_laws_hold_across_authored_arrangements() {
6398 let empty = empty_ephemeral();
6399 assert_slice_refinement_composition_laws(empty.preconditions.as_slice());
6400 assert_slice_refinement_composition_laws(empty.postconditions.as_slice());
6401
6402 for pre_kind in ConditionKind::ALL {
6403 for post_kind in ConditionKind::ALL {
6404 let mut spec = empty_ephemeral();
6405 spec.preconditions.push(cond(pre_kind));
6406 spec.postconditions.push(cond(post_kind));
6407 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
6408 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
6409 }
6410 }
6411
6412 for populated in ConditionKind::ALL {
6413 let mut spec = empty_ephemeral();
6414 spec.preconditions.push(cond(populated));
6415 spec.preconditions.push(cond(populated));
6416 spec.preconditions.push(cond(populated));
6417 spec.postconditions.push(cond(populated));
6418 spec.postconditions.push(cond(populated));
6419 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
6420 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
6421 }
6422 }
6423
6424 // ── assert_surface_union_composition_laws — ephemeral surface ────
6425 //
6426 // The substrate testkit macro
6427 // [`crate::assert_surface_union_composition_laws`] pins the FOUR
6428 // union composition laws (has: OR, find: or_else, iter: chain,
6429 // count: SUM) that bind the (pre, post, union) refinement triads
6430 // on the [`EphemeralSpec`] sugar-surface at ONE call site per
6431 // authored arrangement, sweeping [`ConditionKind::ALL`]. Byte-for-
6432 // byte peer of the point-surface
6433 // `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
6434 // / `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
6435 // pins on the [`crate::boundary::Boundary`] surface — the two-
6436 // surface parity contract binds every downstream `condition-<K>`
6437 // / `precondition-<K>` / `postcondition-<K>` require-tag classifier
6438 // on either surface to the SAME four union-composition operators
6439 // through ONE substrate primitive rather than through per-surface
6440 // author-time re-authored sweeps.
6441
6442 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate macro
6443 /// [`crate::assert_surface_union_composition_laws`] passes on
6444 /// [`EphemeralSpec`] for the four canonical authored arrangements
6445 /// (empty spec, precondition-only populated, postcondition-only
6446 /// populated, dual-populated sweep over `ALL × ALL`). Byte-for-byte
6447 /// peer of the point-surface
6448 /// `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
6449 /// pin — the two-surface parity contract binds every union
6450 /// composition law on both surfaces to the SAME substrate
6451 /// primitive.
6452 #[test]
6453 fn ephemeral_surface_union_composition_laws_hold_across_authored_arrangements() {
6454 let empty = empty_ephemeral();
6455 crate::assert_surface_union_composition_laws!(empty);
6456
6457 for populated in ConditionKind::ALL {
6458 let mut pre_only = empty_ephemeral();
6459 pre_only.preconditions.push(cond(populated));
6460 crate::assert_surface_union_composition_laws!(pre_only);
6461
6462 let mut post_only = empty_ephemeral();
6463 post_only.postconditions.push(cond(populated));
6464 crate::assert_surface_union_composition_laws!(post_only);
6465 }
6466
6467 for pre_kind in ConditionKind::ALL {
6468 for post_kind in ConditionKind::ALL {
6469 let mut dual = empty_ephemeral();
6470 dual.preconditions.push(cond(pre_kind));
6471 dual.postconditions.push(cond(post_kind));
6472 crate::assert_surface_union_composition_laws!(dual);
6473 }
6474 }
6475 }
6476
6477 /// SUBSTRATE PANEL pin (ephemeral surface, params-distinguishable
6478 /// duplicates) — the substrate macro holds on an [`EphemeralSpec`]
6479 /// whose two half-slices each carry duplicates of the same kind at
6480 /// multiple positions interleaved with a distinct kind. Byte-for-
6481 /// byte peer of the point-surface
6482 /// `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
6483 /// pin — the non-degenerate composition of every union arm on the
6484 /// sugar-surface binds against the SAME four monoid operators as
6485 /// the point-surface peer. A regression on the ephemeral surface
6486 /// only that (a) collapsed `find`'s `or_else` to `and_then`, (b)
6487 /// collapsed `iter`'s `chain` to `zip`, or (c) collapsed `count`'s
6488 /// SUM to `max` surfaces HERE, breaking two-surface parity.
6489 #[test]
6490 fn ephemeral_surface_union_composition_laws_hold_on_interleaved_duplicates() {
6491 let mut spec = empty_ephemeral();
6492 spec.preconditions.push(Condition {
6493 kind: ConditionKind::ClosedLoopAuth,
6494 params: serde_json::json!({ "side": "pre-1" }),
6495 });
6496 spec.preconditions.push(Condition {
6497 kind: ConditionKind::PromQL,
6498 params: serde_json::json!({ "query": "up" }),
6499 });
6500 spec.preconditions.push(Condition {
6501 kind: ConditionKind::ClosedLoopAuth,
6502 params: serde_json::json!({ "side": "pre-2" }),
6503 });
6504 spec.postconditions.push(Condition {
6505 kind: ConditionKind::PromQL,
6506 params: serde_json::json!({ "query": "healthy" }),
6507 });
6508 spec.postconditions.push(Condition {
6509 kind: ConditionKind::ClosedLoopAuth,
6510 params: serde_json::json!({ "side": "post-1" }),
6511 });
6512 crate::assert_surface_union_composition_laws!(spec);
6513 }
6514
6515 #[test]
6516 fn from_impl_clears_other_intent_variants() {
6517 // Even if someone constructs an EphemeralSpec by hand and the
6518 // resulting ProcessSpec is later mutated, the From bridge sets
6519 // every non-Aplicacao slot to None explicitly.
6520 let e = EphemeralSpec {
6521 aplicacao: demo_overlay(),
6522 ttl: "10m".into(),
6523 teardown: TeardownPolicy::Never,
6524 max_concurrent: 0,
6525 postconditions: vec![],
6526 preconditions: vec![],
6527 verify_timeout: None,
6528 classification: None,
6529 parent: Some("seph.1".into()),
6530 exports: vec![],
6531 routing: None,
6532 };
6533 let ps: ProcessSpec = e.into();
6534 assert!(ps.intent.nix.is_none());
6535 assert!(ps.intent.flux.is_none());
6536 assert!(ps.intent.lisp.is_none());
6537 assert!(ps.intent.container.is_none());
6538 assert!(ps.intent.guest.is_none());
6539 assert!(ps.intent.aplicacao.is_some());
6540 assert_eq!(ps.identity.parent.as_deref(), Some("seph.1"));
6541 }
6542
6543 // ── EphemeralSpec::has_teardown_policy substrate pins ────────────
6544 //
6545 // Fail-before-pass-after granularity:
6546 // `EphemeralSpec::has_teardown_policy` did not exist before this
6547 // commit — the (`self.teardown == kind`) scalar-carrier probe on
6548 // the sugar-surface [`EphemeralSpec`] lived only implicitly via
6549 // hand-authored comparisons at potential future call sites, with
6550 // no analogue to the peer
6551 // [`crate::lifetime::EphemeralLifetime::has_teardown_policy`] on
6552 // the point-surface carrier. The lift adds the peer inherent
6553 // method on the [`EphemeralSpec`] sugar-surface so both surfaces'
6554 // `teardown-policy-<kind>` require-tag families in
6555 // `tatara-reconciler::bin::tatara-check` compose against the SAME
6556 // scalar `==` shape in lockstep. A regression that (a) hard-coded
6557 // the arm to a single kind, (b) inverted the closed-set match
6558 // (silently returning `true` on non-matching variants), or (c)
6559 // probed the wrong slot (a stray comparison against `ttl` /
6560 // `max_concurrent`) fails HERE at the substrate primitive rather
6561 // than as silent operator-facing drift at the ephemeral
6562 // `teardown-policy-<kind>` require-tag surface.
6563
6564 /// STORED-slot pin — an ephemeral spec that carries a given
6565 /// [`TeardownPolicy`] returns `true` for that kind, `false` for
6566 /// every other variant. Sweep the [`TeardownPolicy::ALL`] × ALL
6567 /// cross so a regression that hard-coded the arm to a single kind
6568 /// or wired the closure to a fixed unrelated field fails HERE at
6569 /// the substrate primitive. Byte-for-byte peer of
6570 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_returns_true_iff_variant_matches`]
6571 /// on the point-surface [`crate::lifetime::EphemeralLifetime`]
6572 /// carrier — the two surfaces publish identical `==` scalar
6573 /// semantics on their respective `teardown` / `teardown_policy`
6574 /// slots.
6575 #[test]
6576 fn has_teardown_policy_returns_true_iff_ephemeral_teardown_matches_per_kind() {
6577 for populated in TeardownPolicy::ALL {
6578 let mut spec = empty_ephemeral();
6579 spec.teardown = populated;
6580 for query in TeardownPolicy::ALL {
6581 let expected = query == populated;
6582 assert_eq!(
6583 spec.has_teardown_policy(query),
6584 expected,
6585 "ephemeral teardown={populated:?}: query {query:?} drifted",
6586 );
6587 }
6588 }
6589 }
6590
6591 /// DEFAULT-SLOT pin — an [`EphemeralSpec`] whose `teardown` slot
6592 /// is [`TeardownPolicy::default`] (`Always`) returns `true` for
6593 /// `Always` and `false` for every other variant. The
6594 /// (required-scalar-child) corner has no absent state — a
6595 /// hand-authored spec that omits `:teardown` from the
6596 /// `(defephemeral …)` form IS configured for `Always`, and this
6597 /// pin locks the corner's default-arm short-circuit as identical
6598 /// to the (Option-parent × defaulted-scalar-child) corner's
6599 /// reachable arm on the point surface (both return `true` on
6600 /// `Always` only). Byte-for-byte peer of
6601 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_default_probes_always_only`]
6602 /// on the point-surface carrier.
6603 #[test]
6604 fn has_teardown_policy_default_probes_always_only_on_ephemeral() {
6605 let spec = EphemeralSpec {
6606 teardown: TeardownPolicy::default(),
6607 ..empty_ephemeral()
6608 };
6609 for kind in TeardownPolicy::ALL {
6610 let expected = kind == TeardownPolicy::Always;
6611 assert_eq!(
6612 spec.has_teardown_policy(kind),
6613 expected,
6614 "default ephemeral (teardown=Always) baseline: query {kind:?} must be {expected}",
6615 );
6616 }
6617 }
6618
6619 // ── derived-bool-predicate presence probe on EphemeralSpec ×
6620 // TeardownPolicy × ProcessPhase ──
6621 //
6622 // Fail-before-pass-after granularity:
6623 // [`EphemeralSpec::has_teardown_firing_on`] did not exist before
6624 // this commit — the ephemeral sugar surface's require-tag algebra
6625 // discriminated the teardown axis only by the RAW authored variant
6626 // (via `teardown-policy-<kind>`), never by the derived
6627 // [`ProcessPhase`] transition the stored policy fires on
6628 // ([`TeardownPolicy::should_teardown_on`]). Post-lift the shape
6629 // lives at ONE inherent method that byte-for-byte parallels
6630 // [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
6631 // on the point-surface carrier, and both surfaces' require-tag
6632 // classifiers publish a symmetric `teardown-fires-on-<phase>`
6633 // family through the SAME predicate.
6634
6635 /// TRUTH-TABLE DIAGONAL — for every [`TeardownPolicy`] variant,
6636 /// an [`EphemeralSpec`] whose `teardown` slot is set to that
6637 /// variant returns `has_teardown_firing_on(phase)` in agreement
6638 /// with [`TeardownPolicy::should_teardown_on`] for every
6639 /// [`ProcessPhase`] variant. Sweep [`TeardownPolicy::ALL`] ×
6640 /// [`ProcessPhase::ALL`] full cross so a regression that hard-
6641 /// coded the arm to a single policy, wired to the wrong field, or
6642 /// inverted the predicate direction fails HERE at the substrate
6643 /// primitive on the sugar surface (byte-for-byte peer of
6644 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase`]
6645 /// on the point carrier).
6646 #[test]
6647 fn has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase_on_ephemeral() {
6648 for populated in TeardownPolicy::ALL {
6649 let spec = EphemeralSpec {
6650 teardown: populated,
6651 ..empty_ephemeral()
6652 };
6653 for phase in ProcessPhase::ALL {
6654 assert_eq!(
6655 spec.has_teardown_firing_on(phase),
6656 populated.should_teardown_on(phase),
6657 "teardown={populated:?}, phase={phase:?}: predicate drift from \
6658 should_teardown_on projection",
6659 );
6660 }
6661 }
6662 }
6663
6664 /// TWO-SURFACE PARITY PIN — for every [`TeardownPolicy`] variant
6665 /// and every [`ProcessPhase`] variant, the sugar-surface probe
6666 /// and the lowered point-surface probe agree. The `EphemeralSpec
6667 /// → ProcessSpec` lowering routes the stored `teardown` slot
6668 /// through the SAME [`TeardownPolicy::should_teardown_on`]
6669 /// projection on both sides, so the sugar caller and the lowered
6670 /// caller can never disagree — a regression that (a) drifted
6671 /// [`Self::teardown`] between sugar and lowered, (b) rewired
6672 /// either probe body to bypass the shared substrate primitive, or
6673 /// (c) skewed the (policy, phase) truth table between the two
6674 /// surfaces fails HERE at the two-surface boundary rather than at
6675 /// the operator-facing require-tag classifier.
6676 #[test]
6677 fn has_teardown_firing_on_matches_point_peer_through_lowered_teardown_policy() {
6678 for populated in TeardownPolicy::ALL {
6679 let sugar = EphemeralSpec {
6680 teardown: populated,
6681 ..empty_ephemeral()
6682 };
6683 let lowered: ProcessSpec = sugar.clone().into();
6684 let lowered_eph = lowered
6685 .lifetime
6686 .resolved_ephemeral()
6687 .expect("lowered spec must be ephemeral");
6688 for phase in ProcessPhase::ALL {
6689 assert_eq!(
6690 sugar.has_teardown_firing_on(phase),
6691 lowered_eph.has_teardown_firing_on(phase),
6692 "sugar-vs-lowered predicate drift for teardown={populated:?}, phase={phase:?}",
6693 );
6694 }
6695 }
6696 }
6697
6698 // ── EphemeralSpec::resolved_classification + has_point_type pins ─────
6699 //
6700 // Fail-before-pass-after granularity: `resolved_classification` and
6701 // `has_point_type` did not exist pre-lift on `impl EphemeralSpec` — every
6702 // caller wanting the resolved [`Classification`] on the ephemeral
6703 // sugar-surface (currently zero; future ephemeral-surface classification-
6704 // axis require-tag families in `tatara-reconciler::bin::tatara-check`,
6705 // typed audit hooks, documentation generators listing the ephemeral
6706 // surface's known require-tag vocabulary) restated the two-line
6707 // `self.classification.as_ref().unwrap_or(&default_ephemeral_class())`
6708 // resolver body at their site. Post-lift both callers of the resolver
6709 // (`Self::has_point_type` and every future classification-axis peer)
6710 // route through ONE inherent method that shares the fill-through with
6711 // the sibling `From<EphemeralSpec> for ProcessSpec` lowering
6712 // byte-for-byte. A regression that (a) inverted the arm (`Some` filled
6713 // through the default), (b) drifted the default from the sibling
6714 // primitive `Classification::gate_compute()`, or (c) shifted the
6715 // `Cow<'_, Classification>` return shape (a stray `.clone()` on the
6716 // populated arm) fails HERE at the substrate primitive rather than as
6717 // silent operator-facing drift at a future
6718 // `point-type-<kind>` ephemeral require-tag surface.
6719
6720 /// AUTHORED-slot pin — an [`EphemeralSpec`] whose
6721 /// [`EphemeralSpec::classification`] slot names a concrete
6722 /// [`Classification`] returns [`Cow::Borrowed`] pointing at that
6723 /// authored value from [`Self::resolved_classification`]. Pins the
6724 /// populated-arm zero-allocation contract: a caller reading past
6725 /// the resolver sees the SAME byte address the operator authored,
6726 /// so the resolver does not silently clone the authored slot on
6727 /// the populated arm.
6728 #[test]
6729 fn resolved_classification_borrows_authored_slot() {
6730 let mut spec = empty_ephemeral();
6731 let mut authored = Classification::gate_compute();
6732 authored.point_type = ConvergencePointType::Fork;
6733 spec.classification = Some(authored.clone());
6734 let resolved = spec.resolved_classification();
6735 assert!(matches!(resolved, Cow::Borrowed(_)));
6736 assert_eq!(&*resolved, &authored);
6737 }
6738
6739 /// ABSENT-slot pin — an [`EphemeralSpec`] whose
6740 /// [`EphemeralSpec::classification`] slot is `None` returns
6741 /// [`Cow::Owned`] with the SAME value the sibling
6742 /// [`default_ephemeral_class`] baseline produces. Pins the
6743 /// two-surface parity contract with `From<EphemeralSpec> for
6744 /// ProcessSpec`: both sites fill through the SAME baseline on
6745 /// `None`, so the ephemeral require-tag surface's future
6746 /// `point-type-<kind>` family reads identically on the authored
6747 /// spec and on the mechanically lowered `ProcessSpec`.
6748 #[test]
6749 fn resolved_classification_fills_default_on_absent_slot() {
6750 let spec = empty_ephemeral();
6751 assert!(spec.classification.is_none());
6752 let resolved = spec.resolved_classification();
6753 assert!(matches!(resolved, Cow::Owned(_)));
6754 assert_eq!(&*resolved, &default_ephemeral_class());
6755 }
6756
6757 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
6758 /// [`EphemeralSpec::classification`] slot names a concrete
6759 /// [`Classification`] returns `true` from
6760 /// [`Self::has_point_type`] on the authored
6761 /// [`ConvergencePointType`] slot and `false` for every other
6762 /// variant. Sweep the [`ConvergencePointType::ALL`] × ALL cross so
6763 /// a regression that hard-coded the arm to a single kind or wired
6764 /// the closure to a fixed unrelated slot fails HERE at the
6765 /// substrate primitive. Byte-for-byte peer of
6766 /// [`crate::classification::tests`]'s point-surface
6767 /// [`Classification::has_point_type`] populated-slot sweep on the
6768 /// SAME closed-set primitive.
6769 #[test]
6770 fn has_point_type_returns_true_iff_authored_classification_matches_per_kind() {
6771 for populated in ConvergencePointType::ALL {
6772 let mut classification = Classification::gate_compute();
6773 classification.point_type = populated;
6774 let mut spec = empty_ephemeral();
6775 spec.classification = Some(classification);
6776 for query in ConvergencePointType::ALL {
6777 let expected = query == populated;
6778 assert_eq!(
6779 spec.has_point_type(query),
6780 expected,
6781 "ephemeral classification.point_type={populated:?}: query {query:?} drifted",
6782 );
6783 }
6784 }
6785 }
6786
6787 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
6788 /// [`EphemeralSpec::classification`] slot is `None` returns
6789 /// `true` from [`Self::has_point_type`] on
6790 /// [`ConvergencePointType::Gate`] (the `default_ephemeral_class`
6791 /// baseline's `point_type`) and `false` on every other variant.
6792 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
6793 /// default-arm short-circuit: on the ephemeral sugar surface the
6794 /// parent Option is filled through the workspace baseline rather
6795 /// than reading `false` on every variant like the encapsulation-
6796 /// mode / encapsulation-target / routing-form Option-parent
6797 /// corners.
6798 #[test]
6799 fn has_point_type_probes_gate_only_on_absent_classification() {
6800 let spec = empty_ephemeral();
6801 assert!(spec.classification.is_none());
6802 for kind in ConvergencePointType::ALL {
6803 let expected = kind == ConvergencePointType::Gate;
6804 assert_eq!(
6805 spec.has_point_type(kind),
6806 expected,
6807 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
6808 );
6809 }
6810 }
6811
6812 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
6813 /// identically through [`Self::has_point_type`] AND through
6814 /// `<eph.clone().into::<ProcessSpec>>()`
6815 /// `.classification.has_point_type(kind)` on the mechanically-
6816 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
6817 /// classification on every [`ConvergencePointType::ALL`] variant)
6818 /// × ALL queries so a future regression on either side of the
6819 /// resolver (a shift in the ephemeral resolver's default, a
6820 /// shift in the `From<EphemeralSpec>` lowering's fill-through)
6821 /// fails HERE at the parity boundary.
6822 #[test]
6823 fn has_point_type_matches_point_peer_through_lowered_classification() {
6824 // Absent classification: both surfaces resolve through the SAME
6825 // default and agree on every variant.
6826 let eph = empty_ephemeral();
6827 let lowered: ProcessSpec = eph.clone().into();
6828 for query in ConvergencePointType::ALL {
6829 assert_eq!(
6830 eph.has_point_type(query),
6831 lowered.classification.has_point_type(query),
6832 "None-classification parity drift on query {query:?}",
6833 );
6834 }
6835 // Authored classification: both surfaces read the same authored
6836 // value verbatim.
6837 for populated in ConvergencePointType::ALL {
6838 let mut classification = Classification::gate_compute();
6839 classification.point_type = populated;
6840 let mut eph = empty_ephemeral();
6841 eph.classification = Some(classification);
6842 let lowered: ProcessSpec = eph.clone().into();
6843 for query in ConvergencePointType::ALL {
6844 assert_eq!(
6845 eph.has_point_type(query),
6846 lowered.classification.has_point_type(query),
6847 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
6848 );
6849 }
6850 }
6851 }
6852
6853 // ── EphemeralSpec::has_substrate pins ────────────────────────────
6854 //
6855 // Fail-before-pass-after granularity: [`Self::has_substrate`] did
6856 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
6857 // through `.resolved_classification().substrate == kind` or through
6858 // the lowered `ProcessSpec`'s `spec.classification.has_substrate`.
6859 // Post-lift the SECOND classification-axis peer on the ephemeral
6860 // sugar surface routes through the SAME
6861 // [`Self::resolved_classification`] resolver + the sibling closed-
6862 // set primitive [`Classification::has_substrate`], so a regression
6863 // that dropped the resolver hop, inverted the `Some`/`None`
6864 // fill-through, or wired the closure to a fixed unrelated slot
6865 // fails HERE.
6866
6867 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
6868 /// [`EphemeralSpec::classification`] slot names a concrete
6869 /// [`Classification`] returns `true` from
6870 /// [`Self::has_substrate`] on the authored [`SubstrateType`] slot
6871 /// and `false` for every other variant. Sweep the
6872 /// [`SubstrateType::ALL`] × ALL cross so a regression that
6873 /// hard-coded the arm to a single kind or wired the closure to a
6874 /// fixed unrelated slot fails HERE at the substrate primitive.
6875 /// Byte-for-byte peer of the point-surface
6876 /// [`Classification::has_substrate`] populated-slot sweep on the
6877 /// SAME closed-set primitive.
6878 #[test]
6879 fn has_substrate_returns_true_iff_authored_classification_matches_per_kind() {
6880 for populated in SubstrateType::ALL {
6881 let mut classification = Classification::gate_compute();
6882 classification.substrate = populated;
6883 let mut spec = empty_ephemeral();
6884 spec.classification = Some(classification);
6885 for query in SubstrateType::ALL {
6886 let expected = query == populated;
6887 assert_eq!(
6888 spec.has_substrate(query),
6889 expected,
6890 "ephemeral classification.substrate={populated:?}: query {query:?} drifted",
6891 );
6892 }
6893 }
6894 }
6895
6896 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
6897 /// [`EphemeralSpec::classification`] slot is `None` returns
6898 /// `true` from [`Self::has_substrate`] on
6899 /// [`SubstrateType::Compute`] (the `default_ephemeral_class`
6900 /// baseline's `substrate`) and `false` on every other variant.
6901 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
6902 /// default-arm short-circuit on the SECOND classification-axis
6903 /// peer: on the ephemeral sugar surface the parent Option is
6904 /// filled through the workspace baseline rather than reading
6905 /// `false` on every variant like the Option-parent encapsulates /
6906 /// routing corners.
6907 #[test]
6908 fn has_substrate_probes_compute_only_on_absent_classification() {
6909 let spec = empty_ephemeral();
6910 assert!(spec.classification.is_none());
6911 for kind in SubstrateType::ALL {
6912 let expected = kind == SubstrateType::Compute;
6913 assert_eq!(
6914 spec.has_substrate(kind),
6915 expected,
6916 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
6917 );
6918 }
6919 }
6920
6921 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
6922 /// identically through [`Self::has_substrate`] AND through
6923 /// `<eph.clone().into::<ProcessSpec>>()`
6924 /// `.classification.has_substrate(kind)` on the mechanically-
6925 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
6926 /// classification on every [`SubstrateType::ALL`] variant) × ALL
6927 /// queries so a future regression on either side of the resolver
6928 /// (a shift in the ephemeral resolver's default, a shift in the
6929 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
6930 /// the parity boundary. Byte-for-byte peer of the sibling
6931 /// [`Self::has_point_type`] two-surface parity pin on the SAME
6932 /// `Cow`-resolver carrier — the SECOND classification-axis
6933 /// two-surface parity contract on the ephemeral surface.
6934 #[test]
6935 fn has_substrate_matches_point_peer_through_lowered_classification() {
6936 // Absent classification: both surfaces resolve through the SAME
6937 // default and agree on every variant.
6938 let eph = empty_ephemeral();
6939 let lowered: ProcessSpec = eph.clone().into();
6940 for query in SubstrateType::ALL {
6941 assert_eq!(
6942 eph.has_substrate(query),
6943 lowered.classification.has_substrate(query),
6944 "None-classification parity drift on query {query:?}",
6945 );
6946 }
6947 // Authored classification: both surfaces read the same authored
6948 // value verbatim.
6949 for populated in SubstrateType::ALL {
6950 let mut classification = Classification::gate_compute();
6951 classification.substrate = populated;
6952 let mut eph = empty_ephemeral();
6953 eph.classification = Some(classification);
6954 let lowered: ProcessSpec = eph.clone().into();
6955 for query in SubstrateType::ALL {
6956 assert_eq!(
6957 eph.has_substrate(query),
6958 lowered.classification.has_substrate(query),
6959 "authored classification.substrate={populated:?}: parity drift on query {query:?}",
6960 );
6961 }
6962 }
6963 }
6964
6965 // ── EphemeralSpec::has_calm pins ─────────────────────────────────
6966 //
6967 // Fail-before-pass-after granularity: [`Self::has_calm`] did not
6968 // exist pre-lift on `impl EphemeralSpec` — every callsite went
6969 // through `.resolved_classification().calm == kind` or through the
6970 // lowered `ProcessSpec`'s `spec.classification.has_calm`. Post-
6971 // lift the THIRD classification-axis peer on the ephemeral sugar
6972 // surface routes through the SAME
6973 // [`Self::resolved_classification`] resolver + the sibling closed-
6974 // set primitive [`Classification::has_calm`], so a regression that
6975 // dropped the resolver hop, inverted the `Some`/`None` fill-
6976 // through, or wired the closure to a fixed unrelated slot fails
6977 // HERE. Distinct from the FIRST + SECOND peers on the (Option-
6978 // parent × NON-DEFAULT-scalar-child) corner: the (Option-parent ×
6979 // DEFAULTED-scalar-child) corner this peer opens has BOTH the
6980 // parent fill-through baseline (`default_ephemeral_class`) AND the
6981 // child's own `#[default]` land on the SAME variant
6982 // ([`CalmClassification::Monotone`]), a two-defaults composition
6983 // property the three pins below all exercise.
6984
6985 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
6986 /// [`EphemeralSpec::classification`] slot names a concrete
6987 /// [`Classification`] returns `true` from [`Self::has_calm`] on
6988 /// the authored [`CalmClassification`] slot and `false` for every
6989 /// other variant. Sweep the [`CalmClassification::ALL`] × ALL
6990 /// cross so a regression that hard-coded the arm to a single
6991 /// kind or wired the closure to a fixed unrelated slot fails HERE
6992 /// at the substrate primitive. Byte-for-byte peer of the point-
6993 /// surface [`Classification::has_calm`] populated-slot sweep on
6994 /// the SAME closed-set primitive.
6995 #[test]
6996 fn has_calm_returns_true_iff_authored_classification_matches_per_kind() {
6997 for populated in CalmClassification::ALL {
6998 let mut classification = Classification::gate_compute();
6999 classification.calm = populated;
7000 let mut spec = empty_ephemeral();
7001 spec.classification = Some(classification);
7002 for query in CalmClassification::ALL {
7003 let expected = query == populated;
7004 assert_eq!(
7005 spec.has_calm(query),
7006 expected,
7007 "ephemeral classification.calm={populated:?}: query {query:?} drifted",
7008 );
7009 }
7010 }
7011 }
7012
7013 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7014 /// [`EphemeralSpec::classification`] slot is `None` returns
7015 /// `true` from [`Self::has_calm`] on
7016 /// [`CalmClassification::Monotone`] (the `default_ephemeral_class`
7017 /// baseline's `calm` axis AND the [`CalmClassification`] child's
7018 /// own `#[default]` variant) and `false` on every other variant.
7019 /// Pins the (Option-parent × DEFAULTED-scalar-child ×
7020 /// operator-resolvable-baseline) corner's default-arm short-
7021 /// circuit on the THIRD classification-axis peer — distinct from
7022 /// the FIRST + SECOND peers on the (Option-parent × NON-DEFAULT-
7023 /// scalar-child) corner which default through a specific chosen
7024 /// baseline ([`ConvergencePointType::Gate`],
7025 /// [`SubstrateType::Compute`]) rather than through the child's
7026 /// own `#[default]`. Two-defaults composition property: both the
7027 /// parent fill-through and the child's `#[default]` land on the
7028 /// SAME variant, so the ephemeral sugar surface's `calm-Monotone`
7029 /// require-tag reads `true` on every operator-authored spec that
7030 /// omits both the `:classification` slot AND the `:calm` sub-slot,
7031 /// pinning the workspace's monotone-by-default posture.
7032 #[test]
7033 fn has_calm_probes_monotone_only_on_absent_classification() {
7034 let spec = empty_ephemeral();
7035 assert!(spec.classification.is_none());
7036 for kind in CalmClassification::ALL {
7037 let expected = kind == CalmClassification::Monotone;
7038 assert_eq!(
7039 spec.has_calm(kind),
7040 expected,
7041 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7042 );
7043 }
7044 }
7045
7046 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7047 /// identically through [`Self::has_calm`] AND through
7048 /// `<eph.clone().into::<ProcessSpec>>()`
7049 /// `.classification.has_calm(kind)` on the mechanically-
7050 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7051 /// classification on every [`CalmClassification::ALL`] variant) ×
7052 /// ALL queries so a future regression on either side of the
7053 /// resolver (a shift in the ephemeral resolver's default, a shift
7054 /// in the `From<EphemeralSpec>` lowering's fill-through) fails
7055 /// HERE at the parity boundary. Byte-for-byte peer of the sibling
7056 /// [`Self::has_point_type`] + [`Self::has_substrate`] two-surface
7057 /// parity pins on the SAME `Cow`-resolver carrier — the THIRD
7058 /// classification-axis two-surface parity contract on the
7059 /// ephemeral surface, and the FIRST on the (Option-parent ×
7060 /// DEFAULTED-scalar-child) corner.
7061 #[test]
7062 fn has_calm_matches_point_peer_through_lowered_classification() {
7063 // Absent classification: both surfaces resolve through the SAME
7064 // default and agree on every variant.
7065 let eph = empty_ephemeral();
7066 let lowered: ProcessSpec = eph.clone().into();
7067 for query in CalmClassification::ALL {
7068 assert_eq!(
7069 eph.has_calm(query),
7070 lowered.classification.has_calm(query),
7071 "None-classification parity drift on query {query:?}",
7072 );
7073 }
7074 // Authored classification: both surfaces read the same authored
7075 // value verbatim.
7076 for populated in CalmClassification::ALL {
7077 let mut classification = Classification::gate_compute();
7078 classification.calm = populated;
7079 let mut eph = empty_ephemeral();
7080 eph.classification = Some(classification);
7081 let lowered: ProcessSpec = eph.clone().into();
7082 for query in CalmClassification::ALL {
7083 assert_eq!(
7084 eph.has_calm(query),
7085 lowered.classification.has_calm(query),
7086 "authored classification.calm={populated:?}: parity drift on query {query:?}",
7087 );
7088 }
7089 }
7090 }
7091
7092 // ── EphemeralSpec::has_data_classification pins ──────────────────
7093 //
7094 // Fail-before-pass-after granularity: [`Self::has_data_classification`]
7095 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
7096 // went through `.resolved_classification().data_classification ==
7097 // kind` or through the lowered `ProcessSpec`'s
7098 // `spec.classification.has_data_classification`. Post-lift the
7099 // FOURTH classification-axis peer on the ephemeral sugar surface
7100 // routes through the SAME [`Self::resolved_classification`]
7101 // resolver + the sibling closed-set primitive
7102 // [`crate::classification::Classification::has_data_classification`],
7103 // so a regression that dropped the resolver hop, inverted the
7104 // `Some`/`None` fill-through, or wired the closure to a fixed
7105 // unrelated slot fails HERE. SECOND occupant on the (Option-parent
7106 // × DEFAULTED-scalar-child × operator-resolvable-baseline) corner
7107 // alongside [`Self::has_calm`]: both the parent fill-through
7108 // baseline (`default_ephemeral_class`) AND the child's own
7109 // `#[default]` land on the SAME variant
7110 // ([`DataClassification::Internal`]), a two-defaults composition
7111 // property the three pins below all exercise.
7112
7113 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7114 /// [`EphemeralSpec::classification`] slot names a concrete
7115 /// [`Classification`] returns `true` from
7116 /// [`Self::has_data_classification`] on the authored
7117 /// [`DataClassification`] slot and `false` for every other
7118 /// variant. Sweep the [`DataClassification::ALL`] × ALL cross so
7119 /// a regression that hard-coded the arm to a single kind or
7120 /// wired the closure to a fixed unrelated slot fails HERE at the
7121 /// substrate primitive. Byte-for-byte peer of the point-surface
7122 /// [`Classification::has_data_classification`] populated-slot
7123 /// sweep on the SAME closed-set primitive.
7124 #[test]
7125 fn has_data_classification_returns_true_iff_authored_classification_matches_per_kind() {
7126 for populated in DataClassification::ALL {
7127 let mut classification = Classification::gate_compute();
7128 classification.data_classification = populated;
7129 let mut spec = empty_ephemeral();
7130 spec.classification = Some(classification);
7131 for query in DataClassification::ALL {
7132 let expected = query == populated;
7133 assert_eq!(
7134 spec.has_data_classification(query),
7135 expected,
7136 "ephemeral classification.data_classification={populated:?}: query {query:?} drifted",
7137 );
7138 }
7139 }
7140 }
7141
7142 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7143 /// [`EphemeralSpec::classification`] slot is `None` returns
7144 /// `true` from [`Self::has_data_classification`] on
7145 /// [`DataClassification::Internal`] (the `default_ephemeral_class`
7146 /// baseline's `data_classification` axis AND the
7147 /// [`DataClassification`] child's own `#[default]` variant) and
7148 /// `false` on every other variant. Pins the (Option-parent ×
7149 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner's
7150 /// default-arm short-circuit on the FOURTH classification-axis
7151 /// peer — SECOND occupant on that corner after [`Self::has_calm`]
7152 /// opened it. Two-defaults composition property: both the parent
7153 /// fill-through and the child's `#[default]` land on the SAME
7154 /// variant, so the ephemeral sugar surface's
7155 /// `data-classification-Internal` require-tag reads `true` on
7156 /// every operator-authored spec that omits both the
7157 /// `:classification` slot AND the `:data-classification` sub-slot,
7158 /// pinning the workspace's internal-by-default sensitivity posture.
7159 #[test]
7160 fn has_data_classification_probes_internal_only_on_absent_classification() {
7161 let spec = empty_ephemeral();
7162 assert!(spec.classification.is_none());
7163 for kind in DataClassification::ALL {
7164 let expected = kind == DataClassification::Internal;
7165 assert_eq!(
7166 spec.has_data_classification(kind),
7167 expected,
7168 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7169 );
7170 }
7171 }
7172
7173 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7174 /// identically through [`Self::has_data_classification`] AND
7175 /// through `<eph.clone().into::<ProcessSpec>>()`
7176 /// `.classification.has_data_classification(kind)` on the
7177 /// mechanically-lowered `ProcessSpec`. Sweeps (`None`
7178 /// classification, `Some(_)` classification on every
7179 /// [`DataClassification::ALL`] variant) × ALL queries so a
7180 /// future regression on either side of the resolver (a shift in
7181 /// the ephemeral resolver's default, a shift in the
7182 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7183 /// the parity boundary. Byte-for-byte peer of the sibling
7184 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
7185 /// [`Self::has_calm`] two-surface parity pins on the SAME
7186 /// `Cow`-resolver carrier — the FOURTH classification-axis
7187 /// two-surface parity contract on the ephemeral surface, and the
7188 /// SECOND on the (Option-parent × DEFAULTED-scalar-child) corner.
7189 #[test]
7190 fn has_data_classification_matches_point_peer_through_lowered_classification() {
7191 // Absent classification: both surfaces resolve through the SAME
7192 // default and agree on every variant.
7193 let eph = empty_ephemeral();
7194 let lowered: ProcessSpec = eph.clone().into();
7195 for query in DataClassification::ALL {
7196 assert_eq!(
7197 eph.has_data_classification(query),
7198 lowered.classification.has_data_classification(query),
7199 "None-classification parity drift on query {query:?}",
7200 );
7201 }
7202 // Authored classification: both surfaces read the same authored
7203 // value verbatim.
7204 for populated in DataClassification::ALL {
7205 let mut classification = Classification::gate_compute();
7206 classification.data_classification = populated;
7207 let mut eph = empty_ephemeral();
7208 eph.classification = Some(classification);
7209 let lowered: ProcessSpec = eph.clone().into();
7210 for query in DataClassification::ALL {
7211 assert_eq!(
7212 eph.has_data_classification(query),
7213 lowered.classification.has_data_classification(query),
7214 "authored classification.data_classification={populated:?}: parity drift on query {query:?}",
7215 );
7216 }
7217 }
7218 }
7219
7220 // ── EphemeralSpec::has_horizon_kind pins ─────────────────────────
7221 //
7222 // Fail-before-pass-after granularity: [`Self::has_horizon_kind`]
7223 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
7224 // went through `.resolved_classification().horizon.kind == kind`
7225 // or through the lowered `ProcessSpec`'s
7226 // `spec.classification.has_horizon_kind`. Post-lift the FIFTH
7227 // classification-axis peer on the ephemeral sugar surface routes
7228 // through the SAME [`Self::resolved_classification`] resolver +
7229 // the sibling closed-set primitive
7230 // [`crate::classification::Classification::has_horizon_kind`], so
7231 // a regression that dropped the resolver hop, inverted the
7232 // `Some`/`None` fill-through, or wired the closure to a fixed
7233 // unrelated slot fails HERE. OPENS a fresh (Option-parent ×
7234 // NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
7235 // corner on the ephemeral surface — distinct from the four prior
7236 // scalar-carrier peers on the (Option-parent × NON-DEFAULT-scalar-
7237 // child) and (Option-parent × DEFAULTED-scalar-child) corners, all
7238 // of which reach a discriminator DIRECTLY off a scalar
7239 // [`Classification`] slot. Both the parent Option's fill-through
7240 // baseline (`default_ephemeral_class`, which fills
7241 // `horizon: Horizon::default()`) AND the child's own `#[default]`
7242 // land on the SAME variant ([`HorizonKind::Bounded`]) — a two-
7243 // defaults composition property the three pins below all
7244 // exercise.
7245
7246 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7247 /// [`EphemeralSpec::classification`] slot names a concrete
7248 /// [`Classification`] returns `true` from
7249 /// [`Self::has_horizon_kind`] on the authored [`HorizonKind`] slot
7250 /// and `false` for every other variant. Sweep the
7251 /// [`HorizonKind::ALL`] × ALL cross so a regression that hard-
7252 /// coded the arm to a single kind or wired the closure to a
7253 /// fixed unrelated slot (e.g. reading `self.classification` as if
7254 /// it were a scalar rather than routing through
7255 /// `resolved_classification().horizon.kind`) fails HERE at the
7256 /// substrate primitive. Byte-for-byte peer of the point-surface
7257 /// [`Classification::has_horizon_kind`] populated-slot sweep on
7258 /// the SAME closed-set primitive.
7259 #[test]
7260 fn has_horizon_kind_returns_true_iff_authored_classification_matches_per_kind() {
7261 for populated in HorizonKind::ALL {
7262 let classification = Classification::gate_compute_with_axis(populated);
7263 let mut spec = empty_ephemeral();
7264 spec.classification = Some(classification);
7265 for query in HorizonKind::ALL {
7266 let expected = query == populated;
7267 assert_eq!(
7268 spec.has_horizon_kind(query),
7269 expected,
7270 "ephemeral classification.horizon.kind={populated:?}: query {query:?} drifted",
7271 );
7272 }
7273 }
7274 }
7275
7276 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7277 /// [`EphemeralSpec::classification`] slot is `None` returns
7278 /// `true` from [`Self::has_horizon_kind`] on
7279 /// [`HorizonKind::Bounded`] (the `default_ephemeral_class`
7280 /// baseline's `horizon.kind` axis AND the [`HorizonKind`] child's
7281 /// own `#[default]` variant) and `false` on every other variant.
7282 /// Pins the fresh (Option-parent × NESTED-STRUCT-scalar-child ×
7283 /// operator-resolvable-baseline) corner's default-arm short-
7284 /// circuit on the FIFTH classification-axis peer. Two-defaults
7285 /// composition property through a NESTED-STRUCT hop: both the
7286 /// parent Option's fill-through baseline
7287 /// (`default_ephemeral_class` fills `horizon: Horizon::default()`)
7288 /// AND the child's own `#[default]` (`HorizonKind::Bounded` via
7289 /// `#[default]` on the closed set) land on the SAME variant, so
7290 /// the ephemeral sugar surface's `horizon-Bounded` require-tag
7291 /// reads `true` on every operator-authored spec that omits both
7292 /// the `:classification` slot AND the `:horizon` sub-slot,
7293 /// pinning the workspace's bounded-by-default lifetime posture.
7294 #[test]
7295 fn has_horizon_kind_probes_bounded_only_on_absent_classification() {
7296 let spec = empty_ephemeral();
7297 assert!(spec.classification.is_none());
7298 for kind in HorizonKind::ALL {
7299 let expected = kind == HorizonKind::Bounded;
7300 assert_eq!(
7301 spec.has_horizon_kind(kind),
7302 expected,
7303 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7304 );
7305 }
7306 }
7307
7308 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7309 /// identically through [`Self::has_horizon_kind`] AND through
7310 /// `<eph.clone().into::<ProcessSpec>>()`
7311 /// `.classification.has_horizon_kind(kind)` on the mechanically-
7312 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
7313 /// classification on every [`HorizonKind::ALL`] variant) × ALL
7314 /// queries so a future regression on either side of the resolver
7315 /// (a shift in the ephemeral resolver's default, a shift in the
7316 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
7317 /// the parity boundary. Byte-for-byte peer of the sibling
7318 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
7319 /// [`Self::has_calm`] + [`Self::has_data_classification`] two-
7320 /// surface parity pins on the SAME `Cow`-resolver carrier — the
7321 /// FIFTH classification-axis two-surface parity contract on the
7322 /// ephemeral surface, and the FIRST on the (Option-parent ×
7323 /// NESTED-STRUCT-scalar-child) corner.
7324 #[test]
7325 fn has_horizon_kind_matches_point_peer_through_lowered_classification() {
7326 // Absent classification: both surfaces resolve through the SAME
7327 // default and agree on every variant.
7328 let eph = empty_ephemeral();
7329 let lowered: ProcessSpec = eph.clone().into();
7330 for query in HorizonKind::ALL {
7331 assert_eq!(
7332 eph.has_horizon_kind(query),
7333 lowered.classification.has_horizon_kind(query),
7334 "None-classification parity drift on query {query:?}",
7335 );
7336 }
7337 // Authored classification: both surfaces read the same authored
7338 // value verbatim.
7339 for populated in HorizonKind::ALL {
7340 let classification = Classification::gate_compute_with_axis(populated);
7341 let mut eph = empty_ephemeral();
7342 eph.classification = Some(classification);
7343 let lowered: ProcessSpec = eph.clone().into();
7344 for query in HorizonKind::ALL {
7345 assert_eq!(
7346 eph.has_horizon_kind(query),
7347 lowered.classification.has_horizon_kind(query),
7348 "authored classification.horizon.kind={populated:?}: parity drift on query {query:?}",
7349 );
7350 }
7351 }
7352 }
7353
7354 // ── EphemeralSpec::has_optimization_direction pins ───────────────
7355 //
7356 // Fail-before-pass-after granularity:
7357 // [`Self::has_optimization_direction`] did not exist pre-lift on
7358 // `impl EphemeralSpec` — every callsite went through
7359 // `.resolved_classification().horizon.direction.unwrap_or_default() == kind`
7360 // or through the lowered `ProcessSpec`'s
7361 // `spec.classification.has_optimization_direction`. Post-lift the
7362 // SIXTH classification-axis peer on the ephemeral sugar surface
7363 // routes through the SAME [`Self::resolved_classification`]
7364 // resolver + the sibling closed-set primitive
7365 // [`crate::classification::Classification::has_optimization_direction`],
7366 // so a regression that dropped the resolver hop, inverted the
7367 // `Some`/`None` fill-through, wired the closure to a fixed
7368 // unrelated slot, or flipped [`OptimizationDirection`]'s
7369 // `#[default]` off `Minimize` fails HERE. SECOND occupant on the
7370 // (Option-parent × NESTED-STRUCT-scalar-child × operator-
7371 // resolvable-baseline) corner alongside
7372 // [`Self::has_horizon_kind`] — pinning the corner as a proven-
7373 // repeatable primitive shape on the ephemeral surface with a
7374 // second nested-struct-child probe, and DEMONSTRATING that the
7375 // corner admits both direct-scalar and Option-scalar traversals
7376 // through the SAME nested [`Horizon`] intermediary via the closed
7377 // set's `Default` on the inner `Option<OptimizationDirection>`
7378 // slot.
7379
7380 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
7381 /// [`EphemeralSpec::classification`] slot names a concrete
7382 /// [`Classification`] whose [`crate::classification::Horizon::direction`]
7383 /// slot carries `Some(<direction>)` returns `true` from
7384 /// [`Self::has_optimization_direction`] on the authored
7385 /// [`OptimizationDirection`] variant and `false` for every other
7386 /// variant. Sweep the [`OptimizationDirection::ALL`] × ALL cross
7387 /// so a regression that hard-coded the arm to a single kind, or
7388 /// dropped the `Option::unwrap_or_default` collapse, or wired the
7389 /// closure to a fixed unrelated slot (e.g. reading `self.horizon.kind`)
7390 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
7391 /// point-surface
7392 /// [`Classification::has_optimization_direction`] populated-slot
7393 /// sweep on the SAME closed-set primitive.
7394 #[test]
7395 fn has_optimization_direction_returns_true_iff_authored_direction_matches_per_kind() {
7396 for populated in OptimizationDirection::ALL {
7397 let classification = Classification::gate_compute_with_axis(populated);
7398 let mut spec = empty_ephemeral();
7399 spec.classification = Some(classification);
7400 for query in OptimizationDirection::ALL {
7401 let expected = query == populated;
7402 assert_eq!(
7403 spec.has_optimization_direction(query),
7404 expected,
7405 "ephemeral classification.horizon.direction=Some({populated:?}): query {query:?} drifted",
7406 );
7407 }
7408 }
7409 }
7410
7411 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
7412 /// [`EphemeralSpec::classification`] slot is `None` returns
7413 /// `true` from [`Self::has_optimization_direction`] on
7414 /// [`OptimizationDirection::Minimize`] (the `default_ephemeral_class`
7415 /// baseline fills `horizon: Horizon::default()`, which in turn
7416 /// leaves `direction: None`, and the substrate's
7417 /// `Option::unwrap_or_default` collapse then reads
7418 /// [`OptimizationDirection::Minimize`] via the closed set's
7419 /// `#[default]`) and `false` on every other variant. Pins the
7420 /// (Option-parent × NESTED-STRUCT-scalar-child × operator-
7421 /// resolvable-baseline) corner's default-arm short-circuit on the
7422 /// SIXTH classification-axis peer through TWO Option-hops: parent
7423 /// `EphemeralSpec::classification` and inner `Horizon::direction`
7424 /// both `None`, both collapsing to the closed set's `#[default]`
7425 /// [`OptimizationDirection::Minimize`]. A regression that promoted
7426 /// [`OptimizationDirection::Maximize`] to `#[default]` (silently
7427 /// inverting every unadorned Process's rate-window evaluator
7428 /// polarity), dropped `Option::unwrap_or_default`, or wired the arm
7429 /// to a fixed variant answer fails HERE.
7430 #[test]
7431 fn has_optimization_direction_probes_minimize_only_on_absent_classification() {
7432 let spec = empty_ephemeral();
7433 assert!(spec.classification.is_none());
7434 for kind in OptimizationDirection::ALL {
7435 let expected = kind == OptimizationDirection::Minimize;
7436 assert_eq!(
7437 spec.has_optimization_direction(kind),
7438 expected,
7439 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
7440 );
7441 }
7442 }
7443
7444 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7445 /// identically through [`Self::has_optimization_direction`] AND
7446 /// through
7447 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
7448 /// on the mechanically-lowered `ProcessSpec`. Sweeps three arms —
7449 /// (`None` classification), (`Some(_)` classification with
7450 /// `direction: None`), and (`Some(_)` classification on every
7451 /// [`OptimizationDirection::ALL`] variant) — × ALL queries so a
7452 /// future regression on either side of the resolver (an ephemeral-
7453 /// side fill-through drift, a lowering-side `From<EphemeralSpec>`
7454 /// `unwrap_or_else(default_ephemeral_class)` drift, an inner
7455 /// `Option::unwrap_or_default` collapse drift on either side)
7456 /// fails HERE at the parity boundary. Byte-for-byte peer of the
7457 /// sibling [`Self::has_point_type`] + [`Self::has_substrate`] +
7458 /// [`Self::has_calm`] + [`Self::has_data_classification`] +
7459 /// [`Self::has_horizon_kind`] two-surface parity pins on the SAME
7460 /// `Cow`-resolver carrier — the SIXTH classification-axis two-
7461 /// surface parity contract on the ephemeral surface, and the
7462 /// SECOND on the (Option-parent × NESTED-STRUCT-scalar-child)
7463 /// corner.
7464 #[test]
7465 fn has_optimization_direction_matches_point_peer_through_lowered_classification() {
7466 // Absent classification: both surfaces resolve through the SAME
7467 // default and agree on every variant.
7468 let eph = empty_ephemeral();
7469 let lowered: ProcessSpec = eph.clone().into();
7470 for query in OptimizationDirection::ALL {
7471 assert_eq!(
7472 eph.has_optimization_direction(query),
7473 lowered.classification.has_optimization_direction(query),
7474 "None-classification parity drift on query {query:?}",
7475 );
7476 }
7477 // Authored classification with `direction: None` — the inner
7478 // Option collapses through `unwrap_or_default` on both sides,
7479 // reading `Minimize`.
7480 let mut classification = Classification::gate_compute();
7481 classification.horizon = Horizon::default();
7482 let mut eph = empty_ephemeral();
7483 eph.classification = Some(classification);
7484 let lowered: ProcessSpec = eph.clone().into();
7485 for query in OptimizationDirection::ALL {
7486 assert_eq!(
7487 eph.has_optimization_direction(query),
7488 lowered.classification.has_optimization_direction(query),
7489 "authored classification with horizon.direction=None: parity drift on query {query:?}",
7490 );
7491 }
7492 // Authored classification with `direction: Some(_)` — both
7493 // surfaces read the same authored value verbatim.
7494 for populated in OptimizationDirection::ALL {
7495 let classification = Classification::gate_compute_with_axis(populated);
7496 let mut eph = empty_ephemeral();
7497 eph.classification = Some(classification);
7498 let lowered: ProcessSpec = eph.clone().into();
7499 for query in OptimizationDirection::ALL {
7500 assert_eq!(
7501 eph.has_optimization_direction(query),
7502 lowered.classification.has_optimization_direction(query),
7503 "authored classification.horizon.direction=Some({populated:?}): parity drift on query {query:?}",
7504 );
7505 }
7506 }
7507 }
7508
7509 // ── EphemeralSpec::has_input_arity pins ──────────────────────────
7510 //
7511 // Fail-before-pass-after granularity: [`Self::has_input_arity`] did
7512 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
7513 // through `.resolved_classification().point_type.input_arity() ==
7514 // kind` or through the lowered `ProcessSpec`'s
7515 // `spec.classification.has_input_arity`. Post-lift the SEVENTH
7516 // classification-axis peer on the ephemeral sugar surface routes
7517 // through the SAME [`Self::resolved_classification`] resolver + the
7518 // sibling closed-set primitive
7519 // [`crate::classification::Classification::has_input_arity`], so a
7520 // regression that dropped the resolver hop, dropped the
7521 // `.input_arity()` projection call, inverted the projection (`One
7522 // ↔ Many`), or crossed the wires with the sibling
7523 // [`ConvergencePointType::output_arity`] projection fails HERE.
7524 // OPENS the (Option-parent × NESTED-STRUCT-scalar-child ×
7525 // derived-typed-projection) corner on the ephemeral surface —
7526 // distinct from the two prior nested-scalar peers on the corner
7527 // (`has_horizon_kind` reads `horizon.kind` directly;
7528 // `has_optimization_direction` reads `horizon.direction` through an
7529 // Option collapse), both of which reach a discriminator DIRECTLY off
7530 // a scalar. This peer instead threads through a many-to-one closed-
7531 // set typed projection so the child's closed set is REACHED THROUGH
7532 // a projection layer, pinning the corner as admitting three
7533 // ephemeral-surface traversal shapes (direct-scalar, Option-scalar-
7534 // with-default, derived-typed-projection) through the SAME resolver
7535 // walk.
7536
7537 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
7538 /// [`EphemeralSpec::classification`] slot names a concrete
7539 /// [`Classification`] with an authored [`ConvergencePointType`]
7540 /// returns `true` from [`Self::has_input_arity`] on the [`Arity`]
7541 /// value the projection [`ConvergencePointType::input_arity`] maps
7542 /// the authored point-type to and `false` for every other variant.
7543 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
7544 /// a regression that (a) dropped the projection call, (b) inverted
7545 /// the projection, (c) probed [`ConvergencePointType`] directly, or
7546 /// (d) crossed wires with [`ConvergencePointType::output_arity`]
7547 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
7548 /// point-surface [`Classification::has_input_arity`] populated-slot
7549 /// sweep on the SAME closed-set primitive routed through the SAME
7550 /// projection.
7551 #[test]
7552 fn has_input_arity_returns_true_iff_authored_point_type_projects_per_kind() {
7553 for populated in ConvergencePointType::ALL {
7554 let mut classification = Classification::gate_compute();
7555 classification.point_type = populated;
7556 let mut spec = empty_ephemeral();
7557 spec.classification = Some(classification);
7558 let projected = populated.input_arity();
7559 for query in Arity::ALL {
7560 let expected = query == projected;
7561 assert_eq!(
7562 spec.has_input_arity(query),
7563 expected,
7564 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
7565 );
7566 }
7567 }
7568 }
7569
7570 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
7571 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
7572 /// from [`Self::has_input_arity`] on [`Arity::Many`] (the
7573 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
7574 /// and [`ConvergencePointType::input_arity`] projects
7575 /// `Gate → Arity::Many`) and `false` on [`Arity::One`]. Pins the
7576 /// (Option-parent × NESTED-STRUCT-scalar-child × derived-typed-
7577 /// projection) corner's baseline projection on the SEVENTH
7578 /// classification-axis peer through a chain of TWO fill-throughs
7579 /// composed with ONE projection: the parent Option's
7580 /// `unwrap_or_else(default_ephemeral_class)` picks the substrate
7581 /// baseline, and the projection then collapses the baseline's
7582 /// point-type through the closed-set-driven many-to-one bucket
7583 /// walk. [`Arity`] carries no `#[default]`, so there is NO default-
7584 /// arm short-circuit shortcut here — the answer flows entirely
7585 /// through the projection's bucket-membership decision. A
7586 /// regression that promoted the baseline's `point_type` off `Gate`
7587 /// (silently flipping every unadorned Process's convergent-by-
7588 /// default input-side posture to endomorphic or diffusive), dropped
7589 /// the projection call, inverted the projection, or crossed wires
7590 /// with [`ConvergencePointType::output_arity`] (which would flip
7591 /// the baseline answer from `Many` to `One` for `Gate`) fails HERE.
7592 #[test]
7593 fn has_input_arity_probes_many_only_on_absent_classification() {
7594 let spec = empty_ephemeral();
7595 assert!(spec.classification.is_none());
7596 for kind in Arity::ALL {
7597 let expected = kind == Arity::Many;
7598 assert_eq!(
7599 spec.has_input_arity(kind),
7600 expected,
7601 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many): query {kind:?} must be {expected}",
7602 );
7603 }
7604 }
7605
7606 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7607 /// identically through [`Self::has_input_arity`] AND through
7608 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
7609 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
7610 /// classification, `Some(_)` classification on every
7611 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
7612 /// so a future regression on either side of the resolver (a shift
7613 /// in the ephemeral resolver's default, a shift in the
7614 /// `From<EphemeralSpec>` lowering's fill-through, a projection
7615 /// drift on either side) fails HERE at the parity boundary. Byte-
7616 /// for-byte peer of the sibling [`Self::has_point_type`] +
7617 /// [`Self::has_substrate`] + [`Self::has_calm`] +
7618 /// [`Self::has_data_classification`] + [`Self::has_horizon_kind`] +
7619 /// [`Self::has_optimization_direction`] two-surface parity pins on
7620 /// the SAME `Cow`-resolver carrier — the SEVENTH classification-
7621 /// axis two-surface parity contract on the ephemeral surface, and
7622 /// the FIRST on the (Option-parent × NESTED-STRUCT-scalar-child ×
7623 /// derived-typed-projection) corner.
7624 #[test]
7625 fn has_input_arity_matches_point_peer_through_lowered_classification() {
7626 // Absent classification: both surfaces resolve through the SAME
7627 // default and agree on every variant.
7628 let eph = empty_ephemeral();
7629 let lowered: ProcessSpec = eph.clone().into();
7630 for query in Arity::ALL {
7631 assert_eq!(
7632 eph.has_input_arity(query),
7633 lowered.classification.has_input_arity(query),
7634 "None-classification parity drift on query {query:?}",
7635 );
7636 }
7637 // Authored classification: both surfaces read the same authored
7638 // point_type and route through the same projection.
7639 for populated in ConvergencePointType::ALL {
7640 let mut classification = Classification::gate_compute();
7641 classification.point_type = populated;
7642 let mut eph = empty_ephemeral();
7643 eph.classification = Some(classification);
7644 let lowered: ProcessSpec = eph.clone().into();
7645 for query in Arity::ALL {
7646 assert_eq!(
7647 eph.has_input_arity(query),
7648 lowered.classification.has_input_arity(query),
7649 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
7650 );
7651 }
7652 }
7653 }
7654
7655 // ── EphemeralSpec::has_output_arity pins ─────────────────────────
7656 //
7657 // Fail-before-pass-after granularity: [`Self::has_output_arity`] did
7658 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
7659 // through `.resolved_classification().point_type.output_arity() ==
7660 // kind` or through the lowered `ProcessSpec`'s
7661 // `spec.classification.has_output_arity`. Post-lift the EIGHTH
7662 // classification-axis peer on the ephemeral sugar surface routes
7663 // through the SAME [`Self::resolved_classification`] resolver + the
7664 // sibling closed-set primitive
7665 // [`crate::classification::Classification::has_output_arity`], so a
7666 // regression that dropped the resolver hop, dropped the
7667 // `.output_arity()` projection call, inverted the projection (`One
7668 // ↔ Many`), or crossed the wires with the sibling
7669 // [`ConvergencePointType::input_arity`] projection fails HERE.
7670 // CLOSES the (Option-parent × NESTED-STRUCT-scalar-child ×
7671 // derived-typed-projection) corner on the ephemeral surface as the
7672 // SECOND occupant — co-tenant with [`Self::has_input_arity`] on the
7673 // SAME `point_type` scalar carrier through the SAME [`Arity`] closed
7674 // set but through the sibling many-to-one projection, closing the
7675 // DAG-composition arity pair on the ephemeral side.
7676
7677 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
7678 /// [`EphemeralSpec::classification`] slot names a concrete
7679 /// [`Classification`] with an authored [`ConvergencePointType`]
7680 /// returns `true` from [`Self::has_output_arity`] on the [`Arity`]
7681 /// value the projection [`ConvergencePointType::output_arity`] maps
7682 /// the authored point-type to and `false` for every other variant.
7683 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
7684 /// a regression that (a) dropped the projection call, (b) inverted
7685 /// the projection, (c) probed [`ConvergencePointType`] directly, or
7686 /// (d) crossed wires with [`ConvergencePointType::input_arity`]
7687 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
7688 /// point-surface [`Classification::has_output_arity`] populated-slot
7689 /// sweep on the SAME closed-set primitive routed through the SAME
7690 /// projection.
7691 #[test]
7692 fn has_output_arity_returns_true_iff_authored_point_type_projects_per_kind() {
7693 for populated in ConvergencePointType::ALL {
7694 let mut classification = Classification::gate_compute();
7695 classification.point_type = populated;
7696 let mut spec = empty_ephemeral();
7697 spec.classification = Some(classification);
7698 let projected = populated.output_arity();
7699 for query in Arity::ALL {
7700 let expected = query == projected;
7701 assert_eq!(
7702 spec.has_output_arity(query),
7703 expected,
7704 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
7705 );
7706 }
7707 }
7708 }
7709
7710 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
7711 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
7712 /// from [`Self::has_output_arity`] on [`Arity::One`] (the
7713 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
7714 /// and [`ConvergencePointType::output_arity`] projects
7715 /// `Gate → Arity::One`) and `false` on [`Arity::Many`]. MIRROR of
7716 /// the [`Self::has_input_arity`] baseline (`Gate → input_arity =
7717 /// Many`) — the DAG-composition arity pair projects the same `Gate`
7718 /// baseline through the two projections to opposite [`Arity`] arms,
7719 /// so this pin locks the output-side half of that pair against a
7720 /// regression that (a) promoted the baseline's `point_type` off
7721 /// `Gate` (silently flipping every unadorned Process's convergent-
7722 /// by-default output-side posture to diffusive), (b) dropped the
7723 /// projection call, (c) inverted the projection, or (d) crossed
7724 /// wires with [`ConvergencePointType::input_arity`] (which would
7725 /// flip the baseline answer from `One` to `Many` for `Gate`).
7726 #[test]
7727 fn has_output_arity_probes_one_only_on_absent_classification() {
7728 let spec = empty_ephemeral();
7729 assert!(spec.classification.is_none());
7730 for kind in Arity::ALL {
7731 let expected = kind == Arity::One;
7732 assert_eq!(
7733 spec.has_output_arity(kind),
7734 expected,
7735 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One): query {kind:?} must be {expected}",
7736 );
7737 }
7738 }
7739
7740 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7741 /// identically through [`Self::has_output_arity`] AND through
7742 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
7743 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
7744 /// classification, `Some(_)` classification on every
7745 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
7746 /// so a future regression on either side of the resolver fails HERE
7747 /// at the parity boundary. Byte-for-byte peer of the seven sibling
7748 /// two-surface parity pins on the SAME `Cow`-resolver carrier — the
7749 /// EIGHTH classification-axis two-surface parity contract on the
7750 /// ephemeral surface, closing the SECOND occupant of the (Option-
7751 /// parent × NESTED-STRUCT-scalar-child × derived-typed-projection)
7752 /// corner.
7753 #[test]
7754 fn has_output_arity_matches_point_peer_through_lowered_classification() {
7755 // Absent classification: both surfaces resolve through the SAME
7756 // default and agree on every variant.
7757 let eph = empty_ephemeral();
7758 let lowered: ProcessSpec = eph.clone().into();
7759 for query in Arity::ALL {
7760 assert_eq!(
7761 eph.has_output_arity(query),
7762 lowered.classification.has_output_arity(query),
7763 "None-classification parity drift on query {query:?}",
7764 );
7765 }
7766 // Authored classification: both surfaces read the same authored
7767 // point_type and route through the same projection.
7768 for populated in ConvergencePointType::ALL {
7769 let mut classification = Classification::gate_compute();
7770 classification.point_type = populated;
7771 let mut eph = empty_ephemeral();
7772 eph.classification = Some(classification);
7773 let lowered: ProcessSpec = eph.clone().into();
7774 for query in Arity::ALL {
7775 assert_eq!(
7776 eph.has_output_arity(query),
7777 lowered.classification.has_output_arity(query),
7778 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
7779 );
7780 }
7781 }
7782 }
7783
7784 /// DAG-COMPOSITION ARITY-PAIR pin — the SEVENTH
7785 /// ([`Self::has_input_arity`]) and EIGHTH
7786 /// ([`Self::has_output_arity`]) classification-axis peers on the
7787 /// ephemeral surface walk the SAME `point_type` scalar carrier
7788 /// (routed through the SAME [`Self::resolved_classification`]
7789 /// resolver) through the SAME [`Arity`] closed set but through
7790 /// DIFFERENT typed projections
7791 /// ([`ConvergencePointType::input_arity`] vs.
7792 /// [`ConvergencePointType::output_arity`]). An [`EphemeralSpec`]
7793 /// with `classification.point_type = Fork` (the diffusive `(One,
7794 /// Many)` cell) MUST simultaneously answer `has_input_arity(One)`
7795 /// true AND `has_output_arity(Many)` true AND
7796 /// `has_input_arity(Many)` false AND `has_output_arity(One)` false.
7797 /// An [`EphemeralSpec`] with `point_type = Transform` (endomorphic
7798 /// `(One, One)`) MUST answer BOTH `has_input_arity(One)` and
7799 /// `has_output_arity(One)` true — the two projections AGREE in the
7800 /// endomorphic bucket. The absent-classification baseline (Gate,
7801 /// convergent `(Many, One)`) MUST answer
7802 /// `has_input_arity(Many)` true AND `has_output_arity(One)` true —
7803 /// the mirror of the Fork case. A regression that (a) collapsed
7804 /// `has_output_arity` onto `has_input_arity`, (b) swapped the
7805 /// projection direction, or (c) drifted the topology-bucket
7806 /// contract fails HERE at ONE narrow ephemeral-surface site,
7807 /// symmetric with the point-surface DAG-composition arity-pair pin.
7808 #[test]
7809 fn has_input_arity_and_has_output_arity_pin_dag_composition_pair() {
7810 // Diffusive cell: Fork carries (input, output) = (One, Many)
7811 let mut classification = Classification::gate_compute();
7812 classification.point_type = ConvergencePointType::Fork;
7813 let mut fork = empty_ephemeral();
7814 fork.classification = Some(classification);
7815 assert!(fork.has_input_arity(Arity::One));
7816 assert!(fork.has_output_arity(Arity::Many));
7817 assert!(!fork.has_input_arity(Arity::Many));
7818 assert!(!fork.has_output_arity(Arity::One));
7819
7820 // Endomorphic cell: Transform carries (input, output) = (One, One)
7821 let mut classification = Classification::gate_compute();
7822 classification.point_type = ConvergencePointType::Transform;
7823 let mut transform = empty_ephemeral();
7824 transform.classification = Some(classification);
7825 assert!(transform.has_input_arity(Arity::One));
7826 assert!(transform.has_output_arity(Arity::One));
7827 assert!(!transform.has_input_arity(Arity::Many));
7828 assert!(!transform.has_output_arity(Arity::Many));
7829
7830 // Convergent cell: absent classification defaults to Gate,
7831 // which carries (input, output) = (Many, One).
7832 let gate = empty_ephemeral();
7833 assert!(gate.classification.is_none());
7834 assert!(gate.has_input_arity(Arity::Many));
7835 assert!(gate.has_output_arity(Arity::One));
7836 assert!(!gate.has_input_arity(Arity::One));
7837 assert!(!gate.has_output_arity(Arity::Many));
7838 }
7839
7840 // ── EphemeralSpec::horizon_terminates pins ───────────────────────
7841 //
7842 // Fail-before-pass-after granularity: `horizon_terminates` did not
7843 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
7844 // the "does this ephemeral spec's horizon terminate?" question
7845 // went through `.resolved_classification().horizon.kind.terminates()`
7846 // or through the lowered `ProcessSpec`'s
7847 // `spec.classification.horizon.kind.terminates()`. Post-lift the
7848 // NINTH classification-axis peer on the ephemeral surface routes
7849 // through the SAME [`Self::resolved_classification`] resolver +
7850 // the sibling substrate primitive
7851 // [`crate::classification::Classification::horizon_terminates`],
7852 // so the two-surface parity contract holds by construction — a
7853 // regression on either side of the resolver fails at these pins
7854 // before landing at the operator-facing `terminating-horizon`
7855 // fixed tag in `tatara-check`.
7856
7857 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
7858 /// [`Classification`] carries a specific [`HorizonKind`] variant
7859 /// answers [`Self::horizon_terminates`] matching the closed
7860 /// set's own [`HorizonKind::terminates`] truth table. Sweep
7861 /// [`HorizonKind::ALL`] so a regression that (a) hard-coded the
7862 /// body to a fixed answer, (b) inverted the projection, or (c)
7863 /// crossed the wires with the antisymmetric partner
7864 /// [`HorizonKind::requires_metric_axes`] fails HERE at the
7865 /// substrate primitive before drifting through the
7866 /// `terminating-horizon` fixed tag or the peer point surface.
7867 #[test]
7868 fn horizon_terminates_returns_horizon_kind_projection_per_kind() {
7869 for populated in HorizonKind::ALL {
7870 let classification = Classification::gate_compute_with_axis(populated);
7871 let mut spec = empty_ephemeral();
7872 spec.classification = Some(classification);
7873 assert_eq!(
7874 spec.horizon_terminates(),
7875 populated.terminates(),
7876 "authored horizon.kind={populated:?}: horizon_terminates() drift",
7877 );
7878 }
7879 }
7880
7881 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
7882 /// with `classification: None` routes through the
7883 /// [`Self::resolved_classification`] resolver's substrate default
7884 /// [`Classification::gate_compute`], which uses
7885 /// [`crate::classification::Horizon::default`] whose `kind`
7886 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
7887 /// [`HorizonKind::Bounded::terminates`] projects `true`, so
7888 /// [`Self::horizon_terminates`] returns `true`. Pins the default-
7889 /// arm short-circuit through THREE layers of `Default`
7890 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
7891 /// [`HorizonKind::default`]) reaching this derived-nullary
7892 /// predicate — a regression that dropped the resolver hop
7893 /// (silently answering `false` on an absent classification, as
7894 /// if the operator's absence meant "no horizon at all") fails
7895 /// HERE at ONE narrow ephemeral-surface site.
7896 #[test]
7897 fn horizon_terminates_probes_true_on_absent_classification() {
7898 let spec = empty_ephemeral();
7899 assert!(spec.classification.is_none());
7900 assert!(
7901 spec.horizon_terminates(),
7902 "absent classification (defaults to gate_compute, horizon.kind=Bounded → terminates=true)",
7903 );
7904 }
7905
7906 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
7907 /// identically through [`Self::horizon_terminates`] AND through
7908 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_terminates()`
7909 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
7910 /// classification, `Some(_)` classification on every
7911 /// [`HorizonKind::ALL`] variant) so a future regression on
7912 /// either side of the resolver fails HERE at the parity
7913 /// boundary. Byte-for-byte peer of the eight sibling two-surface
7914 /// parity pins on the SAME `Cow`-resolver carrier — the NINTH
7915 /// classification-axis two-surface parity contract on the
7916 /// ephemeral surface, and the FIRST via a derived-nullary-
7917 /// boolean predicate rather than a variant-equality probe.
7918 #[test]
7919 fn horizon_terminates_matches_point_peer_through_lowered_classification() {
7920 // Absent classification: both surfaces resolve through the SAME
7921 // default and agree.
7922 let eph = empty_ephemeral();
7923 let lowered: ProcessSpec = eph.clone().into();
7924 assert_eq!(
7925 eph.horizon_terminates(),
7926 lowered.classification.horizon_terminates(),
7927 "None-classification parity drift",
7928 );
7929 // Authored classification: both surfaces read the same authored
7930 // horizon.kind and route through the same projection.
7931 for populated in HorizonKind::ALL {
7932 let classification = Classification::gate_compute_with_axis(populated);
7933 let mut eph = empty_ephemeral();
7934 eph.classification = Some(classification);
7935 let lowered: ProcessSpec = eph.clone().into();
7936 assert_eq!(
7937 eph.horizon_terminates(),
7938 lowered.classification.horizon_terminates(),
7939 "authored horizon.kind={populated:?}: parity drift",
7940 );
7941 }
7942 }
7943
7944 // ── EphemeralSpec::horizon_requires_metric_axes pins ─────────────
7945 //
7946 // Fail-before-pass-after granularity: `horizon_requires_metric_axes`
7947 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
7948 // walking the "does this ephemeral spec's horizon require metric
7949 // axes?" question went through
7950 // `.resolved_classification().horizon.kind.requires_metric_axes()`
7951 // or through the lowered `ProcessSpec`'s
7952 // `spec.classification.horizon.kind.requires_metric_axes()`. Post-
7953 // lift the antisymmetric peer of `horizon_terminates` routes
7954 // through the SAME [`Self::resolved_classification`] resolver +
7955 // the sibling substrate primitive
7956 // [`crate::classification::Classification::horizon_requires_metric_axes`],
7957 // so the two-surface parity contract holds by construction — a
7958 // regression on either side of the resolver fails at these pins
7959 // before landing at the operator-facing `metric-axes-required`
7960 // fixed tag in `tatara-check`.
7961
7962 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
7963 /// [`Classification`] carries a specific [`HorizonKind`] variant
7964 /// answers [`Self::horizon_requires_metric_axes`] matching the
7965 /// closed set's own [`HorizonKind::requires_metric_axes`] truth
7966 /// table. Sweep [`HorizonKind::ALL`] so a regression that (a)
7967 /// hard-coded the body to a fixed answer, (b) inverted the
7968 /// projection, or (c) crossed the wires with the antisymmetric
7969 /// partner [`HorizonKind::terminates`] fails HERE at the
7970 /// substrate primitive before drifting through the
7971 /// `metric-axes-required` fixed tag or the peer point surface.
7972 #[test]
7973 fn horizon_requires_metric_axes_returns_horizon_kind_projection_per_kind() {
7974 for populated in HorizonKind::ALL {
7975 let classification = Classification::gate_compute_with_axis(populated);
7976 let mut spec = empty_ephemeral();
7977 spec.classification = Some(classification);
7978 assert_eq!(
7979 spec.horizon_requires_metric_axes(),
7980 populated.requires_metric_axes(),
7981 "authored horizon.kind={populated:?}: horizon_requires_metric_axes() drift",
7982 );
7983 }
7984 }
7985
7986 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
7987 /// with `classification: None` routes through the
7988 /// [`Self::resolved_classification`] resolver's substrate default
7989 /// [`Classification::gate_compute`], which uses
7990 /// [`crate::classification::Horizon::default`] whose `kind`
7991 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
7992 /// [`HorizonKind::Bounded::requires_metric_axes`] projects
7993 /// `false`, so [`Self::horizon_requires_metric_axes`] returns
7994 /// `false`. Pins the default-arm short-circuit through THREE
7995 /// layers of `Default` ([`Classification::gate_compute`] →
7996 /// [`Horizon::default`] → [`HorizonKind::default`]) reaching this
7997 /// derived-nullary predicate — mirror image of
7998 /// `horizon_terminates_probes_true_on_absent_classification`.
7999 #[test]
8000 fn horizon_requires_metric_axes_probes_false_on_absent_classification() {
8001 let spec = empty_ephemeral();
8002 assert!(spec.classification.is_none());
8003 assert!(
8004 !spec.horizon_requires_metric_axes(),
8005 "absent classification (defaults to gate_compute, horizon.kind=Bounded → requires_metric_axes=false)",
8006 );
8007 }
8008
8009 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8010 /// identically through [`Self::horizon_requires_metric_axes`]
8011 /// AND through
8012 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_requires_metric_axes()`
8013 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8014 /// classification, `Some(_)` classification on every
8015 /// [`HorizonKind::ALL`] variant) so a future regression on
8016 /// either side of the resolver fails HERE at the parity
8017 /// boundary. Byte-for-byte peer of the sibling
8018 /// `horizon_terminates_matches_point_peer_through_lowered_classification`.
8019 #[test]
8020 fn horizon_requires_metric_axes_matches_point_peer_through_lowered_classification() {
8021 // Absent classification.
8022 let eph = empty_ephemeral();
8023 let lowered: ProcessSpec = eph.clone().into();
8024 assert_eq!(
8025 eph.horizon_requires_metric_axes(),
8026 lowered.classification.horizon_requires_metric_axes(),
8027 "None-classification parity drift",
8028 );
8029 // Authored classification.
8030 for populated in HorizonKind::ALL {
8031 let classification = Classification::gate_compute_with_axis(populated);
8032 let mut eph = empty_ephemeral();
8033 eph.classification = Some(classification);
8034 let lowered: ProcessSpec = eph.clone().into();
8035 assert_eq!(
8036 eph.horizon_requires_metric_axes(),
8037 lowered.classification.horizon_requires_metric_axes(),
8038 "authored horizon.kind={populated:?}: parity drift",
8039 );
8040 }
8041 }
8042
8043 // ── EphemeralSpec::calm_requires_coordination pins ───────────────
8044 //
8045 // Fail-before-pass-after granularity: `calm_requires_coordination`
8046 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
8047 // walking the "does this ephemeral spec require coordination?"
8048 // question went through
8049 // `.resolved_classification().calm.requires_coordination()` or
8050 // through the lowered `ProcessSpec`'s
8051 // `spec.classification.calm.requires_coordination()`. Post-lift the
8052 // THIRD derived-nullary-boolean peer on the ephemeral surface
8053 // (first on the calm axis, after the two horizon-axis peers)
8054 // routes through the SAME [`Self::resolved_classification`]
8055 // resolver + the sibling substrate primitive
8056 // [`crate::classification::Classification::calm_requires_coordination`],
8057 // so the two-surface parity contract holds by construction — a
8058 // regression on either side of the resolver fails at these pins
8059 // before landing at the operator-facing `coordination-required`
8060 // fixed tag in `tatara-check`.
8061
8062 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8063 /// [`Classification`] carries a specific [`CalmClassification`]
8064 /// variant answers [`Self::calm_requires_coordination`] matching
8065 /// the closed set's own
8066 /// [`CalmClassification::requires_coordination`] truth table.
8067 /// Sweep [`CalmClassification::ALL`] so a regression that (a)
8068 /// hard-coded the body to a fixed answer, (b) inverted the
8069 /// projection, or (c) crossed the wires with a sibling
8070 /// classification-axis probe fails HERE at the substrate primitive
8071 /// before drifting through the `coordination-required` fixed tag
8072 /// or the peer point surface.
8073 #[test]
8074 fn calm_requires_coordination_returns_calm_projection_per_kind() {
8075 for populated in CalmClassification::ALL {
8076 let mut classification = Classification::gate_compute();
8077 classification.calm = populated;
8078 let mut spec = empty_ephemeral();
8079 spec.classification = Some(classification);
8080 assert_eq!(
8081 spec.calm_requires_coordination(),
8082 populated.requires_coordination(),
8083 "authored calm={populated:?}: calm_requires_coordination() drift",
8084 );
8085 }
8086 }
8087
8088 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8089 /// with `classification: None` routes through the
8090 /// [`Self::resolved_classification`] resolver's substrate default
8091 /// [`Classification::gate_compute`], which carries
8092 /// [`CalmClassification::default = Monotone`], and
8093 /// [`CalmClassification::Monotone::requires_coordination`] projects
8094 /// `false`, so [`Self::calm_requires_coordination`] returns
8095 /// `false`. Pins the default-arm short-circuit through TWO layers
8096 /// of `Default` ([`Classification::gate_compute`] →
8097 /// [`CalmClassification::default`]) reaching this derived-nullary
8098 /// predicate — distinct from the sibling `horizon_*` absent-
8099 /// classification pins by ONE structural degree (those walk THREE
8100 /// layers of `Default` because horizon has a nested-struct wrapper;
8101 /// this walks TWO because `calm` is a direct scalar). A regression
8102 /// that dropped the resolver hop (silently answering `true` on an
8103 /// absent classification, as if the operator's absence meant
8104 /// "requires coordination") fails HERE at ONE narrow ephemeral-
8105 /// surface site.
8106 #[test]
8107 fn calm_requires_coordination_probes_false_on_absent_classification() {
8108 let spec = empty_ephemeral();
8109 assert!(spec.classification.is_none());
8110 assert!(
8111 !spec.calm_requires_coordination(),
8112 "absent classification (defaults to gate_compute, calm=Monotone → requires_coordination=false)",
8113 );
8114 }
8115
8116 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8117 /// identically through [`Self::calm_requires_coordination`] AND
8118 /// through
8119 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_requires_coordination()`
8120 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8121 /// classification, `Some(_)` classification on every
8122 /// [`CalmClassification::ALL`] variant) so a future regression on
8123 /// either side of the resolver fails HERE at the parity boundary.
8124 /// Byte-for-byte peer of the sibling
8125 /// `horizon_terminates_matches_point_peer_through_lowered_classification`
8126 /// on the calm axis.
8127 #[test]
8128 fn calm_requires_coordination_matches_point_peer_through_lowered_classification() {
8129 // Absent classification.
8130 let eph = empty_ephemeral();
8131 let lowered: ProcessSpec = eph.clone().into();
8132 assert_eq!(
8133 eph.calm_requires_coordination(),
8134 lowered.classification.calm_requires_coordination(),
8135 "None-classification parity drift",
8136 );
8137 // Authored classification.
8138 for populated in CalmClassification::ALL {
8139 let mut classification = Classification::gate_compute();
8140 classification.calm = populated;
8141 let mut eph = empty_ephemeral();
8142 eph.classification = Some(classification);
8143 let lowered: ProcessSpec = eph.clone().into();
8144 assert_eq!(
8145 eph.calm_requires_coordination(),
8146 lowered.classification.calm_requires_coordination(),
8147 "authored calm={populated:?}: parity drift",
8148 );
8149 }
8150 }
8151
8152 // ── EphemeralSpec::data_is_regulated pins ────────────────────────
8153 //
8154 // Fail-before-pass-after granularity: `data_is_regulated` did not
8155 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8156 // the "does this ephemeral spec carry regulated data?" question
8157 // went through
8158 // `.resolved_classification().data_classification.is_regulated()`
8159 // or through the lowered `ProcessSpec`'s
8160 // `spec.classification.data_classification.is_regulated()`. Post-
8161 // lift the FOURTH derived-nullary-boolean peer on the ephemeral
8162 // surface (first on the data axis, after two horizon-axis peers
8163 // and one calm-axis peer) routes through the SAME
8164 // [`Self::resolved_classification`] resolver + the sibling
8165 // substrate primitive
8166 // [`crate::classification::Classification::data_is_regulated`],
8167 // so the two-surface parity contract holds by construction — a
8168 // regression on either side of the resolver fails at these pins
8169 // before landing at the operator-facing `data-regulated` fixed
8170 // tag in `tatara-check`.
8171
8172 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8173 /// [`Classification`] carries a specific [`DataClassification`]
8174 /// variant answers [`Self::data_is_regulated`] matching the
8175 /// closed set's own [`DataClassification::is_regulated`] truth
8176 /// table. Sweep [`DataClassification::ALL`] so a regression that
8177 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8178 /// projection, or (c) crossed the wires with a sibling
8179 /// classification-axis probe fails HERE at the substrate
8180 /// primitive before drifting through the `data-regulated` fixed
8181 /// tag or the peer point surface.
8182 #[test]
8183 fn data_is_regulated_returns_data_classification_projection_per_kind() {
8184 for populated in DataClassification::ALL {
8185 let mut classification = Classification::gate_compute();
8186 classification.data_classification = populated;
8187 let mut spec = empty_ephemeral();
8188 spec.classification = Some(classification);
8189 assert_eq!(
8190 spec.data_is_regulated(),
8191 populated.is_regulated(),
8192 "authored data_classification={populated:?}: data_is_regulated() drift",
8193 );
8194 }
8195 }
8196
8197 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8198 /// with `classification: None` routes through the
8199 /// [`Self::resolved_classification`] resolver's substrate default
8200 /// [`Classification::gate_compute`], which carries
8201 /// [`DataClassification::default = Internal`], and
8202 /// [`DataClassification::Internal::is_regulated`] projects
8203 /// `false`, so [`Self::data_is_regulated`] returns `false`. Pins
8204 /// the default-arm short-circuit through TWO layers of `Default`
8205 /// ([`Classification::gate_compute`] →
8206 /// [`DataClassification::default`]) reaching this derived-nullary
8207 /// predicate — byte-for-byte structural peer of the sibling
8208 /// `calm_requires_coordination_probes_false_on_absent_classification`
8209 /// on the classification-data axis, distinct from the two
8210 /// `horizon_*` absent-classification pins by ONE structural
8211 /// degree (those walk THREE layers because horizon has a nested-
8212 /// struct wrapper; this walks TWO because `data_classification`
8213 /// is a direct scalar). A regression that dropped the resolver
8214 /// hop (silently answering `true` on an absent classification,
8215 /// as if the operator's absence meant "regulated data") fails
8216 /// HERE at ONE narrow ephemeral-surface site.
8217 #[test]
8218 fn data_is_regulated_probes_false_on_absent_classification() {
8219 let spec = empty_ephemeral();
8220 assert!(spec.classification.is_none());
8221 assert!(
8222 !spec.data_is_regulated(),
8223 "absent classification (defaults to gate_compute, data_classification=Internal → is_regulated=false)",
8224 );
8225 }
8226
8227 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8228 /// identically through [`Self::data_is_regulated`] AND through
8229 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_regulated()`
8230 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8231 /// classification, `Some(_)` classification on every
8232 /// [`DataClassification::ALL`] variant) so a future regression on
8233 /// either side of the resolver fails HERE at the parity boundary.
8234 /// Byte-for-byte peer of the sibling
8235 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
8236 /// on the data axis.
8237 #[test]
8238 fn data_is_regulated_matches_point_peer_through_lowered_classification() {
8239 // Absent classification.
8240 let eph = empty_ephemeral();
8241 let lowered: ProcessSpec = eph.clone().into();
8242 assert_eq!(
8243 eph.data_is_regulated(),
8244 lowered.classification.data_is_regulated(),
8245 "None-classification parity drift",
8246 );
8247 // Authored classification.
8248 for populated in DataClassification::ALL {
8249 let mut classification = Classification::gate_compute();
8250 classification.data_classification = populated;
8251 let mut eph = empty_ephemeral();
8252 eph.classification = Some(classification);
8253 let lowered: ProcessSpec = eph.clone().into();
8254 assert_eq!(
8255 eph.data_is_regulated(),
8256 lowered.classification.data_is_regulated(),
8257 "authored data_classification={populated:?}: parity drift",
8258 );
8259 }
8260 }
8261
8262 // ── EphemeralSpec::data_is_restricted pins ───────────────────────
8263 //
8264 // Fail-before-pass-after granularity: `data_is_restricted` did not
8265 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8266 // the "does this ephemeral spec require access controls?" question
8267 // went through
8268 // `.resolved_classification().data_classification.is_restricted()`
8269 // or through the lowered `ProcessSpec`'s
8270 // `spec.classification.data_classification.is_restricted()`. Post-
8271 // lift the FIFTH derived-nullary-boolean peer on the ephemeral
8272 // surface (second on the data axis, after
8273 // [`Self::data_is_regulated`] opened the axis) routes through the
8274 // SAME [`Self::resolved_classification`] resolver + the sibling
8275 // substrate primitive
8276 // [`crate::classification::Classification::data_is_restricted`],
8277 // so the two-surface parity contract holds by construction — a
8278 // regression on either side of the resolver fails at these pins
8279 // before landing at the operator-facing `data-restricted` fixed
8280 // tag in `tatara-check`. FIRST direct-scalar ephemeral-surface
8281 // peer whose absent-classification baseline projects to `true`
8282 // rather than `false`.
8283
8284 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8285 /// [`Classification`] carries a specific [`DataClassification`]
8286 /// variant answers [`Self::data_is_restricted`] matching the
8287 /// closed set's own [`DataClassification::is_restricted`] truth
8288 /// table. Sweep [`DataClassification::ALL`] so a regression that
8289 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8290 /// projection, or (c) crossed the wires with the sibling
8291 /// [`DataClassification::is_regulated`] projection fails HERE at
8292 /// the substrate primitive before drifting through the
8293 /// `data-restricted` fixed tag or the peer point surface.
8294 #[test]
8295 fn data_is_restricted_returns_data_classification_projection_per_kind() {
8296 for populated in DataClassification::ALL {
8297 let mut classification = Classification::gate_compute();
8298 classification.data_classification = populated;
8299 let mut spec = empty_ephemeral();
8300 spec.classification = Some(classification);
8301 assert_eq!(
8302 spec.data_is_restricted(),
8303 populated.is_restricted(),
8304 "authored data_classification={populated:?}: data_is_restricted() drift",
8305 );
8306 }
8307 }
8308
8309 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8310 /// with `classification: None` routes through the
8311 /// [`Self::resolved_classification`] resolver's substrate default
8312 /// [`Classification::gate_compute`], which carries
8313 /// [`DataClassification::default = Internal`], and
8314 /// [`DataClassification::Internal::is_restricted`] projects
8315 /// `true`, so [`Self::data_is_restricted`] returns `true`. Pins
8316 /// the default-arm short-circuit through TWO layers of `Default`
8317 /// ([`Classification::gate_compute`] →
8318 /// [`DataClassification::default`]) reaching this derived-nullary
8319 /// predicate. FIRST direct-scalar ephemeral-surface peer whose
8320 /// absent-classification baseline answers `true`, not `false`
8321 /// (the four earlier direct-scalar peers on this surface —
8322 /// `data_is_regulated`, `calm_requires_coordination`, plus the
8323 /// nested-struct `horizon_requires_metric_axes` — all project
8324 /// `false` on the same absent classification, and only the
8325 /// sibling nested-struct `horizon_terminates` projects `true`).
8326 /// A regression that dropped the resolver hop (silently answering
8327 /// `false` on an absent classification, as if the operator's
8328 /// absence meant "freely distributable"), or that inverted the
8329 /// projection while the closed-set primitive stayed intact,
8330 /// fails HERE at ONE narrow ephemeral-surface site.
8331 #[test]
8332 fn data_is_restricted_probes_true_on_absent_classification() {
8333 let spec = empty_ephemeral();
8334 assert!(spec.classification.is_none());
8335 assert!(
8336 spec.data_is_restricted(),
8337 "absent classification (defaults to gate_compute, data_classification=Internal → is_restricted=true)",
8338 );
8339 }
8340
8341 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8342 /// identically through [`Self::data_is_restricted`] AND through
8343 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_restricted()`
8344 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8345 /// classification, `Some(_)` classification on every
8346 /// [`DataClassification::ALL`] variant) so a future regression on
8347 /// either side of the resolver fails HERE at the parity boundary.
8348 /// Byte-for-byte peer of the sibling
8349 /// `data_is_regulated_matches_point_peer_through_lowered_classification`
8350 /// on the same classification-data axis, published a second time
8351 /// through the antisymmetric closed-set projection.
8352 #[test]
8353 fn data_is_restricted_matches_point_peer_through_lowered_classification() {
8354 // Absent classification.
8355 let eph = empty_ephemeral();
8356 let lowered: ProcessSpec = eph.clone().into();
8357 assert_eq!(
8358 eph.data_is_restricted(),
8359 lowered.classification.data_is_restricted(),
8360 "None-classification parity drift",
8361 );
8362 // Authored classification.
8363 for populated in DataClassification::ALL {
8364 let mut classification = Classification::gate_compute();
8365 classification.data_classification = populated;
8366 let mut eph = empty_ephemeral();
8367 eph.classification = Some(classification);
8368 let lowered: ProcessSpec = eph.clone().into();
8369 assert_eq!(
8370 eph.data_is_restricted(),
8371 lowered.classification.data_is_restricted(),
8372 "authored data_classification={populated:?}: parity drift",
8373 );
8374 }
8375 }
8376
8377 /// COMPOSED IMPLICATION pin — the ephemeral-surface counterpart of
8378 /// the closed-set-internal
8379 /// `data_classification_regulated_implies_restricted` and its
8380 /// parent-composed peer
8381 /// `classification_data_is_regulated_implies_data_is_restricted_over_all`:
8382 /// for every ([`EphemeralSpec`] with authored classification
8383 /// carrying every [`DataClassification`] variant, plus the
8384 /// absent-classification case), the resolver-hop probe pair
8385 /// satisfies `data_is_regulated() ⇒ data_is_restricted()`. Pins
8386 /// the implication contract at the ephemeral-surface site so a
8387 /// regression that (a) inverted the ephemeral
8388 /// [`Self::data_is_regulated`] resolver hop, (b) inverted the
8389 /// ephemeral [`Self::data_is_restricted`] resolver hop, or (c)
8390 /// crossed their wires while the underlying substrate primitives
8391 /// stayed intact fails HERE. FIRST ephemeral-surface corner-peer
8392 /// pair whose two projections carry a non-trivial closed-set-
8393 /// internal implication relationship.
8394 #[test]
8395 fn ephemeral_data_is_regulated_implies_data_is_restricted_over_all() {
8396 // Absent classification.
8397 let eph = empty_ephemeral();
8398 assert!(
8399 !eph.data_is_regulated() || eph.data_is_restricted(),
8400 "None-classification: data_is_regulated ⇒ data_is_restricted violated",
8401 );
8402 // Authored classification.
8403 for populated in DataClassification::ALL {
8404 let mut classification = Classification::gate_compute();
8405 classification.data_classification = populated;
8406 let mut eph = empty_ephemeral();
8407 eph.classification = Some(classification);
8408 assert!(
8409 !eph.data_is_regulated() || eph.data_is_restricted(),
8410 "authored data_classification={populated:?}: data_is_regulated ⇒ data_is_restricted violated",
8411 );
8412 }
8413 }
8414
8415 // ── EphemeralSpec::point_is_endomorphic pins ─────────────────────
8416 //
8417 // Fail-before-pass-after granularity: `point_is_endomorphic` did
8418 // not exist pre-lift on `impl EphemeralSpec` — every consumer
8419 // walking the "does this ephemeral spec's point-type project to
8420 // the 1→1 endomorphic bucket?" question went through
8421 // `.resolved_classification().point_type.is_endomorphic()` or the
8422 // lowered `ProcessSpec`'s
8423 // `spec.classification.point_type.is_endomorphic()`. Post-lift the
8424 // SIXTH derived-nullary-boolean peer on the ephemeral surface
8425 // (first on the `point_type` axis) routes through the SAME
8426 // [`Self::resolved_classification`] resolver + the sibling
8427 // substrate primitive
8428 // [`crate::classification::Classification::point_is_endomorphic`],
8429 // so the two-surface parity contract holds by construction — a
8430 // regression on either side of the resolver fails at these pins
8431 // before landing at the operator-facing `endomorphic-point` fixed
8432 // tag in `tatara-check`.
8433
8434 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8435 /// [`Classification`] carries a specific [`ConvergencePointType`]
8436 /// variant answers [`Self::point_is_endomorphic`] matching the
8437 /// closed set's own [`ConvergencePointType::is_endomorphic`] truth
8438 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
8439 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8440 /// projection, or (c) crossed the wires with the sibling
8441 /// [`ConvergencePointType::is_diffusive`] /
8442 /// [`ConvergencePointType::is_convergent`] projections fails
8443 /// HERE at the substrate primitive before drifting through the
8444 /// `endomorphic-point` fixed tag or the peer point surface.
8445 #[test]
8446 fn point_is_endomorphic_returns_point_type_projection_per_kind() {
8447 for populated in ConvergencePointType::ALL {
8448 let mut classification = Classification::gate_compute();
8449 classification.point_type = populated;
8450 let mut spec = empty_ephemeral();
8451 spec.classification = Some(classification);
8452 assert_eq!(
8453 spec.point_is_endomorphic(),
8454 populated.is_endomorphic(),
8455 "authored point_type={populated:?}: point_is_endomorphic() drift",
8456 );
8457 }
8458 }
8459
8460 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8461 /// with `classification: None` routes through the
8462 /// [`Self::resolved_classification`] resolver's substrate default
8463 /// [`Classification::gate_compute`], which carries
8464 /// [`ConvergencePointType::Gate`] (a convergent barrier, not an
8465 /// endomorphism), and
8466 /// [`ConvergencePointType::Gate::is_endomorphic`] projects `false`,
8467 /// so [`Self::point_is_endomorphic`] returns `false`. Pins the
8468 /// resolver's chosen-field baseline at ONE narrow site — a
8469 /// regression that dropped the resolver hop, or that promoted
8470 /// [`ConvergencePointType::Transform`] to the gate-compute
8471 /// baseline (silently retargeting every unadorned ephemeral
8472 /// spec's topology bucket), fails HERE at ONE narrow ephemeral-
8473 /// surface site. FIRST direct-scalar ephemeral-surface peer whose
8474 /// absent-classification baseline is a chosen-field answer on the
8475 /// resolver's [`Classification::gate_compute`] default rather
8476 /// than a substrate-`#[default]` short-circuit on the closed-set
8477 /// side ([`ConvergencePointType`] has no `impl Default`).
8478 #[test]
8479 fn point_is_endomorphic_probes_false_on_absent_classification() {
8480 let spec = empty_ephemeral();
8481 assert!(spec.classification.is_none());
8482 assert!(
8483 !spec.point_is_endomorphic(),
8484 "absent classification (defaults to gate_compute, point_type=Gate → is_endomorphic=false)",
8485 );
8486 }
8487
8488 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8489 /// identically through [`Self::point_is_endomorphic`] AND through
8490 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_endomorphic()`
8491 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8492 /// classification, `Some(_)` classification on every
8493 /// [`ConvergencePointType::ALL`] variant) so a future regression
8494 /// on either side of the resolver fails HERE at the parity
8495 /// boundary. Byte-for-byte peer of the sibling
8496 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
8497 /// on a DIFFERENT closed-set axis, published a first time through
8498 /// the `point_type` closed-set projection.
8499 #[test]
8500 fn point_is_endomorphic_matches_point_peer_through_lowered_classification() {
8501 // Absent classification.
8502 let eph = empty_ephemeral();
8503 let lowered: ProcessSpec = eph.clone().into();
8504 assert_eq!(
8505 eph.point_is_endomorphic(),
8506 lowered.classification.point_is_endomorphic(),
8507 "None-classification parity drift",
8508 );
8509 // Authored classification.
8510 for populated in ConvergencePointType::ALL {
8511 let mut classification = Classification::gate_compute();
8512 classification.point_type = populated;
8513 let mut eph = empty_ephemeral();
8514 eph.classification = Some(classification);
8515 let lowered: ProcessSpec = eph.clone().into();
8516 assert_eq!(
8517 eph.point_is_endomorphic(),
8518 lowered.classification.point_is_endomorphic(),
8519 "authored point_type={populated:?}: parity drift",
8520 );
8521 }
8522 }
8523
8524 // ── EphemeralSpec::point_is_diffusive pins ───────────────────────
8525 //
8526 // Fail-before-pass-after granularity: `point_is_diffusive` did not
8527 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
8528 // the "does this ephemeral spec's point-type project to the 1→N
8529 // diffusive fan-out bucket?" question went through
8530 // `.resolved_classification().point_type.is_diffusive()` or the
8531 // lowered `ProcessSpec`'s
8532 // `spec.classification.point_type.is_diffusive()`. Post-lift the
8533 // SEVENTH derived-nullary-boolean peer on the ephemeral surface
8534 // (SECOND on the `point_type` axis) routes through the SAME
8535 // [`Self::resolved_classification`] resolver + the sibling
8536 // substrate primitive
8537 // [`crate::classification::Classification::point_is_diffusive`],
8538 // so the two-surface parity contract holds by construction.
8539
8540 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8541 /// [`Classification`] carries a specific [`ConvergencePointType`]
8542 /// variant answers [`Self::point_is_diffusive`] matching the
8543 /// closed set's own [`ConvergencePointType::is_diffusive`] truth
8544 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
8545 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8546 /// projection, or (c) crossed the wires with the sibling
8547 /// [`ConvergencePointType::is_endomorphic`] /
8548 /// [`ConvergencePointType::is_convergent`] projections fails HERE
8549 /// at the substrate primitive before drifting through the
8550 /// `diffusive-point` fixed tag or the peer point surface.
8551 #[test]
8552 fn point_is_diffusive_returns_point_type_projection_per_kind() {
8553 for populated in ConvergencePointType::ALL {
8554 let mut classification = Classification::gate_compute();
8555 classification.point_type = populated;
8556 let mut spec = empty_ephemeral();
8557 spec.classification = Some(classification);
8558 assert_eq!(
8559 spec.point_is_diffusive(),
8560 populated.is_diffusive(),
8561 "authored point_type={populated:?}: point_is_diffusive() drift",
8562 );
8563 }
8564 }
8565
8566 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8567 /// with `classification: None` routes through the
8568 /// [`Self::resolved_classification`] resolver's substrate default
8569 /// [`Classification::gate_compute`], which carries
8570 /// [`ConvergencePointType::Gate`] (a convergent barrier, not a
8571 /// diffusive fan-out), and
8572 /// [`ConvergencePointType::Gate::is_diffusive`] projects `false`,
8573 /// so [`Self::point_is_diffusive`] returns `false`. Pins the
8574 /// resolver's chosen-field baseline at ONE narrow site.
8575 #[test]
8576 fn point_is_diffusive_probes_false_on_absent_classification() {
8577 let spec = empty_ephemeral();
8578 assert!(spec.classification.is_none());
8579 assert!(
8580 !spec.point_is_diffusive(),
8581 "absent classification (defaults to gate_compute, point_type=Gate → is_diffusive=false)",
8582 );
8583 }
8584
8585 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8586 /// identically through [`Self::point_is_diffusive`] AND through
8587 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_diffusive()`
8588 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8589 /// classification, `Some(_)` classification on every
8590 /// [`ConvergencePointType::ALL`] variant) so a future regression
8591 /// on either side of the resolver fails HERE at the parity
8592 /// boundary. Byte-for-byte peer of
8593 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
8594 /// on the SAME closed-set axis via a sibling projection.
8595 #[test]
8596 fn point_is_diffusive_matches_point_peer_through_lowered_classification() {
8597 // Absent classification.
8598 let eph = empty_ephemeral();
8599 let lowered: ProcessSpec = eph.clone().into();
8600 assert_eq!(
8601 eph.point_is_diffusive(),
8602 lowered.classification.point_is_diffusive(),
8603 "None-classification parity drift",
8604 );
8605 // Authored classification.
8606 for populated in ConvergencePointType::ALL {
8607 let mut classification = Classification::gate_compute();
8608 classification.point_type = populated;
8609 let mut eph = empty_ephemeral();
8610 eph.classification = Some(classification);
8611 let lowered: ProcessSpec = eph.clone().into();
8612 assert_eq!(
8613 eph.point_is_diffusive(),
8614 lowered.classification.point_is_diffusive(),
8615 "authored point_type={populated:?}: parity drift",
8616 );
8617 }
8618 }
8619
8620 /// MUTEX pin — [`Self::point_is_endomorphic`] AND
8621 /// [`Self::point_is_diffusive`] are NEVER simultaneously true for
8622 /// ANY [`EphemeralSpec`] (authored or defaulted), since the
8623 /// underlying [`ConvergencePointType`] closed set carves its
8624 /// eight variants into THREE disjoint buckets. Sweep the absent-
8625 /// classification case + every [`ConvergencePointType::ALL`]
8626 /// variant so a regression that crossed the wires between the
8627 /// two ephemeral-surface corner peers (one probe silently
8628 /// composing the wrong closed-set arm at the resolver-hop layer)
8629 /// fails HERE rather than at every downstream consumer that
8630 /// trusts the two probes partition the resolver's output into
8631 /// disjoint buckets. FIRST ephemeral-surface corner-peer pair on
8632 /// the `point_type` axis whose two projections carry a non-
8633 /// trivial closed-set-internal MUTEX relationship (distinct from
8634 /// the sibling `data`-axis pair whose two projections carry a
8635 /// non-trivial IMPLICATION relationship, sealed by
8636 /// `ephemeral_data_is_regulated_implies_data_is_restricted_over_all`).
8637 #[test]
8638 fn ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all() {
8639 // Absent classification.
8640 let eph = empty_ephemeral();
8641 assert!(
8642 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
8643 "None-classification: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
8644 );
8645 // Authored classification.
8646 for populated in ConvergencePointType::ALL {
8647 let mut classification = Classification::gate_compute();
8648 classification.point_type = populated;
8649 let mut eph = empty_ephemeral();
8650 eph.classification = Some(classification);
8651 assert!(
8652 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
8653 "authored point_type={populated:?}: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
8654 );
8655 }
8656 }
8657
8658 // ── EphemeralSpec::point_is_convergent pins ──────────────────────
8659 //
8660 // Fail-before-pass-after granularity: `point_is_convergent` did
8661 // not exist pre-lift on `impl EphemeralSpec` — every consumer
8662 // walking the "does this ephemeral spec's point-type project to
8663 // the N→1 convergent fan-in bucket?" question went through
8664 // `.resolved_classification().point_type.is_convergent()` or the
8665 // lowered `ProcessSpec`'s
8666 // `spec.classification.point_type.is_convergent()`. Post-lift the
8667 // EIGHTH derived-nullary-boolean peer on the ephemeral surface
8668 // (THIRD on the `point_type` axis) routes through the SAME
8669 // [`Self::resolved_classification`] resolver + the sibling
8670 // substrate primitive
8671 // [`crate::classification::Classification::point_is_convergent`],
8672 // so the two-surface parity contract holds by construction, AND
8673 // the THREE `point_type`-axis peers on this surface close into
8674 // the FULL three-way XOR partition contract.
8675
8676 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8677 /// [`Classification`] carries a specific [`ConvergencePointType`]
8678 /// variant answers [`Self::point_is_convergent`] matching the
8679 /// closed set's own [`ConvergencePointType::is_convergent`] truth
8680 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
8681 /// (a) hard-coded the body to a fixed answer, (b) inverted the
8682 /// projection, or (c) crossed the wires with the sibling
8683 /// [`ConvergencePointType::is_endomorphic`] /
8684 /// [`ConvergencePointType::is_diffusive`] projections fails HERE
8685 /// at the substrate primitive before drifting through the
8686 /// `convergent-point` fixed tag or the peer point surface.
8687 #[test]
8688 fn point_is_convergent_returns_point_type_projection_per_kind() {
8689 for populated in ConvergencePointType::ALL {
8690 let mut classification = Classification::gate_compute();
8691 classification.point_type = populated;
8692 let mut spec = empty_ephemeral();
8693 spec.classification = Some(classification);
8694 assert_eq!(
8695 spec.point_is_convergent(),
8696 populated.is_convergent(),
8697 "authored point_type={populated:?}: point_is_convergent() drift",
8698 );
8699 }
8700 }
8701
8702 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8703 /// with `classification: None` routes through the
8704 /// [`Self::resolved_classification`] resolver's substrate default
8705 /// [`Classification::gate_compute`], which carries
8706 /// [`ConvergencePointType::Gate`] (the canonical convergent
8707 /// barrier), and [`ConvergencePointType::Gate::is_convergent`]
8708 /// projects `true`, so [`Self::point_is_convergent`] returns
8709 /// `true`. Pins the resolver's chosen-field baseline at ONE
8710 /// narrow site — FIRST direct-scalar ephemeral-surface peer whose
8711 /// absent-classification baseline projects `true` through the
8712 /// resolver's chosen-field answer, mirror-inverted from the two
8713 /// sibling `point_is_endomorphic` / `point_is_diffusive`
8714 /// ephemeral-surface baselines which both project `false`.
8715 #[test]
8716 fn point_is_convergent_probes_true_on_absent_classification() {
8717 let spec = empty_ephemeral();
8718 assert!(spec.classification.is_none());
8719 assert!(
8720 spec.point_is_convergent(),
8721 "absent classification (defaults to gate_compute, point_type=Gate → is_convergent=true)",
8722 );
8723 }
8724
8725 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8726 /// identically through [`Self::point_is_convergent`] AND through
8727 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_convergent()`
8728 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8729 /// classification, `Some(_)` classification on every
8730 /// [`ConvergencePointType::ALL`] variant) so a future regression
8731 /// on either side of the resolver fails HERE at the parity
8732 /// boundary. Byte-for-byte peer of
8733 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
8734 /// and
8735 /// `point_is_diffusive_matches_point_peer_through_lowered_classification`
8736 /// on the SAME closed-set axis via a sibling projection.
8737 #[test]
8738 fn point_is_convergent_matches_point_peer_through_lowered_classification() {
8739 // Absent classification.
8740 let eph = empty_ephemeral();
8741 let lowered: ProcessSpec = eph.clone().into();
8742 assert_eq!(
8743 eph.point_is_convergent(),
8744 lowered.classification.point_is_convergent(),
8745 "None-classification parity drift",
8746 );
8747 // Authored classification.
8748 for populated in ConvergencePointType::ALL {
8749 let mut classification = Classification::gate_compute();
8750 classification.point_type = populated;
8751 let mut eph = empty_ephemeral();
8752 eph.classification = Some(classification);
8753 let lowered: ProcessSpec = eph.clone().into();
8754 assert_eq!(
8755 eph.point_is_convergent(),
8756 lowered.classification.point_is_convergent(),
8757 "authored point_type={populated:?}: parity drift",
8758 );
8759 }
8760 }
8761
8762 /// THREE-WAY XOR PARTITION pin — for the absent-classification
8763 /// baseline AND every [`ConvergencePointType::ALL`] variant,
8764 /// EXACTLY ONE of [`Self::point_is_endomorphic`],
8765 /// [`Self::point_is_diffusive`], and [`Self::point_is_convergent`]
8766 /// returns `true`. Closes the mutex pair
8767 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`
8768 /// into the FULL ternary XOR partition contract on the ephemeral
8769 /// surface — the resolver-hop peer of the parent-composed
8770 /// `classification_point_type_probes_form_three_way_xor_partition_over_all`
8771 /// test. Guarantees the absent-classification case lands in the
8772 /// convergent bucket (`gate_compute` → Gate → is_convergent =
8773 /// true), so every unadorned `(defephemeral …)` audits under a
8774 /// definite non-empty topology bucket.
8775 #[test]
8776 fn ephemeral_point_type_probes_form_three_way_xor_partition_over_all() {
8777 // Absent classification.
8778 let eph = empty_ephemeral();
8779 let buckets = [
8780 eph.point_is_endomorphic(),
8781 eph.point_is_diffusive(),
8782 eph.point_is_convergent(),
8783 ];
8784 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
8785 assert_eq!(
8786 hits, 1,
8787 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
8788 );
8789 // Authored classification.
8790 for populated in ConvergencePointType::ALL {
8791 let mut classification = Classification::gate_compute();
8792 classification.point_type = populated;
8793 let mut eph = empty_ephemeral();
8794 eph.classification = Some(classification);
8795 let buckets = [
8796 eph.point_is_endomorphic(),
8797 eph.point_is_diffusive(),
8798 eph.point_is_convergent(),
8799 ];
8800 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
8801 assert_eq!(
8802 hits, 1,
8803 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
8804 );
8805 }
8806 }
8807
8808 // ── EphemeralSpec::substrate_is_resource pins ────────────────────
8809 //
8810 // Fail-before-pass-after granularity: `substrate_is_resource` did
8811 // not exist pre-lift on `impl EphemeralSpec` — every consumer
8812 // walking the "does this ephemeral spec's substrate project to
8813 // the resource plane?" question went through
8814 // `.resolved_classification().substrate.is_resource()` or the
8815 // lowered `ProcessSpec`'s
8816 // `spec.classification.substrate.is_resource()`. Post-lift the
8817 // NINTH derived-nullary-boolean peer on the ephemeral surface
8818 // (FIRST on the `substrate` axis) routes through the SAME
8819 // [`Self::resolved_classification`] resolver + the sibling
8820 // substrate primitive
8821 // [`crate::classification::Classification::substrate_is_resource`],
8822 // so the two-surface parity contract holds by construction.
8823
8824 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8825 /// [`Classification`] carries a specific
8826 /// [`crate::classification::SubstrateType`] variant answers
8827 /// [`Self::substrate_is_resource`] matching the closed set's own
8828 /// [`crate::classification::SubstrateType::is_resource`] truth
8829 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
8830 /// so a regression that (a) hard-coded the body to a fixed
8831 /// answer, (b) inverted the projection, or (c) crossed the wires
8832 /// with the sibling
8833 /// [`crate::classification::SubstrateType::is_policy`] /
8834 /// [`crate::classification::SubstrateType::is_telemetry`]
8835 /// projections fails HERE at the substrate primitive before
8836 /// drifting through the `resource-substrate` fixed tag or the
8837 /// peer point surface.
8838 #[test]
8839 fn substrate_is_resource_returns_substrate_projection_per_kind() {
8840 for populated in SubstrateType::ALL {
8841 let mut classification = Classification::gate_compute();
8842 classification.substrate = populated;
8843 let mut spec = empty_ephemeral();
8844 spec.classification = Some(classification);
8845 assert_eq!(
8846 spec.substrate_is_resource(),
8847 populated.is_resource(),
8848 "authored substrate={populated:?}: substrate_is_resource() drift",
8849 );
8850 }
8851 }
8852
8853 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8854 /// with `classification: None` routes through the
8855 /// [`Self::resolved_classification`] resolver's substrate default
8856 /// [`Classification::gate_compute`], which carries
8857 /// [`crate::classification::SubstrateType::Compute`] (the
8858 /// canonical resource-plane substrate), and
8859 /// [`crate::classification::SubstrateType::Compute::is_resource`]
8860 /// projects `true`, so [`Self::substrate_is_resource`] returns
8861 /// `true`. Pins the resolver's chosen-field baseline at ONE
8862 /// narrow site — mirror-aligned with the sibling
8863 /// `point_is_convergent_probes_true_on_absent_classification`
8864 /// baseline (both projections on `gate_compute` chosen fields
8865 /// answer `true`).
8866 #[test]
8867 fn substrate_is_resource_probes_true_on_absent_classification() {
8868 let spec = empty_ephemeral();
8869 assert!(spec.classification.is_none());
8870 assert!(
8871 spec.substrate_is_resource(),
8872 "absent classification (defaults to gate_compute, substrate=Compute → is_resource=true)",
8873 );
8874 }
8875
8876 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8877 /// identically through [`Self::substrate_is_resource`] AND through
8878 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_resource()`
8879 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8880 /// classification, `Some(_)` classification on every
8881 /// [`crate::classification::SubstrateType::ALL`] variant) so a
8882 /// future regression on either side of the resolver fails HERE
8883 /// at the parity boundary. Byte-for-byte peer of
8884 /// `point_is_convergent_matches_point_peer_through_lowered_classification`
8885 /// on a sibling classification axis.
8886 #[test]
8887 fn substrate_is_resource_matches_point_peer_through_lowered_classification() {
8888 // Absent classification.
8889 let eph = empty_ephemeral();
8890 let lowered: ProcessSpec = eph.clone().into();
8891 assert_eq!(
8892 eph.substrate_is_resource(),
8893 lowered.classification.substrate_is_resource(),
8894 "None-classification parity drift",
8895 );
8896 // Authored classification.
8897 for populated in SubstrateType::ALL {
8898 let mut classification = Classification::gate_compute();
8899 classification.substrate = populated;
8900 let mut eph = empty_ephemeral();
8901 eph.classification = Some(classification);
8902 let lowered: ProcessSpec = eph.clone().into();
8903 assert_eq!(
8904 eph.substrate_is_resource(),
8905 lowered.classification.substrate_is_resource(),
8906 "authored substrate={populated:?}: parity drift",
8907 );
8908 }
8909 }
8910
8911 // ── EphemeralSpec::substrate_is_policy pins ──────────────────────
8912 //
8913 // Fail-before-pass-after granularity: `substrate_is_policy` did
8914 // not exist pre-lift on `impl EphemeralSpec` — every consumer
8915 // walking the "does this ephemeral spec's substrate project to
8916 // the policy plane?" question went through
8917 // `.resolved_classification().substrate.is_policy()` or the
8918 // lowered `ProcessSpec`'s
8919 // `spec.classification.substrate.is_policy()`. Post-lift the
8920 // TENTH derived-nullary-boolean peer on the ephemeral surface
8921 // (SECOND on the `substrate` axis) routes through the SAME
8922 // [`Self::resolved_classification`] resolver + the sibling
8923 // substrate primitive
8924 // [`crate::classification::Classification::substrate_is_policy`],
8925 // so the two-surface parity contract holds by construction, AND
8926 // the two `substrate`-axis peers on this surface open the
8927 // MUTEX pair on the axis via
8928 // `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`.
8929
8930 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
8931 /// [`Classification`] carries a specific
8932 /// [`crate::classification::SubstrateType`] variant answers
8933 /// [`Self::substrate_is_policy`] matching the closed set's own
8934 /// [`crate::classification::SubstrateType::is_policy`] truth
8935 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
8936 /// so a regression that (a) hard-coded the body to a fixed
8937 /// answer, (b) inverted the projection, or (c) crossed the wires
8938 /// with the sibling
8939 /// [`crate::classification::SubstrateType::is_resource`] /
8940 /// [`crate::classification::SubstrateType::is_telemetry`]
8941 /// projections fails HERE at the substrate primitive before
8942 /// drifting through the `policy-substrate` fixed tag or the
8943 /// peer point surface.
8944 #[test]
8945 fn substrate_is_policy_returns_substrate_projection_per_kind() {
8946 for populated in SubstrateType::ALL {
8947 let mut classification = Classification::gate_compute();
8948 classification.substrate = populated;
8949 let mut spec = empty_ephemeral();
8950 spec.classification = Some(classification);
8951 assert_eq!(
8952 spec.substrate_is_policy(),
8953 populated.is_policy(),
8954 "authored substrate={populated:?}: substrate_is_policy() drift",
8955 );
8956 }
8957 }
8958
8959 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
8960 /// with `classification: None` routes through the
8961 /// [`Self::resolved_classification`] resolver's substrate default
8962 /// [`Classification::gate_compute`], which carries
8963 /// [`crate::classification::SubstrateType::Compute`] (the
8964 /// canonical resource-plane substrate, NOT a policy plane), and
8965 /// [`crate::classification::SubstrateType::Compute::is_policy`]
8966 /// projects `false`, so [`Self::substrate_is_policy`] returns
8967 /// `false`. Pins the resolver's chosen-field baseline at ONE
8968 /// narrow site — mirror-inverted from the sibling
8969 /// `substrate_is_resource_probes_true_on_absent_classification`
8970 /// (both projections on `gate_compute`'s chosen `substrate`
8971 /// field, but the sibling answers `true` where this one
8972 /// answers `false` — the closed set's disjoint plane partition
8973 /// forbids both being true).
8974 #[test]
8975 fn substrate_is_policy_probes_false_on_absent_classification() {
8976 let spec = empty_ephemeral();
8977 assert!(spec.classification.is_none());
8978 assert!(
8979 !spec.substrate_is_policy(),
8980 "absent classification (defaults to gate_compute, substrate=Compute → is_policy=false)",
8981 );
8982 }
8983
8984 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8985 /// identically through [`Self::substrate_is_policy`] AND through
8986 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_policy()`
8987 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
8988 /// classification, `Some(_)` classification on every
8989 /// [`crate::classification::SubstrateType::ALL`] variant) so a
8990 /// future regression on either side of the resolver fails HERE
8991 /// at the parity boundary. Byte-for-byte peer of
8992 /// `substrate_is_resource_matches_point_peer_through_lowered_classification`
8993 /// on the SAME closed-set axis via a sibling projection.
8994 #[test]
8995 fn substrate_is_policy_matches_point_peer_through_lowered_classification() {
8996 // Absent classification.
8997 let eph = empty_ephemeral();
8998 let lowered: ProcessSpec = eph.clone().into();
8999 assert_eq!(
9000 eph.substrate_is_policy(),
9001 lowered.classification.substrate_is_policy(),
9002 "None-classification parity drift",
9003 );
9004 // Authored classification.
9005 for populated in SubstrateType::ALL {
9006 let mut classification = Classification::gate_compute();
9007 classification.substrate = populated;
9008 let mut eph = empty_ephemeral();
9009 eph.classification = Some(classification);
9010 let lowered: ProcessSpec = eph.clone().into();
9011 assert_eq!(
9012 eph.substrate_is_policy(),
9013 lowered.classification.substrate_is_policy(),
9014 "authored substrate={populated:?}: parity drift",
9015 );
9016 }
9017 }
9018
9019 /// MUTEX pin — [`Self::substrate_is_resource`] AND
9020 /// [`Self::substrate_is_policy`] are NEVER simultaneously true
9021 /// for ANY [`EphemeralSpec`] (authored or defaulted), since the
9022 /// underlying [`crate::classification::SubstrateType`] closed set
9023 /// carves its eight variants into THREE disjoint buckets. Sweep
9024 /// the absent-classification case + every
9025 /// [`crate::classification::SubstrateType::ALL`] variant so a
9026 /// regression that crossed the wires between the two ephemeral-
9027 /// surface corner peers (one probe silently composing the wrong
9028 /// closed-set arm at the resolver-hop layer) fails HERE rather
9029 /// than at every downstream consumer that trusts the two probes
9030 /// partition the resolver's output into disjoint buckets.
9031 /// FIRST ephemeral-surface `substrate`-axis corner-peer pair
9032 /// carrying a non-trivial MUTEX relationship — structural twin
9033 /// of the sibling `point_type`-axis MUTEX pair sealed on this
9034 /// surface by
9035 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
9036 #[test]
9037 fn ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all() {
9038 // Absent classification.
9039 let eph = empty_ephemeral();
9040 assert!(
9041 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
9042 "None-classification: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
9043 );
9044 // Authored classification.
9045 for populated in SubstrateType::ALL {
9046 let mut classification = Classification::gate_compute();
9047 classification.substrate = populated;
9048 let mut eph = empty_ephemeral();
9049 eph.classification = Some(classification);
9050 assert!(
9051 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
9052 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
9053 );
9054 }
9055 }
9056
9057 // ── EphemeralSpec::substrate_is_telemetry pins ───────────────────
9058 //
9059 // Fail-before-pass-after granularity: `substrate_is_telemetry`
9060 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9061 // walking the "does this ephemeral spec's substrate project to
9062 // the telemetry plane?" question went through
9063 // `.resolved_classification().substrate.is_telemetry()` or the
9064 // lowered `ProcessSpec`'s
9065 // `spec.classification.substrate.is_telemetry()`. Post-lift the
9066 // ELEVENTH derived-nullary-boolean peer on the ephemeral surface
9067 // (THIRD on the `substrate` axis) routes through the SAME
9068 // [`Self::resolved_classification`] resolver + the sibling
9069 // substrate primitive
9070 // [`crate::classification::Classification::substrate_is_telemetry`],
9071 // so the two-surface parity contract holds by construction, AND
9072 // the three `substrate`-axis peers on this surface CLOSE the
9073 // axis into the FULL three-way XOR partition contract via
9074 // `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
9075
9076 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9077 /// [`Classification`] carries a specific
9078 /// [`crate::classification::SubstrateType`] variant answers
9079 /// [`Self::substrate_is_telemetry`] matching the closed set's own
9080 /// [`crate::classification::SubstrateType::is_telemetry`] truth
9081 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
9082 /// so a regression that (a) hard-coded the body to a fixed
9083 /// answer, (b) inverted the projection, or (c) crossed the wires
9084 /// with the sibling
9085 /// [`crate::classification::SubstrateType::is_resource`] /
9086 /// [`crate::classification::SubstrateType::is_policy`]
9087 /// projections fails HERE at the substrate primitive before
9088 /// drifting through the `telemetry-substrate` fixed tag or the
9089 /// peer point surface.
9090 #[test]
9091 fn substrate_is_telemetry_returns_substrate_projection_per_kind() {
9092 for populated in SubstrateType::ALL {
9093 let mut classification = Classification::gate_compute();
9094 classification.substrate = populated;
9095 let mut spec = empty_ephemeral();
9096 spec.classification = Some(classification);
9097 assert_eq!(
9098 spec.substrate_is_telemetry(),
9099 populated.is_telemetry(),
9100 "authored substrate={populated:?}: substrate_is_telemetry() drift",
9101 );
9102 }
9103 }
9104
9105 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9106 /// with `classification: None` routes through the
9107 /// [`Self::resolved_classification`] resolver's substrate default
9108 /// [`Classification::gate_compute`], which carries
9109 /// [`crate::classification::SubstrateType::Compute`] (the
9110 /// canonical resource-plane substrate, NOT a telemetry plane),
9111 /// and
9112 /// [`crate::classification::SubstrateType::Compute::is_telemetry`]
9113 /// projects `false`, so [`Self::substrate_is_telemetry`] returns
9114 /// `false`. Pins the resolver's chosen-field baseline at ONE
9115 /// narrow site — aligned with the sibling
9116 /// `substrate_is_policy_probes_false_on_absent_classification`
9117 /// (both projections on `gate_compute`'s chosen `substrate`
9118 /// field project `false` since `Compute` lives in the resource
9119 /// plane), mirror-inverted from
9120 /// `substrate_is_resource_probes_true_on_absent_classification`.
9121 #[test]
9122 fn substrate_is_telemetry_probes_false_on_absent_classification() {
9123 let spec = empty_ephemeral();
9124 assert!(spec.classification.is_none());
9125 assert!(
9126 !spec.substrate_is_telemetry(),
9127 "absent classification (defaults to gate_compute, substrate=Compute → is_telemetry=false)",
9128 );
9129 }
9130
9131 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9132 /// identically through [`Self::substrate_is_telemetry`] AND
9133 /// through
9134 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_telemetry()`
9135 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9136 /// classification, `Some(_)` classification on every
9137 /// [`crate::classification::SubstrateType::ALL`] variant) so a
9138 /// future regression on either side of the resolver fails HERE
9139 /// at the parity boundary. Byte-for-byte peer of
9140 /// `substrate_is_policy_matches_point_peer_through_lowered_classification`
9141 /// on the SAME closed-set axis via a sibling projection.
9142 #[test]
9143 fn substrate_is_telemetry_matches_point_peer_through_lowered_classification() {
9144 // Absent classification.
9145 let eph = empty_ephemeral();
9146 let lowered: ProcessSpec = eph.clone().into();
9147 assert_eq!(
9148 eph.substrate_is_telemetry(),
9149 lowered.classification.substrate_is_telemetry(),
9150 "None-classification parity drift",
9151 );
9152 // Authored classification.
9153 for populated in SubstrateType::ALL {
9154 let mut classification = Classification::gate_compute();
9155 classification.substrate = populated;
9156 let mut eph = empty_ephemeral();
9157 eph.classification = Some(classification);
9158 let lowered: ProcessSpec = eph.clone().into();
9159 assert_eq!(
9160 eph.substrate_is_telemetry(),
9161 lowered.classification.substrate_is_telemetry(),
9162 "authored substrate={populated:?}: parity drift",
9163 );
9164 }
9165 }
9166
9167 /// MUTEX pin — [`Self::substrate_is_resource`] AND
9168 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
9169 /// for ANY [`EphemeralSpec`] (authored or defaulted). Second
9170 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
9171 /// peer of
9172 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9173 /// on a sibling closed-set projection.
9174 #[test]
9175 fn ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all() {
9176 // Absent classification.
9177 let eph = empty_ephemeral();
9178 assert!(
9179 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
9180 "None-classification: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
9181 );
9182 // Authored classification.
9183 for populated in SubstrateType::ALL {
9184 let mut classification = Classification::gate_compute();
9185 classification.substrate = populated;
9186 let mut eph = empty_ephemeral();
9187 eph.classification = Some(classification);
9188 assert!(
9189 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
9190 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
9191 );
9192 }
9193 }
9194
9195 /// MUTEX pin — [`Self::substrate_is_policy`] AND
9196 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
9197 /// for ANY [`EphemeralSpec`] (authored or defaulted). Third
9198 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
9199 /// completes the three pairwise MUTEX relations alongside
9200 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9201 /// and
9202 /// `ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all`.
9203 #[test]
9204 fn ephemeral_substrate_is_policy_and_substrate_is_telemetry_are_mutex_over_all() {
9205 // Absent classification.
9206 let eph = empty_ephemeral();
9207 assert!(
9208 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
9209 "None-classification: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
9210 );
9211 // Authored classification.
9212 for populated in SubstrateType::ALL {
9213 let mut classification = Classification::gate_compute();
9214 classification.substrate = populated;
9215 let mut eph = empty_ephemeral();
9216 eph.classification = Some(classification);
9217 assert!(
9218 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
9219 "authored substrate={populated:?}: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
9220 );
9221 }
9222 }
9223
9224 /// THREE-WAY XOR PARTITION pin — for the absent-classification
9225 /// baseline AND every [`crate::classification::SubstrateType::ALL`]
9226 /// variant, EXACTLY ONE of [`Self::substrate_is_resource`],
9227 /// [`Self::substrate_is_policy`], and
9228 /// [`Self::substrate_is_telemetry`] returns `true`. CLOSES the
9229 /// three pairwise MUTEX pins on the substrate axis
9230 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`,
9231 /// `substrate_is_resource ⇒ ¬substrate_is_telemetry`,
9232 /// `substrate_is_policy ⇒ ¬substrate_is_telemetry`) into the
9233 /// FULL ternary XOR partition contract on the ephemeral surface
9234 /// — the resolver-hop peer of the parent-composed
9235 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`
9236 /// test. Structural twin of the sibling `point_type`-axis
9237 /// ternary lift sealed on this surface by
9238 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
9239 /// Guarantees the absent-classification case lands in the
9240 /// resource bucket (`gate_compute` → Compute → is_resource =
9241 /// true), so every unadorned `(defephemeral …)` audits under a
9242 /// definite non-empty plane bucket.
9243 #[test]
9244 fn ephemeral_substrate_probes_form_three_way_xor_partition_over_all() {
9245 // Absent classification.
9246 let eph = empty_ephemeral();
9247 let buckets = [
9248 eph.substrate_is_resource(),
9249 eph.substrate_is_policy(),
9250 eph.substrate_is_telemetry(),
9251 ];
9252 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9253 assert_eq!(
9254 hits, 1,
9255 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9256 );
9257 // Authored classification.
9258 for populated in SubstrateType::ALL {
9259 let mut classification = Classification::gate_compute();
9260 classification.substrate = populated;
9261 let mut eph = empty_ephemeral();
9262 eph.classification = Some(classification);
9263 let buckets = [
9264 eph.substrate_is_resource(),
9265 eph.substrate_is_policy(),
9266 eph.substrate_is_telemetry(),
9267 ];
9268 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9269 assert_eq!(
9270 hits, 1,
9271 "authored substrate={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
9272 );
9273 }
9274 }
9275
9276 // ── EphemeralSpec::calm_is_monotone pins ─────────────────────────
9277 //
9278 // Fail-before-pass-after granularity: `calm_is_monotone` did not
9279 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9280 // the "can this ephemeral spec participate in gossip-only writes?"
9281 // question went through the antisymmetric
9282 // `!self.calm_requires_coordination()` or through
9283 // `.resolved_classification().calm.is_monotone()`. Post-lift the
9284 // TWELFTH derived-nullary-boolean peer on the ephemeral surface
9285 // (SECOND on the calm axis, closing that axis into a binary XOR
9286 // partition on this surface) routes through the SAME
9287 // [`Self::resolved_classification`] resolver + the sibling
9288 // substrate primitive
9289 // [`crate::classification::Classification::calm_is_monotone`], so
9290 // the two-surface parity contract holds by construction, AND the
9291 // two calm-axis peers on this surface CLOSE the axis into the
9292 // FULL binary XOR partition contract via
9293 // `ephemeral_calm_probes_form_binary_xor_partition_over_all`.
9294
9295 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9296 /// [`Classification`] carries a specific
9297 /// [`crate::classification::CalmClassification`] variant answers
9298 /// [`Self::calm_is_monotone`] matching the closed set's own
9299 /// [`crate::classification::CalmClassification::is_monotone`]
9300 /// truth table. Sweep
9301 /// [`crate::classification::CalmClassification::ALL`] so a
9302 /// regression that (a) hard-coded the body to a fixed answer,
9303 /// (b) inverted the projection, or (c) crossed the wires with
9304 /// the sibling
9305 /// [`crate::classification::CalmClassification::requires_coordination`]
9306 /// projection fails HERE at the substrate primitive before
9307 /// drifting through the `monotone-calm` fixed tag or the peer
9308 /// point surface.
9309 #[test]
9310 fn calm_is_monotone_returns_calm_projection_per_kind() {
9311 for populated in CalmClassification::ALL {
9312 let mut classification = Classification::gate_compute();
9313 classification.calm = populated;
9314 let mut spec = empty_ephemeral();
9315 spec.classification = Some(classification);
9316 assert_eq!(
9317 spec.calm_is_monotone(),
9318 populated.is_monotone(),
9319 "authored calm={populated:?}: calm_is_monotone() drift",
9320 );
9321 }
9322 }
9323
9324 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9325 /// with `classification: None` routes through the
9326 /// [`Self::resolved_classification`] resolver's substrate default
9327 /// [`Classification::gate_compute`], which carries
9328 /// [`crate::classification::CalmClassification::default = Monotone`]
9329 /// via `#[default]`, and
9330 /// [`crate::classification::CalmClassification::Monotone::is_monotone`]
9331 /// projects `true`, so [`Self::calm_is_monotone`] returns
9332 /// `true`. Pins the resolver's default-arm short-circuit through
9333 /// TWO layers of `Default` ([`Classification::gate_compute`] →
9334 /// [`crate::classification::CalmClassification::default`])
9335 /// reaching this derived-nullary predicate. Mirror-inverted from
9336 /// the sibling
9337 /// `calm_requires_coordination_probes_false_on_absent_classification`
9338 /// (both walk the SAME defaulted `calm` field, so
9339 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
9340 /// closed set's disjoint XOR partition). Guarantees every
9341 /// unadorned `(defephemeral …)` reads as gossip-eligible under
9342 /// the positive CALM framing.
9343 #[test]
9344 fn calm_is_monotone_probes_true_on_absent_classification() {
9345 let spec = empty_ephemeral();
9346 assert!(spec.classification.is_none());
9347 assert!(
9348 spec.calm_is_monotone(),
9349 "absent classification (defaults to gate_compute, calm=Monotone → is_monotone=true)",
9350 );
9351 }
9352
9353 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9354 /// identically through [`Self::calm_is_monotone`] AND through
9355 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_is_monotone()`
9356 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9357 /// classification, `Some(_)` classification on every
9358 /// [`crate::classification::CalmClassification::ALL`] variant) so
9359 /// a future regression on either side of the resolver fails HERE
9360 /// at the parity boundary. Byte-for-byte peer of
9361 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
9362 /// on the SAME closed-set axis via the antisymmetric projection.
9363 #[test]
9364 fn calm_is_monotone_matches_point_peer_through_lowered_classification() {
9365 // Absent classification.
9366 let eph = empty_ephemeral();
9367 let lowered: ProcessSpec = eph.clone().into();
9368 assert_eq!(
9369 eph.calm_is_monotone(),
9370 lowered.classification.calm_is_monotone(),
9371 "None-classification parity drift",
9372 );
9373 // Authored classification.
9374 for populated in CalmClassification::ALL {
9375 let mut classification = Classification::gate_compute();
9376 classification.calm = populated;
9377 let mut eph = empty_ephemeral();
9378 eph.classification = Some(classification);
9379 let lowered: ProcessSpec = eph.clone().into();
9380 assert_eq!(
9381 eph.calm_is_monotone(),
9382 lowered.classification.calm_is_monotone(),
9383 "authored calm={populated:?}: parity drift",
9384 );
9385 }
9386 }
9387
9388 /// MUTEX pin — [`Self::calm_requires_coordination`] AND
9389 /// [`Self::calm_is_monotone`] are NEVER simultaneously true for
9390 /// ANY [`EphemeralSpec`] (authored or defaulted). FIRST
9391 /// ephemeral-surface `calm`-axis corner-peer MUTEX pin — the
9392 /// calm axis's counterpart to the sibling substrate-axis
9393 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
9394 /// on a binary (rather than ternary) closed set.
9395 #[test]
9396 fn ephemeral_calm_requires_coordination_and_calm_is_monotone_are_mutex_over_all() {
9397 // Absent classification.
9398 let eph = empty_ephemeral();
9399 assert!(
9400 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
9401 "None-classification: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
9402 );
9403 // Authored classification.
9404 for populated in CalmClassification::ALL {
9405 let mut classification = Classification::gate_compute();
9406 classification.calm = populated;
9407 let mut eph = empty_ephemeral();
9408 eph.classification = Some(classification);
9409 assert!(
9410 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
9411 "authored calm={populated:?}: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
9412 );
9413 }
9414 }
9415
9416 /// BINARY XOR PARTITION pin — for the absent-classification
9417 /// baseline AND every
9418 /// [`crate::classification::CalmClassification::ALL`] variant,
9419 /// EXACTLY ONE of [`Self::calm_is_monotone`] and
9420 /// [`Self::calm_requires_coordination`] returns `true`. CLOSES
9421 /// the calm-axis MUTEX pin
9422 /// (`calm_requires_coordination ⇒ ¬calm_is_monotone`) into the
9423 /// FULL binary XOR partition contract on the ephemeral surface
9424 /// — the resolver-hop peer of the parent-composed
9425 /// `classification_calm_probes_form_binary_xor_partition_over_all`
9426 /// test. Binary counterpart of the ternary XOR partitions sealed
9427 /// on the sibling `point_type` and `substrate` axes by
9428 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
9429 /// and
9430 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
9431 /// Guarantees the absent-classification case lands in the
9432 /// monotone bucket (`gate_compute` → CalmClassification::Monotone
9433 /// → is_monotone = true), so every unadorned `(defephemeral …)`
9434 /// audits under a definite non-empty CALM bucket.
9435 #[test]
9436 fn ephemeral_calm_probes_form_binary_xor_partition_over_all() {
9437 // Absent classification.
9438 let eph = empty_ephemeral();
9439 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
9440 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9441 assert_eq!(
9442 hits, 1,
9443 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9444 );
9445 // Authored classification.
9446 for populated in CalmClassification::ALL {
9447 let mut classification = Classification::gate_compute();
9448 classification.calm = populated;
9449 let mut eph = empty_ephemeral();
9450 eph.classification = Some(classification);
9451 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
9452 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9453 assert_eq!(
9454 hits, 1,
9455 "authored calm={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9456 );
9457 }
9458 }
9459
9460 // ── EphemeralSpec::data_is_public pins ───────────────────────────
9461 //
9462 // Fail-before-pass-after granularity: `data_is_public` did not
9463 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9464 // the "is this ephemeral spec's dataset publicly distributable?"
9465 // question went through the antisymmetric
9466 // `!self.data_is_restricted()` or through
9467 // `.resolved_classification().data_classification.is_public()`.
9468 // Post-lift the THIRTEENTH derived-nullary-boolean peer on the
9469 // ephemeral surface (THIRD on the data axis, closing that axis
9470 // into a binary XOR partition on this surface) routes through the
9471 // SAME [`Self::resolved_classification`] resolver + the sibling
9472 // substrate primitive
9473 // [`crate::classification::Classification::data_is_public`], so
9474 // the two-surface parity contract holds by construction, AND the
9475 // two-way public/restricted split on this surface CLOSES the
9476 // data axis into the FULL binary XOR partition contract via
9477 // `ephemeral_data_probes_form_binary_xor_partition_over_all`.
9478
9479 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9480 /// [`Classification`] carries a specific
9481 /// [`crate::classification::DataClassification`] variant answers
9482 /// [`Self::data_is_public`] matching the closed set's own
9483 /// [`crate::classification::DataClassification::is_public`] truth
9484 /// table. Sweep
9485 /// [`crate::classification::DataClassification::ALL`] so a
9486 /// regression that (a) hard-coded the body to a fixed answer,
9487 /// (b) inverted the projection, or (c) crossed the wires with
9488 /// the sibling
9489 /// [`crate::classification::DataClassification::is_restricted`]
9490 /// projection fails HERE at the substrate primitive before
9491 /// drifting through the `public-data` fixed tag or the peer
9492 /// point surface.
9493 #[test]
9494 fn data_is_public_returns_data_projection_per_kind() {
9495 for populated in DataClassification::ALL {
9496 let mut classification = Classification::gate_compute();
9497 classification.data_classification = populated;
9498 let mut spec = empty_ephemeral();
9499 spec.classification = Some(classification);
9500 assert_eq!(
9501 spec.data_is_public(),
9502 populated.is_public(),
9503 "authored data_classification={populated:?}: data_is_public() drift",
9504 );
9505 }
9506 }
9507
9508 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9509 /// with `classification: None` routes through the
9510 /// [`Self::resolved_classification`] resolver's substrate default
9511 /// [`Classification::gate_compute`], which carries
9512 /// [`crate::classification::DataClassification::default = Internal`]
9513 /// via `#[default]`, and
9514 /// [`crate::classification::DataClassification::Internal::is_public`]
9515 /// projects `false`, so [`Self::data_is_public`] returns `false`.
9516 /// Pins the resolver's default-arm short-circuit through TWO
9517 /// layers of `Default` ([`Classification::gate_compute`] →
9518 /// [`crate::classification::DataClassification::default`])
9519 /// reaching this derived-nullary predicate. Mirror-inverted from
9520 /// the sibling
9521 /// `data_is_restricted_probes_true_on_absent_classification`
9522 /// (both walk the SAME defaulted `data_classification` field, so
9523 /// `is_restricted = true` ⇒ `is_public = false` on the closed
9524 /// set's disjoint XOR partition). Guarantees every unadorned
9525 /// `(defephemeral …)` audits under the access-controlled default
9526 /// rather than silently promoting an unadorned dataset onto the
9527 /// freely-distributable path.
9528 #[test]
9529 fn data_is_public_probes_false_on_absent_classification() {
9530 let spec = empty_ephemeral();
9531 assert!(spec.classification.is_none());
9532 assert!(
9533 !spec.data_is_public(),
9534 "absent classification (defaults to gate_compute, data_classification=Internal → is_public=false)",
9535 );
9536 }
9537
9538 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9539 /// identically through [`Self::data_is_public`] AND through
9540 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_public()`
9541 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9542 /// classification, `Some(_)` classification on every
9543 /// [`crate::classification::DataClassification::ALL`] variant) so
9544 /// a future regression on either side of the resolver fails HERE
9545 /// at the parity boundary. Byte-for-byte peer of
9546 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
9547 /// on the SAME closed-set axis via the antisymmetric projection.
9548 #[test]
9549 fn data_is_public_matches_point_peer_through_lowered_classification() {
9550 // Absent classification.
9551 let eph = empty_ephemeral();
9552 let lowered: ProcessSpec = eph.clone().into();
9553 assert_eq!(
9554 eph.data_is_public(),
9555 lowered.classification.data_is_public(),
9556 "None-classification parity drift",
9557 );
9558 // Authored classification.
9559 for populated in DataClassification::ALL {
9560 let mut classification = Classification::gate_compute();
9561 classification.data_classification = populated;
9562 let mut eph = empty_ephemeral();
9563 eph.classification = Some(classification);
9564 let lowered: ProcessSpec = eph.clone().into();
9565 assert_eq!(
9566 eph.data_is_public(),
9567 lowered.classification.data_is_public(),
9568 "authored data_classification={populated:?}: parity drift",
9569 );
9570 }
9571 }
9572
9573 /// MUTEX pin — [`Self::data_is_regulated`] AND
9574 /// [`Self::data_is_public`] are NEVER simultaneously true for ANY
9575 /// [`EphemeralSpec`] (authored or defaulted). FIRST ephemeral-
9576 /// surface data-axis antisymmetric MUTEX pin against the
9577 /// positive-distribution framing: sealed on the closed set by
9578 /// `data_classification_regulated_implies_not_public` and lifted
9579 /// through the resolver hop as a substrate-wide contract on this
9580 /// surface.
9581 #[test]
9582 fn ephemeral_data_is_regulated_and_data_is_public_are_mutex_over_all() {
9583 // Absent classification.
9584 let eph = empty_ephemeral();
9585 assert!(
9586 !(eph.data_is_regulated() && eph.data_is_public()),
9587 "None-classification: data_is_regulated AND data_is_public both true (mutex violated)",
9588 );
9589 // Authored classification.
9590 for populated in DataClassification::ALL {
9591 let mut classification = Classification::gate_compute();
9592 classification.data_classification = populated;
9593 let mut eph = empty_ephemeral();
9594 eph.classification = Some(classification);
9595 assert!(
9596 !(eph.data_is_regulated() && eph.data_is_public()),
9597 "authored data_classification={populated:?}: data_is_regulated AND data_is_public both true (mutex violated)",
9598 );
9599 }
9600 }
9601
9602 /// BINARY XOR PARTITION pin — for the absent-classification
9603 /// baseline AND every
9604 /// [`crate::classification::DataClassification::ALL`] variant,
9605 /// EXACTLY ONE of [`Self::data_is_public`] and
9606 /// [`Self::data_is_restricted`] returns `true`. CLOSES the data-
9607 /// axis MUTEX pin (`data_is_regulated ⇒ ¬data_is_public`) into
9608 /// the FULL binary XOR partition contract on the ephemeral
9609 /// surface — the resolver-hop peer of the parent-composed
9610 /// `classification_data_probes_form_binary_xor_partition_over_all`
9611 /// test. Binary counterpart of the ternary XOR partitions sealed
9612 /// on the sibling `point_type` and `substrate` axes by
9613 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
9614 /// and
9615 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
9616 /// Guarantees the absent-classification case lands in the
9617 /// access-controlled bucket (`gate_compute` →
9618 /// DataClassification::Internal → is_public = false,
9619 /// is_restricted = true), so every unadorned `(defephemeral …)`
9620 /// audits under a definite non-empty distribution bucket.
9621 #[test]
9622 fn ephemeral_data_probes_form_binary_xor_partition_over_all() {
9623 // Absent classification.
9624 let eph = empty_ephemeral();
9625 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
9626 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9627 assert_eq!(
9628 hits, 1,
9629 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9630 );
9631 // Authored classification.
9632 for populated in DataClassification::ALL {
9633 let mut classification = Classification::gate_compute();
9634 classification.data_classification = populated;
9635 let mut eph = empty_ephemeral();
9636 eph.classification = Some(classification);
9637 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
9638 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9639 assert_eq!(
9640 hits, 1,
9641 "authored data_classification={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9642 );
9643 }
9644 }
9645
9646 // ── EphemeralSpec::direction_prefers_lower pins ─────────────────
9647 //
9648 // Fail-before-pass-after granularity: `direction_prefers_lower`
9649 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9650 // walking the "does this ephemeral spec's rate-window evaluator
9651 // treat decreasing values as improvement?" question went through
9652 // `.resolved_classification().horizon.direction.unwrap_or_default().prefers_lower()`.
9653 // Post-lift the FOURTEENTH derived-nullary-boolean peer on the
9654 // ephemeral surface (FIRST on the optimization-direction axis,
9655 // opening the SIXTH classification axis into the fixed-tag algebra)
9656 // routes through the SAME [`Self::resolved_classification`] resolver
9657 // + the sibling substrate primitive
9658 // [`crate::classification::Classification::direction_prefers_lower`],
9659 // so the two-surface parity contract holds by construction.
9660
9661 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9662 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
9663 /// answers [`Self::direction_prefers_lower`] matching the closed
9664 /// set's own
9665 /// [`crate::classification::OptimizationDirection::prefers_lower`]
9666 /// truth table. Sweep
9667 /// [`crate::classification::OptimizationDirection::ALL`] so a
9668 /// regression that (a) hard-coded the body to a fixed answer,
9669 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
9670 /// hop, or (d) crossed the wires with a sibling classification-axis
9671 /// probe fails HERE at the substrate primitive before drifting
9672 /// through the `prefers-lower-direction` fixed tag or the peer
9673 /// point surface.
9674 #[test]
9675 fn direction_prefers_lower_returns_direction_projection_per_kind() {
9676 for populated in OptimizationDirection::ALL {
9677 let mut classification = Classification::gate_compute();
9678 classification.horizon.direction = Some(populated);
9679 let mut spec = empty_ephemeral();
9680 spec.classification = Some(classification);
9681 assert_eq!(
9682 spec.direction_prefers_lower(),
9683 populated.prefers_lower(),
9684 "authored horizon.direction={populated:?}: direction_prefers_lower() drift",
9685 );
9686 }
9687 }
9688
9689 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9690 /// with `classification: None` routes through the
9691 /// [`Self::resolved_classification`] resolver's substrate default
9692 /// [`Classification::gate_compute`], which carries
9693 /// `horizon: Horizon::default()` whose `direction` field is `None`,
9694 /// so `unwrap_or_default()` defaults to
9695 /// [`crate::classification::OptimizationDirection::Minimize`] via
9696 /// `#[default]`, and `Minimize.prefers_lower()` projects `true`,
9697 /// so [`Self::direction_prefers_lower`] returns `true`. Pins the
9698 /// resolver's default-arm short-circuit through THREE layers of
9699 /// `Default` ([`Classification::gate_compute`] →
9700 /// [`crate::classification::Horizon::default`] with `direction: None`
9701 /// → [`crate::classification::OptimizationDirection::default =
9702 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
9703 /// every unadorned `(defephemeral …)` reads under the lower-is-
9704 /// better polarity default (safe under the asymptotic-health
9705 /// rate-window evaluator convention: an operator must deliberately
9706 /// opt into Maximize polarity).
9707 #[test]
9708 fn direction_prefers_lower_probes_true_on_absent_classification() {
9709 let spec = empty_ephemeral();
9710 assert!(spec.classification.is_none());
9711 assert!(
9712 spec.direction_prefers_lower(),
9713 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_lower=true)",
9714 );
9715 }
9716
9717 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9718 /// identically through [`Self::direction_prefers_lower`] AND through
9719 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_lower()`
9720 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9721 /// classification, `Some(_)` classification on every
9722 /// [`crate::classification::OptimizationDirection::ALL`] variant) so
9723 /// a future regression on either side of the resolver fails HERE
9724 /// at the parity boundary. Byte-for-byte peer of
9725 /// `calm_is_monotone_matches_point_peer_through_lowered_classification`
9726 /// on the analog closed-set axis via the same resolver-hop shape.
9727 #[test]
9728 fn direction_prefers_lower_matches_point_peer_through_lowered_classification() {
9729 // Absent classification.
9730 let eph = empty_ephemeral();
9731 let lowered: ProcessSpec = eph.clone().into();
9732 assert_eq!(
9733 eph.direction_prefers_lower(),
9734 lowered.classification.direction_prefers_lower(),
9735 "None-classification parity drift",
9736 );
9737 // Authored classification.
9738 for populated in OptimizationDirection::ALL {
9739 let mut classification = Classification::gate_compute();
9740 classification.horizon.direction = Some(populated);
9741 let mut eph = empty_ephemeral();
9742 eph.classification = Some(classification);
9743 let lowered: ProcessSpec = eph.clone().into();
9744 assert_eq!(
9745 eph.direction_prefers_lower(),
9746 lowered.classification.direction_prefers_lower(),
9747 "authored horizon.direction={populated:?}: parity drift",
9748 );
9749 }
9750 }
9751
9752 // ── EphemeralSpec::direction_prefers_higher pins ────────────────
9753 //
9754 // Fail-before-pass-after granularity: `direction_prefers_higher`
9755 // did not exist pre-lift on `impl EphemeralSpec` — the positive
9756 // higher-is-better framing peer of
9757 // [`Self::direction_prefers_lower`] had no ephemeral-surface
9758 // substrate owner. Post-lift the FIFTEENTH derived-nullary-boolean
9759 // peer on the ephemeral surface (SECOND on the optimization-
9760 // direction axis, CLOSING the SIXTH classification axis into a
9761 // binary XOR partition on this surface) routes through the SAME
9762 // [`Self::resolved_classification`] resolver + the sibling
9763 // substrate primitive
9764 // [`crate::classification::Classification::direction_prefers_higher`],
9765 // so the two-surface parity contract holds by construction, AND
9766 // the two-way lower/higher split on this surface CLOSES the
9767 // optimization-direction axis into the FULL binary XOR partition
9768 // contract via
9769 // `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
9770
9771 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9772 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
9773 /// answers [`Self::direction_prefers_higher`] matching the closed
9774 /// set's own
9775 /// [`crate::classification::OptimizationDirection::prefers_higher`]
9776 /// truth table. Sweep
9777 /// [`crate::classification::OptimizationDirection::ALL`] so a
9778 /// regression that (a) hard-coded the body to a fixed answer,
9779 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
9780 /// hop, or (d) crossed the wires with a sibling classification-
9781 /// axis probe fails HERE at the substrate primitive before
9782 /// drifting through the `prefers-higher-direction` fixed tag or
9783 /// the peer point surface.
9784 #[test]
9785 fn direction_prefers_higher_returns_direction_projection_per_kind() {
9786 for populated in OptimizationDirection::ALL {
9787 let mut classification = Classification::gate_compute();
9788 classification.horizon.direction = Some(populated);
9789 let mut spec = empty_ephemeral();
9790 spec.classification = Some(classification);
9791 assert_eq!(
9792 spec.direction_prefers_higher(),
9793 populated.prefers_higher(),
9794 "authored horizon.direction={populated:?}: direction_prefers_higher() drift",
9795 );
9796 }
9797 }
9798
9799 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9800 /// with `classification: None` routes through the
9801 /// [`Self::resolved_classification`] resolver's substrate default
9802 /// [`Classification::gate_compute`], which carries
9803 /// `horizon: Horizon::default()` whose `direction` field is `None`,
9804 /// so `unwrap_or_default()` defaults to
9805 /// [`crate::classification::OptimizationDirection::Minimize`] via
9806 /// `#[default]`, and `Minimize.prefers_higher()` projects `false`,
9807 /// so [`Self::direction_prefers_higher`] returns `false`. Pins
9808 /// the resolver's default-arm short-circuit through THREE layers
9809 /// of `Default` ([`Classification::gate_compute`] →
9810 /// [`crate::classification::Horizon::default`] with `direction:
9811 /// None` → [`crate::classification::OptimizationDirection::default =
9812 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
9813 /// every unadorned `(defephemeral …)` reads UNDER the lower-is-
9814 /// better polarity default (safe under the asymptotic-health
9815 /// rate-window evaluator convention: an operator must
9816 /// deliberately opt into Maximize polarity). Mirror-inverted from
9817 /// the sibling `direction_prefers_lower_probes_true_on_absent_classification`
9818 /// baseline on the same resolver walk.
9819 #[test]
9820 fn direction_prefers_higher_probes_false_on_absent_classification() {
9821 let spec = empty_ephemeral();
9822 assert!(spec.classification.is_none());
9823 assert!(
9824 !spec.direction_prefers_higher(),
9825 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_higher=false)",
9826 );
9827 }
9828
9829 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9830 /// identically through [`Self::direction_prefers_higher`] AND
9831 /// through
9832 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_higher()`
9833 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9834 /// classification, `Some(_)` classification on every
9835 /// [`crate::classification::OptimizationDirection::ALL`] variant)
9836 /// so a future regression on either side of the resolver fails
9837 /// HERE at the parity boundary. Byte-for-byte peer of
9838 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
9839 /// on the antisymmetric closed-set arm via the same resolver-hop
9840 /// shape.
9841 #[test]
9842 fn direction_prefers_higher_matches_point_peer_through_lowered_classification() {
9843 // Absent classification.
9844 let eph = empty_ephemeral();
9845 let lowered: ProcessSpec = eph.clone().into();
9846 assert_eq!(
9847 eph.direction_prefers_higher(),
9848 lowered.classification.direction_prefers_higher(),
9849 "None-classification parity drift",
9850 );
9851 // Authored classification.
9852 for populated in OptimizationDirection::ALL {
9853 let mut classification = Classification::gate_compute();
9854 classification.horizon.direction = Some(populated);
9855 let mut eph = empty_ephemeral();
9856 eph.classification = Some(classification);
9857 let lowered: ProcessSpec = eph.clone().into();
9858 assert_eq!(
9859 eph.direction_prefers_higher(),
9860 lowered.classification.direction_prefers_higher(),
9861 "authored horizon.direction={populated:?}: parity drift",
9862 );
9863 }
9864 }
9865
9866 /// BINARY XOR PARTITION pin — for the absent-classification
9867 /// baseline AND every
9868 /// [`crate::classification::OptimizationDirection::ALL`] variant,
9869 /// EXACTLY ONE of [`Self::direction_prefers_lower`] and
9870 /// [`Self::direction_prefers_higher`] returns `true`. CLOSES the
9871 /// optimization-direction axis into the FULL binary XOR partition
9872 /// contract on the ephemeral surface — the resolver-hop peer of
9873 /// the parent-composed
9874 /// `classification_direction_probes_form_binary_xor_partition_over_all`
9875 /// test. Binary counterpart of the ternary XOR partitions sealed
9876 /// on the sibling `point_type` and `substrate` axes by
9877 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
9878 /// and
9879 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
9880 /// structural twin of the calm/data binary partitions
9881 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all` and
9882 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
9883 /// This pin is the SIXTH (and final) classification axis to reach
9884 /// the closed XOR partition landmark on the ephemeral resolver-
9885 /// hop surface — ALL SIX classification axes (horizon, calm,
9886 /// data, point, substrate, optimization-direction) now have
9887 /// their partitions closed on the ephemeral surface at this
9888 /// corner. Guarantees the absent-classification case lands in
9889 /// the definite lower-is-better bucket (`gate_compute` →
9890 /// Horizon::default → direction: None →
9891 /// OptimizationDirection::default = Minimize → prefers_lower =
9892 /// true, prefers_higher = false), so every unadorned
9893 /// `(defephemeral …)` audits under a definite non-empty polarity
9894 /// bucket.
9895 #[test]
9896 fn ephemeral_direction_probes_form_binary_xor_partition_over_all() {
9897 // Absent classification.
9898 let eph = empty_ephemeral();
9899 let buckets = [
9900 eph.direction_prefers_lower(),
9901 eph.direction_prefers_higher(),
9902 ];
9903 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9904 assert_eq!(
9905 hits, 1,
9906 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9907 );
9908 // Authored classification.
9909 for populated in OptimizationDirection::ALL {
9910 let mut classification = Classification::gate_compute();
9911 classification.horizon.direction = Some(populated);
9912 let mut eph = empty_ephemeral();
9913 eph.classification = Some(classification);
9914 let buckets = [
9915 eph.direction_prefers_lower(),
9916 eph.direction_prefers_higher(),
9917 ];
9918 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
9919 assert_eq!(
9920 hits, 1,
9921 "authored horizon.direction={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
9922 );
9923 }
9924 }
9925
9926 // ── EphemeralSpec::input_arity_is_one pins ──────────────────────
9927 //
9928 // Fail-before-pass-after granularity: `input_arity_is_one` did not
9929 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9930 // the "does this ephemeral spec's DAG-composition input port
9931 // accept a single upstream edge?" question went through
9932 // `.resolved_classification().point_type.input_arity().is_one()`.
9933 // Post-lift the SIXTEENTH derived-nullary-boolean peer on the
9934 // ephemeral surface (FIRST on the input-arity axis, opening the
9935 // SEVENTH classification axis into the fixed-tag algebra + the
9936 // derived-typed-projection stratum on this surface for the first
9937 // time) routes through the SAME [`Self::resolved_classification`]
9938 // resolver + the sibling substrate primitive
9939 // [`crate::classification::Classification::input_arity_is_one`],
9940 // so the two-surface parity contract holds by construction.
9941
9942 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9943 /// [`Classification`] carries `point_type: kind` answers
9944 /// [`Self::input_arity_is_one`] matching the closed set's own
9945 /// [`crate::classification::ConvergencePointType::input_arity`]
9946 /// truth table projected through [`Arity::is_one`]. Sweep
9947 /// [`crate::classification::ConvergencePointType::ALL`] so a
9948 /// regression that (a) hard-coded the body to a fixed answer,
9949 /// (b) inverted the projection, (c) dropped the resolver hop, or
9950 /// (d) crossed the wires with the sibling `output_arity`
9951 /// projection (which disagrees on six of eight variants) fails
9952 /// HERE at the substrate primitive before drifting through the
9953 /// future `single-input-arity` fixed tag or the peer point
9954 /// surface.
9955 #[test]
9956 fn input_arity_is_one_returns_input_arity_projection_per_kind() {
9957 for populated in ConvergencePointType::ALL {
9958 let mut classification = Classification::gate_compute();
9959 classification.point_type = populated;
9960 let mut spec = empty_ephemeral();
9961 spec.classification = Some(classification);
9962 assert_eq!(
9963 spec.input_arity_is_one(),
9964 populated.input_arity().is_one(),
9965 "authored point_type={populated:?}: input_arity_is_one() drift",
9966 );
9967 }
9968 }
9969
9970 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9971 /// with `classification: None` routes through the
9972 /// [`Self::resolved_classification`] resolver's substrate default
9973 /// [`Classification::gate_compute`], which carries `point_type:
9974 /// Gate` and `Gate.input_arity() = Many`, so
9975 /// [`Self::input_arity_is_one`] returns `false`. Pins the
9976 /// resolver's default-arm short-circuit reaching this derived-
9977 /// nullary predicate — every unadorned `(defephemeral …)` lands
9978 /// in the multi-input bucket under the substrate default. Mirror-
9979 /// inverted from the sibling `input_arity_is_many` baseline on
9980 /// the same resolver walk (the XOR partition forces exactly one
9981 /// bucket per baseline).
9982 #[test]
9983 fn input_arity_is_one_probes_false_on_absent_classification() {
9984 let spec = empty_ephemeral();
9985 assert!(spec.classification.is_none());
9986 assert!(
9987 !spec.input_arity_is_one(),
9988 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_one=false)",
9989 );
9990 }
9991
9992 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9993 /// identically through [`Self::input_arity_is_one`] AND through
9994 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_one()`
9995 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9996 /// classification, `Some(_)` classification on every
9997 /// [`crate::classification::ConvergencePointType::ALL`] variant)
9998 /// so a future regression on either side of the resolver fails
9999 /// HERE at the parity boundary. Byte-for-byte peer of
10000 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
10001 /// on the same resolver-hop shape.
10002 #[test]
10003 fn input_arity_is_one_matches_point_peer_through_lowered_classification() {
10004 // Absent classification.
10005 let eph = empty_ephemeral();
10006 let lowered: ProcessSpec = eph.clone().into();
10007 assert_eq!(
10008 eph.input_arity_is_one(),
10009 lowered.classification.input_arity_is_one(),
10010 "None-classification parity drift",
10011 );
10012 // Authored classification.
10013 for populated in ConvergencePointType::ALL {
10014 let mut classification = Classification::gate_compute();
10015 classification.point_type = populated;
10016 let mut eph = empty_ephemeral();
10017 eph.classification = Some(classification);
10018 let lowered: ProcessSpec = eph.clone().into();
10019 assert_eq!(
10020 eph.input_arity_is_one(),
10021 lowered.classification.input_arity_is_one(),
10022 "authored point_type={populated:?}: parity drift",
10023 );
10024 }
10025 }
10026
10027 // ── EphemeralSpec::input_arity_is_many pins ─────────────────────
10028 //
10029 // Fail-before-pass-after granularity: `input_arity_is_many` did
10030 // not exist pre-lift on `impl EphemeralSpec` — the multi-input
10031 // framing peer of [`Self::input_arity_is_one`] had no ephemeral-
10032 // surface substrate owner. Post-lift the SEVENTEENTH derived-
10033 // nullary-boolean peer on the ephemeral surface (SECOND on the
10034 // input-arity axis, CLOSING the SEVENTH classification axis into
10035 // a binary XOR partition on this surface) routes through the SAME
10036 // [`Self::resolved_classification`] resolver + the sibling
10037 // substrate primitive
10038 // [`crate::classification::Classification::input_arity_is_many`],
10039 // so the two-surface parity contract holds by construction, AND
10040 // the two-way single/many split on this surface CLOSES the
10041 // input-arity axis into the FULL binary XOR partition contract
10042 // via `ephemeral_input_arity_probes_form_binary_xor_partition_over_all`.
10043
10044 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10045 /// [`Classification`] carries `point_type: kind` answers
10046 /// [`Self::input_arity_is_many`] matching the closed set's own
10047 /// [`crate::classification::ConvergencePointType::input_arity`]
10048 /// truth table projected through [`Arity::is_many`]. Sweep
10049 /// [`crate::classification::ConvergencePointType::ALL`] so a
10050 /// regression that (a) hard-coded the body to a fixed answer,
10051 /// (b) inverted the projection, (c) dropped the resolver hop, or
10052 /// (d) crossed the wires with the sibling `output_arity`
10053 /// projection fails HERE at the substrate primitive before
10054 /// drifting through the future `multi-input-arity` fixed tag or
10055 /// the peer point surface.
10056 #[test]
10057 fn input_arity_is_many_returns_input_arity_projection_per_kind() {
10058 for populated in ConvergencePointType::ALL {
10059 let mut classification = Classification::gate_compute();
10060 classification.point_type = populated;
10061 let mut spec = empty_ephemeral();
10062 spec.classification = Some(classification);
10063 assert_eq!(
10064 spec.input_arity_is_many(),
10065 populated.input_arity().is_many(),
10066 "authored point_type={populated:?}: input_arity_is_many() drift",
10067 );
10068 }
10069 }
10070
10071 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10072 /// with `classification: None` routes through the
10073 /// [`Self::resolved_classification`] resolver's substrate default
10074 /// [`Classification::gate_compute`], which carries `point_type:
10075 /// Gate` and `Gate.input_arity() = Many`, so
10076 /// [`Self::input_arity_is_many`] returns `true`. Pins the
10077 /// resolver's default-arm short-circuit reaching this derived-
10078 /// nullary predicate — every unadorned `(defephemeral …)` lands
10079 /// in the multi-input bucket under the substrate default. Mirror-
10080 /// inverted from the sibling `input_arity_is_one` baseline on
10081 /// the same resolver walk (the XOR partition forces exactly one
10082 /// bucket per baseline).
10083 #[test]
10084 fn input_arity_is_many_probes_true_on_absent_classification() {
10085 let spec = empty_ephemeral();
10086 assert!(spec.classification.is_none());
10087 assert!(
10088 spec.input_arity_is_many(),
10089 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_many=true)",
10090 );
10091 }
10092
10093 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10094 /// identically through [`Self::input_arity_is_many`] AND through
10095 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_many()`
10096 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10097 /// classification, `Some(_)` classification on every
10098 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10099 /// so a future regression on either side of the resolver fails
10100 /// HERE at the parity boundary. Byte-for-byte peer of
10101 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
10102 /// on the antisymmetric closed-set arm via the same resolver-hop
10103 /// shape.
10104 #[test]
10105 fn input_arity_is_many_matches_point_peer_through_lowered_classification() {
10106 // Absent classification.
10107 let eph = empty_ephemeral();
10108 let lowered: ProcessSpec = eph.clone().into();
10109 assert_eq!(
10110 eph.input_arity_is_many(),
10111 lowered.classification.input_arity_is_many(),
10112 "None-classification parity drift",
10113 );
10114 // Authored classification.
10115 for populated in ConvergencePointType::ALL {
10116 let mut classification = Classification::gate_compute();
10117 classification.point_type = populated;
10118 let mut eph = empty_ephemeral();
10119 eph.classification = Some(classification);
10120 let lowered: ProcessSpec = eph.clone().into();
10121 assert_eq!(
10122 eph.input_arity_is_many(),
10123 lowered.classification.input_arity_is_many(),
10124 "authored point_type={populated:?}: parity drift",
10125 );
10126 }
10127 }
10128
10129 /// BINARY XOR PARTITION pin — for the absent-classification
10130 /// baseline AND every
10131 /// [`crate::classification::ConvergencePointType::ALL`] variant,
10132 /// EXACTLY ONE of [`Self::input_arity_is_one`] and
10133 /// [`Self::input_arity_is_many`] returns `true`. CLOSES the
10134 /// input-arity axis into the FULL binary XOR partition contract
10135 /// on the ephemeral surface — the resolver-hop peer of the
10136 /// parent-composed
10137 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`
10138 /// test. Binary counterpart of the ternary XOR partitions sealed
10139 /// on the sibling `point_type` and `substrate` axes by
10140 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10141 /// and
10142 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10143 /// structural twin of the calm/data/direction binary partitions
10144 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
10145 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`,
10146 /// and
10147 /// `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
10148 /// This pin is the SEVENTH classification axis to reach the
10149 /// closed XOR partition landmark on the ephemeral resolver-hop
10150 /// surface — the FIRST closed axis on the derived-typed-
10151 /// projection stratum of this surface, opening the stratum beyond
10152 /// the six stored classification slots. Guarantees the absent-
10153 /// classification case lands in the definite multi-input bucket
10154 /// (`gate_compute` → point_type=Gate → input_arity=Many →
10155 /// is_one=false, is_many=true), so every unadorned
10156 /// `(defephemeral …)` audits under a definite non-empty input-
10157 /// arity bucket.
10158 #[test]
10159 fn ephemeral_input_arity_probes_form_binary_xor_partition_over_all() {
10160 // Absent classification.
10161 let eph = empty_ephemeral();
10162 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
10163 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10164 assert_eq!(
10165 hits, 1,
10166 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10167 );
10168 // Authored classification.
10169 for populated in ConvergencePointType::ALL {
10170 let mut classification = Classification::gate_compute();
10171 classification.point_type = populated;
10172 let mut eph = empty_ephemeral();
10173 eph.classification = Some(classification);
10174 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
10175 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10176 assert_eq!(
10177 hits, 1,
10178 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10179 );
10180 }
10181 }
10182
10183 // ── EphemeralSpec::output_arity_is_one pins ─────────────────────
10184 //
10185 // Fail-before-pass-after granularity: `output_arity_is_one` did not
10186 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10187 // the "does this ephemeral spec's DAG-composition output port emit
10188 // to a single downstream edge?" question went through
10189 // `.resolved_classification().point_type.output_arity().is_one()`.
10190 // Post-lift the EIGHTEENTH derived-nullary-boolean peer on the
10191 // ephemeral surface (FIRST on the output-arity axis, opening the
10192 // EIGHTH classification axis into the fixed-tag algebra + the
10193 // SECOND peer on the derived-typed-projection stratum after
10194 // [`Self::input_arity_is_one`]) routes through the SAME
10195 // [`Self::resolved_classification`] resolver + the sibling
10196 // substrate primitive
10197 // [`crate::classification::Classification::output_arity_is_one`],
10198 // so the two-surface parity contract holds by construction.
10199
10200 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10201 /// [`Classification`] carries `point_type: kind` answers
10202 /// [`Self::output_arity_is_one`] matching the closed set's own
10203 /// [`crate::classification::ConvergencePointType::output_arity`]
10204 /// truth table projected through [`Arity::is_one`]. Sweep
10205 /// [`crate::classification::ConvergencePointType::ALL`] so a
10206 /// regression that (a) hard-coded the body to a fixed answer,
10207 /// (b) inverted the projection, (c) dropped the resolver hop, or
10208 /// (d) crossed the wires with the sibling `input_arity`
10209 /// projection (which disagrees on six of eight variants) fails
10210 /// HERE at the substrate primitive before drifting through the
10211 /// future `single-output-arity` fixed tag or the peer point
10212 /// surface.
10213 #[test]
10214 fn output_arity_is_one_returns_output_arity_projection_per_kind() {
10215 for populated in ConvergencePointType::ALL {
10216 let mut classification = Classification::gate_compute();
10217 classification.point_type = populated;
10218 let mut spec = empty_ephemeral();
10219 spec.classification = Some(classification);
10220 assert_eq!(
10221 spec.output_arity_is_one(),
10222 populated.output_arity().is_one(),
10223 "authored point_type={populated:?}: output_arity_is_one() drift",
10224 );
10225 }
10226 }
10227
10228 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10229 /// with `classification: None` routes through the
10230 /// [`Self::resolved_classification`] resolver's substrate default
10231 /// [`Classification::gate_compute`], which carries `point_type:
10232 /// Gate` and `Gate.output_arity() = One`, so
10233 /// [`Self::output_arity_is_one`] returns `true`. Pins the
10234 /// resolver's default-arm short-circuit reaching this derived-
10235 /// nullary predicate — every unadorned `(defephemeral …)` lands
10236 /// in the single-output bucket under the substrate default.
10237 /// Mirror-inverted from the sibling `output_arity_is_many`
10238 /// baseline on the same resolver walk (the XOR partition forces
10239 /// exactly one bucket per baseline). Note the workspace-baseline
10240 /// answer FLIPS between the input-arity and output-arity axes on
10241 /// the exact same absent-classification baseline: the input-arity
10242 /// sibling `input_arity_is_one` answers `false`, but this
10243 /// output-arity peer answers `true` — direct evidence at the
10244 /// resolver-hop layer that the two axes carve the closed set
10245 /// into structurally different partitions.
10246 #[test]
10247 fn output_arity_is_one_probes_true_on_absent_classification() {
10248 let spec = empty_ephemeral();
10249 assert!(spec.classification.is_none());
10250 assert!(
10251 spec.output_arity_is_one(),
10252 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_one=true)",
10253 );
10254 }
10255
10256 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10257 /// identically through [`Self::output_arity_is_one`] AND through
10258 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_one()`
10259 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10260 /// classification, `Some(_)` classification on every
10261 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10262 /// so a future regression on either side of the resolver fails
10263 /// HERE at the parity boundary. Byte-for-byte peer of
10264 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
10265 /// on the sibling output-arity projection via the same
10266 /// resolver-hop shape.
10267 #[test]
10268 fn output_arity_is_one_matches_point_peer_through_lowered_classification() {
10269 // Absent classification.
10270 let eph = empty_ephemeral();
10271 let lowered: ProcessSpec = eph.clone().into();
10272 assert_eq!(
10273 eph.output_arity_is_one(),
10274 lowered.classification.output_arity_is_one(),
10275 "None-classification parity drift",
10276 );
10277 // Authored classification.
10278 for populated in ConvergencePointType::ALL {
10279 let mut classification = Classification::gate_compute();
10280 classification.point_type = populated;
10281 let mut eph = empty_ephemeral();
10282 eph.classification = Some(classification);
10283 let lowered: ProcessSpec = eph.clone().into();
10284 assert_eq!(
10285 eph.output_arity_is_one(),
10286 lowered.classification.output_arity_is_one(),
10287 "authored point_type={populated:?}: parity drift",
10288 );
10289 }
10290 }
10291
10292 // ── EphemeralSpec::output_arity_is_many pins ────────────────────
10293 //
10294 // Fail-before-pass-after granularity: `output_arity_is_many` did
10295 // not exist pre-lift on `impl EphemeralSpec` — the multi-output
10296 // framing peer of [`Self::output_arity_is_one`] had no ephemeral-
10297 // surface substrate owner. Post-lift the NINETEENTH derived-
10298 // nullary-boolean peer on the ephemeral surface (SECOND on the
10299 // output-arity axis, CLOSING the EIGHTH classification axis into
10300 // a binary XOR partition on this surface) routes through the SAME
10301 // [`Self::resolved_classification`] resolver + the sibling
10302 // substrate primitive
10303 // [`crate::classification::Classification::output_arity_is_many`],
10304 // so the two-surface parity contract holds by construction, AND
10305 // the two-way single/many split on this surface CLOSES the
10306 // output-arity axis into the FULL binary XOR partition contract
10307 // via `ephemeral_output_arity_probes_form_binary_xor_partition_over_all`,
10308 // completing the DAG-composition arity PAIR on the ephemeral
10309 // derived-typed-projection stratum.
10310
10311 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10312 /// [`Classification`] carries `point_type: kind` answers
10313 /// [`Self::output_arity_is_many`] matching the closed set's own
10314 /// [`crate::classification::ConvergencePointType::output_arity`]
10315 /// truth table projected through [`Arity::is_many`]. Sweep
10316 /// [`crate::classification::ConvergencePointType::ALL`] so a
10317 /// regression that (a) hard-coded the body to a fixed answer,
10318 /// (b) inverted the projection, (c) dropped the resolver hop, or
10319 /// (d) crossed the wires with the sibling `input_arity`
10320 /// projection fails HERE at the substrate primitive before
10321 /// drifting through the future `multi-output-arity` fixed tag or
10322 /// the peer point surface.
10323 #[test]
10324 fn output_arity_is_many_returns_output_arity_projection_per_kind() {
10325 for populated in ConvergencePointType::ALL {
10326 let mut classification = Classification::gate_compute();
10327 classification.point_type = populated;
10328 let mut spec = empty_ephemeral();
10329 spec.classification = Some(classification);
10330 assert_eq!(
10331 spec.output_arity_is_many(),
10332 populated.output_arity().is_many(),
10333 "authored point_type={populated:?}: output_arity_is_many() drift",
10334 );
10335 }
10336 }
10337
10338 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10339 /// with `classification: None` routes through the
10340 /// [`Self::resolved_classification`] resolver's substrate default
10341 /// [`Classification::gate_compute`], which carries `point_type:
10342 /// Gate` and `Gate.output_arity() = One`, so
10343 /// [`Self::output_arity_is_many`] returns `false`. Pins the
10344 /// resolver's default-arm short-circuit reaching this derived-
10345 /// nullary predicate — every unadorned `(defephemeral …)` lands
10346 /// in the single-output bucket under the substrate default.
10347 /// Mirror-inverted from the sibling `output_arity_is_one`
10348 /// baseline on the same resolver walk (the XOR partition forces
10349 /// exactly one bucket per baseline).
10350 #[test]
10351 fn output_arity_is_many_probes_false_on_absent_classification() {
10352 let spec = empty_ephemeral();
10353 assert!(spec.classification.is_none());
10354 assert!(
10355 !spec.output_arity_is_many(),
10356 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_many=false)",
10357 );
10358 }
10359
10360 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10361 /// identically through [`Self::output_arity_is_many`] AND through
10362 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_many()`
10363 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10364 /// classification, `Some(_)` classification on every
10365 /// [`crate::classification::ConvergencePointType::ALL`] variant)
10366 /// so a future regression on either side of the resolver fails
10367 /// HERE at the parity boundary. Byte-for-byte peer of
10368 /// `output_arity_is_one_matches_point_peer_through_lowered_classification`
10369 /// on the antisymmetric closed-set arm via the same resolver-hop
10370 /// shape.
10371 #[test]
10372 fn output_arity_is_many_matches_point_peer_through_lowered_classification() {
10373 // Absent classification.
10374 let eph = empty_ephemeral();
10375 let lowered: ProcessSpec = eph.clone().into();
10376 assert_eq!(
10377 eph.output_arity_is_many(),
10378 lowered.classification.output_arity_is_many(),
10379 "None-classification parity drift",
10380 );
10381 // Authored classification.
10382 for populated in ConvergencePointType::ALL {
10383 let mut classification = Classification::gate_compute();
10384 classification.point_type = populated;
10385 let mut eph = empty_ephemeral();
10386 eph.classification = Some(classification);
10387 let lowered: ProcessSpec = eph.clone().into();
10388 assert_eq!(
10389 eph.output_arity_is_many(),
10390 lowered.classification.output_arity_is_many(),
10391 "authored point_type={populated:?}: parity drift",
10392 );
10393 }
10394 }
10395
10396 /// BINARY XOR PARTITION pin — for the absent-classification
10397 /// baseline AND every
10398 /// [`crate::classification::ConvergencePointType::ALL`] variant,
10399 /// EXACTLY ONE of [`Self::output_arity_is_one`] and
10400 /// [`Self::output_arity_is_many`] returns `true`. CLOSES the
10401 /// output-arity axis into the FULL binary XOR partition contract
10402 /// on the ephemeral surface — the resolver-hop peer of the
10403 /// parent-composed
10404 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`
10405 /// test. Binary counterpart of the ternary XOR partitions sealed
10406 /// on the sibling `point_type` and `substrate` axes by
10407 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10408 /// and
10409 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10410 /// structural twin of the calm/data/direction/input-arity binary
10411 /// partitions on this surface. This pin is the EIGHTH
10412 /// classification axis to reach the closed XOR partition landmark
10413 /// on the ephemeral resolver-hop surface — the SECOND closed axis
10414 /// on the derived-typed-projection stratum of this surface,
10415 /// completing the DAG-composition arity PAIR on the ephemeral
10416 /// stratum after the input-arity closure. Guarantees the absent-
10417 /// classification case lands in the definite single-output bucket
10418 /// (`gate_compute` → point_type=Gate → output_arity=One →
10419 /// is_one=true, is_many=false), so every unadorned
10420 /// `(defephemeral …)` audits under a definite non-empty
10421 /// output-arity bucket.
10422 #[test]
10423 fn ephemeral_output_arity_probes_form_binary_xor_partition_over_all() {
10424 // Absent classification.
10425 let eph = empty_ephemeral();
10426 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
10427 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10428 assert_eq!(
10429 hits, 1,
10430 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10431 );
10432 // Authored classification.
10433 for populated in ConvergencePointType::ALL {
10434 let mut classification = Classification::gate_compute();
10435 classification.point_type = populated;
10436 let mut eph = empty_ephemeral();
10437 eph.classification = Some(classification);
10438 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
10439 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10440 assert_eq!(
10441 hits, 1,
10442 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10443 );
10444 }
10445 }
10446
10447 /// BINARY XOR PARTITION pin — for the absent-classification
10448 /// baseline AND every
10449 /// [`crate::classification::HorizonKind::ALL`] variant, EXACTLY
10450 /// ONE of [`Self::horizon_terminates`] and
10451 /// [`Self::horizon_requires_metric_axes`] returns `true`. CLOSES
10452 /// the horizon axis into the FULL binary XOR partition contract
10453 /// on the ephemeral surface — the resolver-hop peer of the
10454 /// parent-composed
10455 /// `classification_horizon_probes_form_binary_xor_partition_over_all`
10456 /// test. Binary counterpart of the ternary XOR partitions sealed
10457 /// on the sibling `point_type` and `substrate` axes by
10458 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
10459 /// and
10460 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
10461 /// structural twin of the calm/data binary partitions
10462 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`
10463 /// and
10464 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
10465 /// This pin is the FIFTH (and final) classification axis to reach
10466 /// the closed XOR partition landmark on the ephemeral resolver-
10467 /// hop surface, sealing every classification axis under the
10468 /// SAME `hits == 1` bucket-array contract. Guarantees the absent-
10469 /// classification case lands in the definite terminating bucket
10470 /// (`gate_compute` → HorizonKind::Bounded → terminates = true,
10471 /// requires_metric_axes = false), so every unadorned
10472 /// `(defephemeral …)` audits under a definite non-empty horizon
10473 /// bucket. Rewritten from the earlier binary-XOR-only form
10474 /// (walked as `a ^ b`) into the canonical bucket-array shape
10475 /// shared with the calm/data partitions.
10476 #[test]
10477 fn ephemeral_horizon_probes_form_binary_xor_partition_over_all() {
10478 // Absent classification.
10479 let eph = empty_ephemeral();
10480 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
10481 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10482 assert_eq!(
10483 hits, 1,
10484 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10485 );
10486 // Authored classification.
10487 for populated in HorizonKind::ALL {
10488 let classification = Classification::gate_compute_with_axis(populated);
10489 let mut eph = empty_ephemeral();
10490 eph.classification = Some(classification);
10491 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
10492 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10493 assert_eq!(
10494 hits, 1,
10495 "authored horizon.kind={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
10496 );
10497 }
10498 }
10499
10500 // ── EphemeralSpec::has_routing_form pins ─────────────────────────
10501 //
10502 // Fail-before-pass-after granularity: `has_routing_form` did not
10503 // exist pre-lift on `impl EphemeralSpec` — the point-surface
10504 // `routing-form-<kind>` prefix family in tatara-check routed
10505 // through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`
10506 // inline, so the ephemeral surface had no matching primitive to
10507 // publish the SAME `routing-form-<kind>` prefix family through
10508 // the `strip_and_classify_prefixed_kind` substrate. Post-lift the
10509 // Option-gated derived-scalar-child probe body lives at ONE
10510 // inherent site on [`EphemeralSpec`] and every consumer (this
10511 // module's peer-symmetry tests, tatara-check's ephemeral
10512 // require-tag classifier, any future audit dispatcher walking
10513 // [`RoutingForm::ALL`] over the ephemeral surface) binds through
10514 // the SAME `has_routing_form(kind)` shape.
10515
10516 fn routing_spec(is_stable: bool) -> RoutingSpec {
10517 use crate::routing::{RoutingBackend, RoutingHostname};
10518 RoutingSpec {
10519 hostnames: vec![RoutingHostname::content_hashed("api")],
10520 backend: RoutingBackend::plain("svc", 80),
10521 stable_name_claim: is_stable,
10522 priority: 0,
10523 }
10524 }
10525
10526 /// POPULATED-slot pin — a populated `routing` slot answers `true`
10527 /// exactly for the [`RoutingForm`] variant its
10528 /// [`RoutingSpec::has_form`] derived-scalar arm agrees with, and
10529 /// `false` for every other variant. Sweep the two-boolean × ALL
10530 /// cross so a regression that (a) hard-coded the arm to a single
10531 /// variant, (b) dropped the Option-parent gate (silently reading
10532 /// through `.unwrap_or_default()` on an absent routing slot), or
10533 /// (c) crossed the wires from
10534 /// [`RoutingForm::from_is_stable`] to a fixed variant fails
10535 /// HERE before landing at the operator-facing checks.lisp
10536 /// surface.
10537 #[test]
10538 fn has_routing_form_returns_true_iff_populated_routing_derives_form_per_kind() {
10539 for is_stable in [true, false] {
10540 let populated = RoutingForm::from_is_stable(is_stable);
10541 let mut spec = empty_ephemeral();
10542 spec.routing = Some(routing_spec(is_stable));
10543 for query in RoutingForm::ALL {
10544 let expected = query == populated;
10545 assert_eq!(
10546 spec.has_routing_form(query),
10547 expected,
10548 "ephemeral routing.stable_name_claim={is_stable} (derives {populated:?}): query {query:?} drifted",
10549 );
10550 }
10551 }
10552 }
10553
10554 /// OPTION-PARENT SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
10555 /// `routing` slot is `None` returns `false` for every
10556 /// [`RoutingForm`] variant, INCLUDING the closed set's
10557 /// derived-default [`RoutingForm::Instance`]. Locks the
10558 /// Option-parent silencing contract so a regression that dropped
10559 /// the `spec.routing.as_ref()` gate (silently probing an absent
10560 /// routing slot as if it carried the defaulted `Instance` form)
10561 /// fails HERE. Peer to
10562 /// [`evaluate_point_require_tag_returns_false_on_absent_routing_for_every_routing_form_kind`]
10563 /// on the point surface — the two-surface symmetry means both
10564 /// classifiers publish the SAME Option-parent silencing at ONE
10565 /// substrate site per surface.
10566 #[test]
10567 fn has_routing_form_returns_false_on_absent_routing_for_every_kind() {
10568 let spec = empty_ephemeral();
10569 assert!(spec.routing.is_none());
10570 for kind in RoutingForm::ALL {
10571 assert!(
10572 !spec.has_routing_form(kind),
10573 "absent ephemeral routing must return false for {kind:?}",
10574 );
10575 }
10576 }
10577
10578 /// DEFAULT-ARM SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
10579 /// `routing` slot is a [`RoutingSpec`] with `stable_name_claim`
10580 /// at its `#[serde(default)]` (bool default = `false`) answers
10581 /// `true` on [`RoutingForm::Instance`] and `false` on every other
10582 /// variant WITHOUT the operator naming the routing-form axis on
10583 /// the routing spec. Peer to
10584 /// [`evaluate_point_require_tag_returns_true_on_default_routing_form_for_instance_only`]
10585 /// on the point surface — both surfaces read the derived-child
10586 /// arm through the ONE substrate composer
10587 /// [`RoutingForm::from_is_stable`], so a future normalization at
10588 /// the derivation lands at ONE site and every downstream
10589 /// (routing-form require-tag families on both surfaces,
10590 /// closed-set audit dispatchers) picks it up mechanically.
10591 #[test]
10592 fn has_routing_form_probes_instance_only_on_default_populated_routing() {
10593 let mut spec = empty_ephemeral();
10594 spec.routing = Some(routing_spec(bool::default()));
10595 for kind in RoutingForm::ALL {
10596 let expected = kind == RoutingForm::Instance;
10597 assert_eq!(
10598 spec.has_routing_form(kind),
10599 expected,
10600 "default-populated ephemeral routing (stable_name_claim=false → Instance) baseline: query {kind:?} must be {expected}",
10601 );
10602 }
10603 }
10604
10605 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
10606 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
10607 /// answer identically on every [`RoutingForm`] × `is_stable`
10608 /// combination. Locks the byte-for-byte parity between
10609 /// [`EphemeralSpec::has_routing_form`] (this new primitive) and
10610 /// the point surface's `spec.routing.as_ref().is_some_and(|r|
10611 /// r.has_form(k))` inline projection at the tatara-check dispatch
10612 /// site. A regression that (a) diverged the ephemeral probe from
10613 /// the lowered point probe (e.g., dropped the Option-parent gate
10614 /// on ONE side, crossed the derived-child arm on the OTHER), or
10615 /// (b) diverged the `From<EphemeralSpec>` lowering's
10616 /// `routing: e.routing` copy from byte-for-byte forwarding, fails
10617 /// HERE at the two-surface boundary.
10618 #[test]
10619 fn has_routing_form_matches_point_peer_through_lowered_routing() {
10620 for is_stable in [true, false] {
10621 let mut authored = empty_ephemeral();
10622 authored.routing = Some(routing_spec(is_stable));
10623 let lowered: ProcessSpec = authored.clone().into();
10624 for kind in RoutingForm::ALL {
10625 let ephemeral_answer = authored.has_routing_form(kind);
10626 let point_answer = lowered.routing.as_ref().is_some_and(|r| r.has_form(kind));
10627 assert_eq!(
10628 ephemeral_answer, point_answer,
10629 "two-surface routing-form parity drift: stable_name_claim={is_stable}, kind={kind:?}",
10630 );
10631 }
10632 }
10633 }
10634
10635 // ── EphemeralSpec::has_applicable_exports_at substrate pins ───────
10636 //
10637 // Fail-before-pass-after granularity: `has_applicable_exports_at`
10638 // did not exist pre-lift on `impl EphemeralSpec` — the peer
10639 // `EphemeralLifetime::has_applicable_exports` on the lowered
10640 // `ProcessSpec` surface routed through the compound
10641 // `.iter().any(|e| e.when.fires_on(phase))` chain inline, so the
10642 // sugar surface had no matching primitive to publish an
10643 // `exports-fire-on-<phase>` prefix family through the
10644 // `strip_and_classify_prefixed_kind` substrate. Post-lift the
10645 // compound-`(when, phase) → fires_on(phase)` probe body lives at
10646 // ONE slice-level substrate site (`ExportSpecSliceExt::has_applicable_at`),
10647 // this ephemeral surface routes through it directly, and the
10648 // point surface reaches the same primitive through
10649 // `spec.lifetime.resolved_ephemeral().is_some_and(|e|
10650 // e.exports.has_applicable_at(phase))`.
10651
10652 fn export_at(when: crate::export::ExportTrigger) -> ExportSpec {
10653 use crate::export::{ArtifactSource, ReceiptsSource, StdoutChannel, VectorChannel};
10654 ExportSpec {
10655 source: ArtifactSource {
10656 receipts: Some(ReceiptsSource::default()),
10657 ..ArtifactSource::default()
10658 },
10659 channel: VectorChannel {
10660 stdout: Some(StdoutChannel::default()),
10661 ..VectorChannel::default()
10662 },
10663 when,
10664 experiment_id_override: None,
10665 }
10666 }
10667
10668 /// EMPTY-EXPORTS pin — an ephemeral spec with an empty `exports`
10669 /// vec returns `false` for EVERY [`ProcessPhase`]. Sweep
10670 /// [`ProcessPhase::ALL`] so a new variant added without a matching
10671 /// arm in [`crate::export::ExportTrigger::fires_on`] surfaces at
10672 /// rustc's exhaustiveness gate on the `ALL` literal (arity forced
10673 /// by `[Self; 11]`) rather than as a silent false-positive at
10674 /// every downstream `exports-fire-on-<phase>` ephemeral require-tag
10675 /// callsite.
10676 #[test]
10677 fn has_applicable_exports_at_returns_false_on_empty_exports_for_every_phase() {
10678 let spec = empty_ephemeral();
10679 assert!(spec.exports.is_empty());
10680 for phase in ProcessPhase::ALL {
10681 assert!(
10682 !spec.has_applicable_exports_at(phase),
10683 "empty-exports ephemeral must return false for {phase:?}",
10684 );
10685 }
10686 }
10687
10688 /// PER-TRIGGER × PER-PHASE pin — an ephemeral spec with a single
10689 /// export answers `has_applicable_exports_at` identically to the
10690 /// [`crate::export::ExportTrigger::fires_on`] truth table on that
10691 /// (trigger, phase) pair, for every combination. Sweep the
10692 /// [`crate::export::ExportTrigger::ALL`] × [`ProcessPhase::ALL`]
10693 /// cross so a regression that (a) short-circuited to raw `when ==
10694 /// kind` equality, (b) missed `Always`'s dual-phase coverage, or
10695 /// (c) inverted a non-terminal phase to return `true` fails HERE
10696 /// at the substrate primitive rather than at each downstream
10697 /// `exports-fire-on-<phase>` classifier callsite.
10698 #[test]
10699 fn has_applicable_exports_at_matches_fires_on_truth_table_per_pair() {
10700 for trigger in crate::export::ExportTrigger::ALL {
10701 let mut spec = empty_ephemeral();
10702 spec.exports = vec![export_at(trigger)];
10703 for phase in ProcessPhase::ALL {
10704 let expected = trigger.fires_on(phase);
10705 assert_eq!(
10706 spec.has_applicable_exports_at(phase),
10707 expected,
10708 "ephemeral trigger={trigger:?} phase={phase:?} drifted from fires_on",
10709 );
10710 }
10711 }
10712 }
10713
10714 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
10715 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
10716 /// answer identically on every [`ProcessPhase`] × trigger
10717 /// combination. Locks the byte-for-byte parity between
10718 /// [`EphemeralSpec::has_applicable_exports_at`] (this new primitive)
10719 /// and the point surface's `spec.lifetime.resolved_ephemeral()
10720 /// .is_some_and(|e| e.exports.has_applicable_at(phase))` projection
10721 /// at the tatara-check dispatch site. A regression that (a)
10722 /// diverged the ephemeral probe from the lowered-lifetime probe,
10723 /// (b) diverged the `From<EphemeralSpec>` lowering's
10724 /// `exports: e.exports` copy from byte-for-byte forwarding, fails
10725 /// HERE at the two-surface boundary.
10726 #[test]
10727 fn has_applicable_exports_at_matches_point_peer_through_lowered_exports() {
10728 for trigger in crate::export::ExportTrigger::ALL {
10729 let mut authored = empty_ephemeral();
10730 authored.exports = vec![export_at(trigger)];
10731 let lowered: ProcessSpec = authored.clone().into();
10732 for phase in ProcessPhase::ALL {
10733 let ephemeral_answer = authored.has_applicable_exports_at(phase);
10734 let point_answer = lowered
10735 .lifetime
10736 .resolved_ephemeral()
10737 .is_some_and(|e| e.exports.has_applicable_at(phase));
10738 assert_eq!(
10739 ephemeral_answer, point_answer,
10740 "two-surface exports-fire-on parity drift: trigger={trigger:?}, phase={phase:?}",
10741 );
10742 }
10743 }
10744 }
10745}