Skip to main content

tatara_process/
crd.rs

1//! The `Process` CRD — `tatara.pleme.io/v1alpha1`.
2
3use chrono::{DateTime, Utc};
4use kube::CustomResource;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use tatara_lisp::DeriveTataraDomain;
8
9use crate::attestation::ProcessAttestation;
10use crate::boundary::Boundary;
11use crate::classification::Classification;
12use crate::compliance::ComplianceSpec;
13use crate::encapsulates::EncapsulatesSpec;
14use crate::identity::Identity;
15use crate::intent::Intent;
16use crate::lifetime::Lifetime;
17use crate::phase::ProcessPhase;
18use crate::routing::RoutingSpec;
19use crate::signal::ProcessSignal;
20use crate::spec::{DependsOn, IdentitySpec, SignalPolicy};
21use crate::status::{BoundaryStatus, ComplianceStatus, FluxResourceRef, ProcessCondition};
22
23/// Process — one element of the tatara convergence lattice, reconciled as a Unix process.
24///
25/// ```yaml
26/// apiVersion: tatara.pleme.io/v1alpha1
27/// kind: Process
28/// metadata:
29///   name: observability-stack
30///   namespace: seph
31/// spec:
32///   identity:
33///     parent: seph.1
34///   classification:
35///     pointType: Gate
36///     substrate: Observability
37///   intent:
38///     nix:
39///       flakeRef: github:pleme-io/k8s?dir=shared/infrastructure
40///       attribute: observability
41///   compliance:
42///     baseline: fedramp-moderate
43///     bindings:
44///       - framework: nist-800-53
45///         controlId: SC-7
46///         phase: AtBoundary
47///   dependsOn:
48///     - name: secret-injection
49/// ```
50#[derive(CustomResource, DeriveTataraDomain, Clone, Debug, Deserialize, Serialize, JsonSchema)]
51#[kube(
52    group = "tatara.pleme.io",
53    version = "v1alpha1",
54    kind = "Process",
55    plural = "processes",
56    shortname = "proc",
57    namespaced,
58    status = "ProcessStatus",
59    printcolumn = r#"{"name":"PID","type":"string","jsonPath":".status.pid"}"#,
60    printcolumn = r#"{"name":"Phase","type":"string","jsonPath":".status.phase"}"#,
61    printcolumn = r#"{"name":"Type","type":"string","jsonPath":".spec.classification.pointType"}"#,
62    printcolumn = r#"{"name":"Substrate","type":"string","jsonPath":".spec.classification.substrate"}"#,
63    printcolumn = r#"{"name":"Gen","type":"integer","jsonPath":".status.attestation.generation"}"#,
64    printcolumn = r#"{"name":"Age","type":"date","jsonPath":".metadata.creationTimestamp"}"#
65)]
66#[serde(rename_all = "camelCase")]
67#[tatara(keyword = "defpoint")]
68pub struct ProcessSpec {
69    /// Identity (parent, name override).
70    #[serde(default)]
71    pub identity: IdentitySpec,
72
73    /// Lattice position (6 dimensions).
74    pub classification: Classification,
75
76    /// Where rendered artifacts come from. Exactly one variant must be set.
77    pub intent: Intent,
78
79    /// Boundary predicates (preconditions / postconditions).
80    #[serde(default)]
81    pub boundary: Boundary,
82
83    /// Compliance bindings + baseline.
84    #[serde(default)]
85    pub compliance: ComplianceSpec,
86
87    /// Lattice dependencies — must reach phase before we proceed.
88    #[serde(default)]
89    pub depends_on: Vec<DependsOn>,
90
91    /// Signal policy (grace, SIGHUP strategy, start-suspended).
92    #[serde(default)]
93    pub signals: SignalPolicy,
94
95    /// Lifetime — `Permanent` (default, re-converging) or `Ephemeral`
96    /// (auto-SIGTERM per `teardown_policy` + TTL clock).
97    #[serde(default, skip_serializing_if = "Lifetime::is_default")]
98    pub lifetime: Lifetime,
99
100    /// External edges — DNS + Ingress. When `None`, the Process is
101    /// internal-only (matches today's default). See
102    /// [`crate::routing`] for the full shape.
103    #[serde(default, skip_serializing_if = "Option::is_none")]
104    pub routing: Option<RoutingSpec>,
105
106    /// Pre-existing in-cluster state this Process wraps. When `None`,
107    /// the Process is greenfield (Manage mode implicitly applied to
108    /// nothing pre-existing). See [`crate::encapsulates`] for the
109    /// three modes (Manage / Adopt / Observe).
110    #[serde(default, skip_serializing_if = "Option::is_none")]
111    pub encapsulates: Option<EncapsulatesSpec>,
112
113    /// Soft-suspend marker — reconciler treats as SIGSTOP.
114    /// Same effect as delivering SIGSTOP, but persistent across restarts.
115    #[serde(default)]
116    pub suspended: bool,
117}
118
119// Coordinate primitives — the `(namespace, name)` pair every downstream
120// composer (annotation writers, claim arbiter, boundary evaluator,
121// render owner-metadata seed) pulled by hand from `Process.metadata`
122// pre-lift, each restating the same two `Option<String>`-to-`&str`
123// unwrap incantations with the same two workspace-wide fallback
124// strings sprayed inline. Post-lift the pair lives at ONE substrate
125// primitive on `Process` — a future normalization (case-fold,
126// unicode-safe collation, cross-cluster prefix, a rename of either
127// fallback) lands here and every downstream composer inherits the
128// upgrade mechanically. Peer to `qualified_process_ref` in
129// `tatara-reconciler::ssapply`, whose two `&str` arguments are
130// exactly the pair `Process::coordinates_or_defaults` returns.
131impl Process {
132    /// The K8s canonical default namespace — the fallback every
133    /// consumer of a `Process` whose `metadata.namespace` is `None`
134    /// substitutes. Matches the string K8s itself substitutes on
135    /// namespaced resource writes with no explicit namespace.
136    pub const DEFAULT_NAMESPACE: &'static str = "default";
137
138    /// Workspace-wide fallback for a `Process`'s `metadata.name` when
139    /// it is `None` — the sentinel every annotation writer, claim
140    /// arbiter, and owner-metadata seed substitutes so downstream
141    /// grepping / label-selecting sees a stable spelling rather than
142    /// a per-callsite ad-hoc placeholder (`""`, `"<unnamed>"`, or the
143    /// empty `unwrap_or_default()` fallback). A Process authored
144    /// through the reconciler's fork path always has a name; this
145    /// constant covers the surface where an untyped `Process` value
146    /// (test fixture, dynamic API response, adopted resource pre-
147    /// name-resolution) surfaces without one.
148    pub const UNNAMED_PLACEHOLDER: &'static str = "unnamed";
149
150    /// Namespace slice with the [`Self::DEFAULT_NAMESPACE`] fallback
151    /// applied — the ONE-line collapse of the `metadata.namespace
152    /// .as_deref().unwrap_or("default")` incantation every consumer
153    /// spelled by hand pre-lift.
154    ///
155    /// Peer to [`Self::name_or_placeholder`] on the (metadata slot ×
156    /// fallback shape) axis; both compose through
157    /// [`Self::coordinates_or_defaults`] when a consumer needs the
158    /// pair together (annotation writers, claim-arbiter row builders,
159    /// render owner-metadata seed).
160    pub fn namespace_or_default(&self) -> &str {
161        self.metadata
162            .namespace
163            .as_deref()
164            .unwrap_or(Self::DEFAULT_NAMESPACE)
165    }
166
167    /// Name slice with the [`Self::UNNAMED_PLACEHOLDER`] fallback
168    /// applied — the ONE-line collapse of the `metadata.name.as_deref
169    /// ().unwrap_or("unnamed")` incantation every consumer spelled by
170    /// hand pre-lift.
171    ///
172    /// Peer to [`Self::namespace_or_default`] on the (metadata slot ×
173    /// fallback shape) axis; both compose through
174    /// [`Self::coordinates_or_defaults`] when a consumer needs the
175    /// pair together.
176    pub fn name_or_placeholder(&self) -> &str {
177        self.metadata
178            .name
179            .as_deref()
180            .unwrap_or(Self::UNNAMED_PLACEHOLDER)
181    }
182
183    /// `(namespace, name)` coordinates with the workspace-wide default
184    /// fallbacks applied — the ONE-line collapse of the paired
185    /// `metadata.namespace.as_deref().unwrap_or("default")` +
186    /// `metadata.name.as_deref().unwrap_or("unnamed")` extraction
187    /// every downstream composer restated by hand pre-lift.
188    ///
189    /// Return-tuple order matches the axis order of the substrate's
190    /// paired-composer primitive
191    /// `tatara_reconciler::ssapply::qualified_process_ref(ns, name)`:
192    /// the (namespace, name) pair this method returns feeds that
193    /// primitive positionally without an axis-swap step.
194    pub fn coordinates_or_defaults(&self) -> (&str, &str) {
195        (self.namespace_or_default(), self.name_or_placeholder())
196    }
197
198    /// `(namespace, name)` coordinates as owned `String`s, with the
199    /// namespace half fallback-defaulted to [`Self::DEFAULT_NAMESPACE`]
200    /// but the name half REQUIRED — an [`anyhow::Error`] is returned
201    /// when `metadata.name` is absent, because "unnamed" is a display
202    /// placeholder, not a valid K8s API path segment. Fed straight into
203    /// kube-rs API calls (`Api::patch`, `Api::delete`, `Api::get`) that
204    /// take owned `String` arguments; the [`Self::DEFAULT_NAMESPACE`]
205    /// fallback matches what K8s itself substitutes on namespaced
206    /// resource writes with no explicit namespace, so the surface is
207    /// safe against a `Process` whose `metadata.namespace` slot is
208    /// absent (test fixture, dynamic API response pre-defaulting) but
209    /// refuses to guess a name.
210    ///
211    /// Peer to [`Self::coordinates_or_defaults`] on the (return-form ×
212    /// name gate) axis pair:
213    /// * borrow + name-defaulted → `coordinates_or_defaults` (display,
214    ///   annotation writers, ownership-tag composers — every consumer
215    ///   whose downstream drops `"unnamed"` in place of a missing name
216    ///   without an operator-visible failure);
217    /// * owned + name-required → this method (kube-rs API calls —
218    ///   every consumer whose downstream must NOT silently substitute
219    ///   a placeholder for the API call target, because the caller is
220    ///   about to `patch`/`delete`/`get` at `metadata.name`).
221    ///
222    /// The error wording is pinned by
223    /// [`tests::owned_coordinates_or_err_error_message_matches_pre_lift_reconciler_wording`]
224    /// to match the exact spelling every pre-lift `tatara-reconciler`
225    /// helper produced (`"Process has no metadata.name"`) so log-line
226    /// / test greps that anchored on that wording keep matching post-
227    /// lift, and no operator-visible message drift lands as a side
228    /// effect of the substrate move.
229    pub fn owned_coordinates_or_err(&self) -> anyhow::Result<(String, String)> {
230        let ns = self
231            .metadata
232            .namespace
233            .clone()
234            .unwrap_or_else(|| Self::DEFAULT_NAMESPACE.into());
235        let name = self
236            .metadata
237            .name
238            .clone()
239            .ok_or_else(|| anyhow::anyhow!("Process has no metadata.name"))?;
240        Ok((ns, name))
241    }
242
243    /// `(namespace, name)` coordinates in the BORROW + NAME-REQUIRED
244    /// corner of the primitive family — namespace half falls back to
245    /// [`Self::DEFAULT_NAMESPACE`], but the name half is REQUIRED
246    /// (`None` on a `Process` whose `metadata.name` is absent, so the
247    /// caller stops with an `else { continue; }` / `else { return
248    /// …; }` guard rather than proceeding with the empty-string
249    /// sentinel every pre-lift consumer had to spell inline).
250    ///
251    /// Peer to [`Self::coordinates_or_defaults`] +
252    /// [`Self::owned_coordinates_or_err`] on the (return-form ×
253    /// name-gate) axis pair — closes the corner the family previously
254    /// left open:
255    ///
256    /// * borrow + name-defaulted → [`Self::coordinates_or_defaults`]
257    ///   (annotation writers, render owner-metadata seed — consumers
258    ///   whose downstream tolerates the `"unnamed"` display placeholder
259    ///   without operator-visible failure);
260    /// * borrow + name-required → **this method** (claim-arbiter
261    ///   probes, child-Process delete-fan-out — consumers that need a
262    ///   real API-path leaf and cleanly SKIP the row when the name is
263    ///   absent rather than issuing a K8s call with an empty-string
264    ///   name argument);
265    /// * owned + name-required → [`Self::owned_coordinates_or_err`]
266    ///   (kube-rs API-path calls — consumers whose downstream requires
267    ///   owned `String` arguments and rejects the missing-name corner
268    ///   with a load-bearing error message).
269    ///
270    /// The primitive family's `None`-on-missing-name semantics
271    /// intentionally differs from [`Self::owned_coordinates_or_err`]'s
272    /// error-on-missing-name semantics: the caller sites for this form
273    /// (child-Process fan-out, claim-arbiter row probes) are non-fatal
274    /// SKIPS rather than reportable failures — an `Option::None` at
275    /// the primitive lets the caller thread that "skip" through a
276    /// let-else without stringifying / logging an anyhow chain per
277    /// missing-name occurrence.
278    ///
279    /// The namespace fallback matches [`Self::coordinates_or_defaults`]
280    /// (via [`Self::namespace_or_default`]), so a consumer that
281    /// switches between the two borrow-form primitives based on its
282    /// name-gate need never sees a different namespace-fallback string
283    /// as a side effect.
284    pub fn coordinates_or_none(&self) -> Option<(&str, &str)> {
285        let name = self.metadata.name.as_deref()?;
286        Some((self.namespace_or_default(), name))
287    }
288
289    /// Borrowed lookup of ONE key in `metadata.annotations`, with
290    /// BOTH the missing-`annotations` corner AND the missing-key
291    /// corner collapsed to `None` — the ONE-liner collapse of the
292    /// paired `self.metadata.annotations.as_ref().and_then(|m|
293    /// m.get(key)).map(String::as_str)` incantation every consumer
294    /// restated by hand pre-lift.
295    ///
296    /// Pre-lift the 3-line `.metadata.annotations.as_ref().and_then
297    /// (|m| m.get(KEY))` chain (in three tail variants — `.cloned()`,
298    /// `.cloned().unwrap_or_default()`, `.map(String::as_str)`) was
299    /// hand-authored at THREE sites past the ★★ PRIME-DIRECTIVE ≥ 2
300    /// duplication threshold across the workspace:
301    /// * `tatara-reconciler::signals::ingest` — SIGNAL annotation
302    ///   lookup (pre-lift `.cloned()` for owned parsing).
303    /// * `tatara-reconciler::phase_machine::released_from_annotation`
304    ///   — RELEASED_FROM annotation lookup (pre-lift `.cloned()
305    ///   .unwrap_or_default()` for `match v.as_str()`).
306    /// * `tatara-pool-reconciler::controller_pool::process_belongs_to_pool`
307    ///   — POOL annotation lookup (pre-lift `.map(String::as_str)`
308    ///   for `== Some(pool_name)`).
309    ///
310    /// All THREE sites walked the SAME 3-line chain — read the
311    /// annotations map, gate on presence, index by key — differing
312    /// only in the tail that shaped the result. Post-lift each
313    /// caller routes through the ONE substrate primitive here and
314    /// applies its own tail at its own site (`.map(str::to_string)`
315    /// / bare match / `==`).
316    ///
317    /// Return-form axis: `Option<&str>` mirrors the existing borrow-
318    /// first discipline of the peer metadata primitives
319    /// [`Self::namespace_or_default`], [`Self::name_or_placeholder`],
320    /// [`Self::coordinates_or_none`]. The two corners the chain
321    /// swallowed pre-lift (missing `metadata.annotations` map,
322    /// missing key inside the map) BOTH collapse to `None` so
323    /// `.is_some()` / `if let Some(_)` / `Option::map` behave
324    /// identically on a `Process` whose annotations block is `None`
325    /// and on one whose annotations block is populated but omits the
326    /// key — matching what the pre-lift `.and_then(...)` chain
327    /// produced.
328    ///
329    /// A future normalization step (a key-canonicalization pass,
330    /// a case-fold lookup, a per-key alias table for renamed
331    /// annotations across API versions, a per-namespace override
332    /// substrate) lands at ONE substrate method here and all three
333    /// downstream consumers pick up the upgrade mechanically — no
334    /// per-callsite hand-edit at `ingest` / `released_from_annotation`
335    /// / `process_belongs_to_pool`.
336    ///
337    /// Sibling to the peer metadata primitives
338    /// ([`Self::namespace_or_default`], [`Self::name_or_placeholder`],
339    /// [`Self::coordinates_or_defaults`], [`Self::coordinates_or_none`],
340    /// [`Self::owned_coordinates_or_err`]) on the metadata axis;
341    /// this method opens the borrow-form peer on the ANNOTATION
342    /// axis. Future annotation projections (a paired
343    /// `label(&str) -> Option<&str>` on `metadata.labels`, a
344    /// `has_annotation(&str) -> bool` boolean gate for presence-
345    /// only consumers) land as peer methods on this same axis.
346    ///
347    /// Theory anchor: THEORY.md §VI.1 (generation over composition
348    /// — the 3-line annotation-lookup chain recurred at three
349    /// hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
350    /// duplication trigger, and is lifted to ONE owner here).
351    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
352    /// the pins bind the missing-`annotations` corner + the
353    /// missing-key corner + the borrow-form `&str` lifetime + the
354    /// byte-identical parity with the pre-lift 3-line chain, so a
355    /// regression that drifted any surface at
356    /// `tests::annotation_*` rather than as silent operator-facing
357    /// skew between the SIGNAL / RELEASED_FROM / POOL annotation
358    /// readers).
359    pub fn annotation(&self, key: &str) -> Option<&str> {
360        self.metadata
361            .annotations
362            .as_ref()
363            .and_then(|m| m.get(key))
364            .map(String::as_str)
365    }
366
367    /// Borrow-form metadata-projection primitive on the `metadata.uid`
368    /// axis: returns the K8s-API-server-assigned uid as a `&str`, with
369    /// the missing-uid corner collapsed to the load-bearing empty-string
370    /// sentinel — the ONE-liner collapse of the paired
371    /// `self.metadata.uid.as_deref().unwrap_or("")` incantation every
372    /// owner-reference-emitting consumer restated by hand pre-lift.
373    ///
374    /// The empty-string fallback is NOT arbitrary — it is the exact
375    /// sentinel value the sibling substrate composer
376    /// [`crate::owner_references_json`] gates on (`if uid.is_empty()
377    /// { vec![] } else { vec![owner_reference_json(name, uid)] }`) to
378    /// stamp `metadata.ownerReferences: []` on a resource whose owning
379    /// Process pre-dates the API server's `metadata.uid` assignment
380    /// (test fixture, mid-Forking snapshot before the first `patch`
381    /// round-trip, dynamic API response pre-uid-resolution). Pre-lift
382    /// each consumer spelled the fallback as `.unwrap_or("")` at its
383    /// callsite; the two literals in two files could drift silently to
384    /// `.unwrap_or_default()`, `.unwrap_or("<unknown>")`, or an
385    /// `if let Some(u) = &process.metadata.uid` gate that returned a
386    /// different owner-refs shape for the missing-uid corner. Post-lift
387    /// the sentinel value is composed at ONE substrate site so the
388    /// empty-uid gate at `owner_references_json` and its per-callsite
389    /// producers share the SAME `""` byte-string, and a rename of the
390    /// sentinel would land at ONE substrate site rather than at every
391    /// downstream `owner_references_json(name, uid)` call.
392    ///
393    /// Peer to [`Self::namespace_or_default`] +
394    /// [`Self::name_or_placeholder`] on the metadata-slot × fallback-
395    /// shape axis: `namespace_or_default` returns the K8s-canonical
396    /// `"default"` fallback (matching what the API server substitutes
397    /// on namespaced writes with no explicit namespace);
398    /// `name_or_placeholder` returns the workspace-wide `"unnamed"`
399    /// sentinel (a display placeholder for downstream grepping /
400    /// label-selecting); this method returns the empty-string sentinel
401    /// (a load-bearing gate value that composes with
402    /// [`crate::owner_references_json`]'s `is_empty` check). The three
403    /// primitives partition the metadata-slot family by whether the
404    /// consumer wants a K8s-canonical fallback (namespace), a display
405    /// placeholder (name), or a gate sentinel (uid).
406    ///
407    /// Pre-lift the `.metadata.uid.as_deref().unwrap_or("")` chain was
408    /// hand-authored at TWO sites past the ★★ PRIME-DIRECTIVE ≥ 2
409    /// duplication threshold in `tatara-reconciler::render`, both
410    /// feeding a downstream owner-reference emitter:
411    /// * `render_routing` — the routing-edge seed that binds
412    ///   `process_uid` into every routing-form `EdgeContext` (Ingress +
413    ///   DNSEndpoint) built inside the fanout loop over
414    ///   `RoutingSpec::hostnames`; each `Edge::render` impl then walks
415    ///   its `EdgeContext` through `build_owner_refs` →
416    ///   [`crate::owner_references_json`] to stamp
417    ///   `metadata.ownerReferences` on the emitted resource.
418    /// * `render_export_jobs` — the ephemeral-export Job builder that
419    ///   passes the same uid slice to `tatara_process::
420    ///   owner_references_json(name, uid)` per rendered Job, stamping
421    ///   the export-Job's `metadata.ownerReferences` back at the
422    ///   owning Process.
423    ///
424    /// Both sites walked the SAME `.as_deref().unwrap_or("")` chain and
425    /// both wanted the `&str` form the primitive returns — as the
426    /// second positional argument to `owner_references_json(name, uid)`
427    /// on the ownership-tag axis. Post-lift each callsite reads
428    /// `let uid = process.uid_or_empty();` and the produced slice feeds
429    /// the same downstream composer unchanged.
430    ///
431    /// Return-form axis: `&str` mirrors the existing borrow-first
432    /// discipline of the peer metadata-fallback primitives
433    /// ([`Self::namespace_or_default`], [`Self::name_or_placeholder`]);
434    /// all three return owned-metadata borrows with a slot-specific
435    /// fallback baked in so downstream consumers compose the slice
436    /// directly into their next call without re-spelling the fallback.
437    ///
438    /// A future normalization step (a canonicalization pass that
439    /// rejects a malformed uid before the owner-ref stamp, a cross-
440    /// cluster uid rewrite for multi-tenant control planes, a stale-
441    /// uid warning annotation for a Process whose uid changed under
442    /// the reconciler mid-generation) lands at ONE substrate method
443    /// here and both downstream `owner_references_json` consumers
444    /// pick up the upgrade mechanically — no per-callsite hand-edit
445    /// at `render_routing` / `render_export_jobs`.
446    ///
447    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
448    /// the `.metadata.uid.as_deref().unwrap_or("")` chain recurred at
449    /// two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
450    /// duplication trigger, and is lifted to ONE owner here).
451    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
452    /// the pins bind the missing-uid corner + the empty-string
453    /// sentinel byte-shape + the borrow-form `&str` lifetime + the
454    /// byte-identical parity with the pre-lift chain + the composition
455    /// coherence with [`crate::owner_references_json`]'s `is_empty`
456    /// gate, so a regression that drifted any surface at
457    /// `tests::uid_or_empty_*` rather than as silent operator-facing
458    /// skew between the two owner-reference emitters on the SAME
459    /// Process).
460    pub fn uid_or_empty(&self) -> &str {
461        self.metadata.uid.as_deref().unwrap_or("")
462    }
463
464    /// Owned-form metadata-projection primitive on the `metadata.name`
465    /// axis: returns an owned `String` copy of the K8s object name, with
466    /// the missing-name corner collapsed to the load-bearing empty-string
467    /// sentinel — the ONE-liner collapse of the paired
468    /// `self.metadata.name.clone().unwrap_or_default()` incantation every
469    /// keying / row-builder consumer restated by hand pre-lift.
470    ///
471    /// Pre-lift the `.metadata.name.clone().unwrap_or_default()` chain
472    /// was hand-authored at TWO sites past the ★★ PRIME-DIRECTIVE ≥ 2
473    /// duplication threshold in `tatara-pool-reconciler::controller_pool`,
474    /// both stamping the `PoolMember` / `PoolMemberSnapshot`
475    /// `process_name: String` slot inside a struct-literal fanout over
476    /// pool-owned `Process`es:
477    /// * `reconcile_pool`'s pool-member seed (annotation-matched Process
478    ///   list → `PoolMember { process_name, state, entered_state_at, .. }`)
479    ///   — the row every operator sees on the pool's status page.
480    /// * `reconcile_pool`'s desired-count snapshot seed
481    ///   (`PoolMemberSnapshot { process_name, phase, created_at }`)
482    ///   — the row fed into `decide_pool_convergence`.
483    ///
484    /// Both sites walked the SAME `.clone().unwrap_or_default()` chain
485    /// and both wanted the `String` form the primitive returns — as the
486    /// owned-form `process_name: String` slot on a struct literal
487    /// composed inside a `.iter().map(...)` fanout over the same
488    /// pool-owned `Process` list. Post-lift each callsite reads
489    /// `process_name: p.owned_name_or_empty()` and the produced value
490    /// feeds the same struct-literal slot unchanged.
491    ///
492    /// The empty-string fallback is the SAME sentinel the sibling
493    /// borrow-form primitive [`Self::uid_or_empty`] returns — the two
494    /// primitives partition the owned-form × borrow-form corner of the
495    /// metadata-slot family on identical fallback semantics (empty
496    /// string means "the slot is unset"), so a consumer that switches
497    /// between them based on downstream ownership requirements never
498    /// sees a different missing-slot spelling as a side effect.
499    ///
500    /// Peer to [`Self::name_or_placeholder`] on the (return-form ×
501    /// fallback-value) axis pair — closes the corner the family
502    /// previously left open:
503    ///
504    /// * borrow + display placeholder → [`Self::name_or_placeholder`]
505    ///   (log lines, annotation writers, ownership-tag composers —
506    ///   consumers whose downstream drops `"unnamed"` in place of a
507    ///   missing name without operator-visible failure);
508    /// * owned + empty sentinel → **this method** (row-builder /
509    ///   HashMap-key / struct-literal fanout consumers whose downstream
510    ///   fills a `String` field with the load-bearing `""` sentinel to
511    ///   flag "no name to key by" rather than substituting a display
512    ///   placeholder that would misalign a downstream lookup);
513    /// * owned + name-required → [`Self::owned_coordinates_or_err`] (kube-rs
514    ///   API-path calls — consumers whose downstream must NOT silently
515    ///   substitute a placeholder for the API call target).
516    ///
517    /// The primitive family's `""`-on-missing-name semantics
518    /// intentionally differs from [`Self::name_or_placeholder`]'s
519    /// `"unnamed"` semantics: the caller sites for this form (pool
520    /// membership row seeds, HashMap keys) are load-bearing keys — a
521    /// display placeholder like `"unnamed"` would silently alias every
522    /// missing-name Process to the same key, collapsing distinct rows
523    /// in the pool's member list. The empty-string sentinel keeps the
524    /// pre-lift byte-shape and lets downstream consumers gate on
525    /// `String::is_empty` if they need to filter the missing-name
526    /// corner explicitly.
527    ///
528    /// A future normalization step (a name-canonicalization pass, a
529    /// case-fold key builder, a per-pool alias table for renamed
530    /// Processes across generations) lands at ONE substrate method
531    /// here and both downstream `PoolMember` / `PoolMemberSnapshot`
532    /// seeds pick up the upgrade mechanically — no per-callsite hand-
533    /// edit at `reconcile_pool`.
534    ///
535    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
536    /// the `.metadata.name.clone().unwrap_or_default()` chain recurred
537    /// at two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
538    /// duplication trigger, and is lifted to ONE owner here).
539    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
540    /// the pins bind the missing-name corner + the empty-string
541    /// sentinel byte-shape + the owned-form `String` return type +
542    /// the byte-identical parity with the pre-lift chain + the
543    /// fallback-value coherence with the sibling [`Self::uid_or_empty`]
544    /// on the metadata-slot × empty-sentinel axis, so a regression
545    /// that drifted any surface at `tests::owned_name_or_empty_*`
546    /// rather than as silent operator-facing skew between the pool-
547    /// member seed and the desired-count snapshot seed on the SAME
548    /// pool).
549    pub fn owned_name_or_empty(&self) -> String {
550        self.metadata.name.clone().unwrap_or_default()
551    }
552
553    /// Borrow-form spec-projection primitive on the declared parent-PID
554    /// axis: returns the hierarchical PID path (e.g. `"seph.1"`) the
555    /// author declared at `spec.identity.parent`, with the empty-slot
556    /// corner collapsed to `None` — the ONE-liner collapse of the
557    /// paired `self.spec.identity.parent.as_deref()` incantation every
558    /// consumer restated by hand pre-lift.
559    ///
560    /// Pre-lift the `.spec.identity.parent.as_deref()` chain was hand-
561    /// authored at TWO sites past the ★★ PRIME-DIRECTIVE ≥ 2
562    /// duplication threshold in `tatara-reconciler::phase_machine`:
563    /// * `handle_forking` — the ALLOCATE-PID composer that threads the
564    ///   declared parent PID into [`pid::allocate_pid`] and also into
565    ///   the status patch payload (`{ "pid": new_pid, "parent":
566    ///   parent_pid }`), so the reconciler-observed
567    ///   [`ProcessStatus::parent`] slot mirrors the author-declared
568    ///   [`IdentitySpec::parent`] at fork time. The `info!` tracing
569    ///   span also reads the same slice as the `parent` field on the
570    ///   PID-assigned log line.
571    /// * `handle_exiting` — the SIGTERM cascade's child-fan-out filter
572    ///   that enumerates every Process cluster-wide and picks children
573    ///   whose `spec.identity.parent` equals this Process's currently-
574    ///   observed PID (`.filter(|c| c.spec.identity.parent.as_deref()
575    ///   == Some(pid))`). The filter runs per candidate child, so the
576    ///   borrow-form projection avoids allocating one `String` clone
577    ///   per non-matching row in the cluster-wide list.
578    ///
579    /// Both sites walked the SAME `.as_deref()` chain and both wanted
580    /// the `Option<&str>` form the primitive returns — the
581    /// `handle_forking` site to feed positionally into
582    /// `pid::allocate_pid(&identity, parent_pid, next_seq)` and the
583    /// tracing span's `parent = ?parent_pid` debug print + the JSON
584    /// payload's `"parent": parent_pid` slot; the `handle_exiting`
585    /// filter to compare directly against `Some(pid)` where `pid:
586    /// &str` came off the borrow-form peer [`Self::observed_pid`].
587    ///
588    /// Return-form axis: `Option<&str>` mirrors the borrow-first
589    /// discipline of every peer primitive on the metadata / status
590    /// slot family ([`Self::namespace_or_default`],
591    /// [`Self::name_or_placeholder`], [`Self::observed_pid`],
592    /// [`Self::annotation`]). The empty-slot corner
593    /// (`spec.identity.parent = None`, matching `init` / PID 1 with
594    /// no parent) collapses to `None` so `.is_some()` / `if let
595    /// Some(_)` / `.map(...)` behave identically on a `Process`
596    /// authored at cluster init (PID 1, parent absent) and on any
597    /// PID-N child (parent present) — matching the pre-lift
598    /// `.as_deref()` chain's `None` byte-identically.
599    ///
600    /// Peer to [`Self::observed_pid`] on the (spec-declared ×
601    /// status-observed) axis pair: `observed_pid` returns the PID
602    /// path this Process currently OWNS (the reconciler-persisted
603    /// child position in the hierarchy), while `declared_parent_pid`
604    /// returns the PID path this Process's parent OWNS (the author-
605    /// declared upstream position). The SIGTERM cascade at
606    /// `handle_exiting` composes both: it reads its own
607    /// [`Self::observed_pid`] and matches each candidate child's
608    /// [`Self::declared_parent_pid`] against that value — the child-
609    /// fan-out relation IS the spec-declared × status-observed axis
610    /// pair collapsed to a single comparator, both sides routed
611    /// through the same borrow-form skeleton.
612    ///
613    /// A future normalization step (a per-slot canonicalization pass
614    /// that rejects malformed hierarchical PIDs, a case-fold lookup
615    /// against a table of renamed identities, a cross-cluster prefix
616    /// stripper, an alias-table lookup that maps a legacy PID to its
617    /// current spelling) lands at ONE substrate method here and both
618    /// downstream consumers pick up the upgrade mechanically — no
619    /// per-callsite hand-edit at `handle_forking` / `handle_exiting`.
620    ///
621    /// Sibling to the peer metadata-projection primitives
622    /// ([`Self::namespace_or_default`], [`Self::name_or_placeholder`],
623    /// [`Self::coordinates_or_defaults`], [`Self::coordinates_or_none`],
624    /// [`Self::owned_coordinates_or_err`], [`Self::annotation`]) on the
625    /// metadata axis; this method opens the borrow-form peer on the
626    /// declared-identity axis. Future identity projections
627    /// (`declared_name_override` on the `spec.identity.name_override`
628    /// axis, a paired `declared_identity` composite that returns both
629    /// halves) land as peer methods on this same axis.
630    ///
631    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
632    /// the `.spec.identity.parent.as_deref()` chain recurred at two
633    /// hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
634    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
635    /// invariant 5 (composition preserves proofs — the pins bind the
636    /// empty-slot corner + the borrow-form `&str` lifetime + the
637    /// byte-identical parity with the pre-lift `.as_deref()` chain,
638    /// so a regression that drifted any surface at
639    /// `tests::declared_parent_pid_*` rather than as silent operator-
640    /// facing skew between the ALLOCATE-PID composer and the SIGTERM
641    /// cascade's child-fan-out filter on the SAME parent-child pair).
642    pub fn declared_parent_pid(&self) -> Option<&str> {
643        self.spec.identity.parent.as_deref()
644    }
645
646    /// Borrow-form spec-projection primitive on the declared
647    /// name-override axis: returns the human name the author declared
648    /// at `spec.identity.name_override` (used verbatim instead of the
649    /// content-hash-derived name in [`derive_identity`]), with the
650    /// empty-slot corner collapsed to `None` — the ONE-liner collapse
651    /// of the paired `self.spec.identity.name_override.as_deref()`
652    /// incantation every consumer restated by hand pre-lift.
653    ///
654    /// Pre-lift the `.spec.identity.name_override.as_deref()` chain
655    /// was hand-authored at TWO sites past the ★★ PRIME-DIRECTIVE ≥ 2
656    /// duplication threshold in `tatara-reconciler::phase_machine`,
657    /// both feeding the second positional argument of
658    /// [`derive_identity`]:
659    /// * `handle_pending` — the DECLARE composer that computes the
660    ///   Process's [`Identity`] on entry to the state machine (before
661    ///   `patch::phase_status` writes it into `status.identity`).
662    /// * `handle_forking` — the ALLOCATE-PID composer that recomputes
663    ///   the same [`Identity`] on a rehydration path (status may
664    ///   already carry an identity from a prior reconcile, in which
665    ///   case the `.and_then(|s| s.identity.clone())` short-circuit
666    ///   takes it; otherwise this `.unwrap_or_else` branch fires and
667    ///   recomputes the identity fresh from the spec) so `pid::
668    ///   allocate_pid` sees the SAME [`Identity`] the DECLARE phase
669    ///   produced.
670    ///
671    /// Both sites walked the SAME `.as_deref()` chain and both wanted
672    /// the `Option<&str>` form the primitive returns — as the second
673    /// positional argument to `derive_identity(&self.spec, …)`, which
674    /// internally trims + filters empty strings + dispatches on
675    /// `Some(non_empty)` (verbatim name, `name_override: true`) vs
676    /// `None | Some(empty | whitespace)` (content-hash-derived name,
677    /// `name_override: false`). The primitive itself preserves the
678    /// raw slot byte-identically (the trim happens IN
679    /// `derive_identity`, not at the borrow site), so the two live
680    /// paths compose through the SAME borrow-form skeleton.
681    ///
682    /// Return-form axis: `Option<&str>` mirrors the borrow-first
683    /// discipline of every peer primitive on the metadata / status /
684    /// spec-identity slot family ([`Self::namespace_or_default`],
685    /// [`Self::name_or_placeholder`], [`Self::observed_pid`],
686    /// [`Self::annotation`], [`Self::declared_parent_pid`]). The
687    /// empty-slot corner (`spec.identity.name_override = None`,
688    /// matching a Process authored WITHOUT the human-name-override
689    /// escape hatch — the default; `derive_identity` then computes
690    /// the name from the content hash) collapses to `None` so
691    /// `.is_some()` / `if let Some(_)` / `.map(...)` behave
692    /// identically on the two Process shapes an operator can author.
693    ///
694    /// Peer to [`Self::declared_parent_pid`] on the (parent × name-
695    /// override) sub-axis of the declared-identity axis: both
696    /// primitives project a `Option<String>` slot on `IdentitySpec`
697    /// through the SAME borrow-form skeleton, so a future
698    /// `declared_identity` composite that returns both halves
699    /// together (e.g. as a `(Option<&str>, Option<&str>)` tuple or a
700    /// borrow-form `DeclaredIdentityView<'_>` newtype) lands as ONE
701    /// method that COMPOSES the two peer primitives, not as three
702    /// hand-authored `.as_deref()` chains restated at each callsite.
703    ///
704    /// A future normalization step (a per-slot canonicalization pass
705    /// that rejects malformed names, a case-fold lookup against a
706    /// table of renamed identities, an alias-table lookup that maps
707    /// a legacy name-override to its current spelling, a whitespace-
708    /// trim lift OUT of `derive_identity` INTO the primitive so both
709    /// consumers see the trimmed form) lands at ONE substrate method
710    /// here and both downstream consumers pick up the upgrade
711    /// mechanically — no per-callsite hand-edit at `handle_pending` /
712    /// `handle_forking`.
713    ///
714    /// Sibling to the peer spec-identity projection
715    /// [`Self::declared_parent_pid`] on the declared-identity axis;
716    /// this method opens the borrow-form peer on the name-override
717    /// sub-axis of the same closed set (`IdentitySpec { parent,
718    /// name_override }`). Future identity projections (a paired
719    /// `declared_identity` composite that returns both halves
720    /// together) land as peer methods on this same axis.
721    ///
722    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
723    /// the `.spec.identity.name_override.as_deref()` chain recurred
724    /// at two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
725    /// duplication trigger, and is lifted to ONE owner here).
726    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
727    /// the pins bind the empty-slot corner + the borrow-form `&str`
728    /// lifetime + the byte-identical parity with the pre-lift
729    /// `.as_deref()` chain + the invariance under
730    /// [`derive_identity`]'s internal trim/filter step, so a
731    /// regression that drifted any surface at
732    /// `tests::declared_name_override_*` rather than as silent
733    /// operator-facing skew between the DECLARE composer and the
734    /// ALLOCATE-PID rehydration branch on the SAME Process spec).
735    pub fn declared_name_override(&self) -> Option<&str> {
736        self.spec.identity.name_override.as_deref()
737    }
738
739    /// Borrowed slice of the FluxCD resources this Process's status
740    /// currently persists at `status.flux_resources`, with the
741    /// missing-`status` corner collapsed to an empty slice — the ONE-
742    /// line collapse of the paired `self.status.as_ref().map(|s|
743    /// s.flux_resources.clone()).unwrap_or_default()` incantation
744    /// every VERIFY-phase / ATTEST-heartbeat consumer restated by hand
745    /// pre-lift.
746    ///
747    /// Pre-lift the 5-line `.status.as_ref().map(|s| s.flux_resources
748    /// .clone()).unwrap_or_default()` chain was hand-authored at TWO
749    /// sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold in
750    /// `tatara-reconciler::phase_machine`:
751    /// * `handle_running` — the VERIFY-phase per-ref readiness probe
752    ///   seed that walks every ref through
753    ///   [`crate::status::FluxResourceRef::fetch_coords`] via
754    ///   `ssapply::fetch_flux_ref` and rebuilds an updated
755    ///   `Vec<FluxResourceRef>` with `ready` + `message` + `last_check`
756    ///   observed at reconcile time.
757    /// * `handle_attested` — the ATTEST-heartbeat drift detector that
758    ///   short-circuits on the first non-Ready ref via
759    ///   `ssapply::fetch_flux_ref` + `ssapply::ready_condition`.
760    ///
761    /// Both sites walked the SAME 5-line chain — clone the vector
762    /// eagerly for the length of the reconcile pass, then iterate it
763    /// by reference — even though neither site ever mutates the vector
764    /// nor keeps it alive past the enclosing async fn. Post-lift both
765    /// callers borrow the slice directly from `self.status`; the two
766    /// pre-lift `.clone()` calls disappear because the slice lives for
767    /// the borrow of `&self`, and both call sites' subsequent
768    /// downstream calls (`ssapply::fetch_flux_ref` / the
769    /// `patch::patch_process_status` write) do not touch the borrowed
770    /// `p: &Process`, so the borrow lifetime holds.
771    ///
772    /// Return-form axis: `&[FluxResourceRef]` mirrors the existing
773    /// borrow-first discipline every pre-lift consumer already
774    /// iterated by reference (`for r in &refs`), and the shape of
775    /// [`crate::status::FluxResourceRef::fetch_coords`]'s per-ref
776    /// borrow projection extends mechanically to the slice-level
777    /// projection here. The missing-`status` corner collapses to the
778    /// empty slice `&[]` so `.is_empty()` / `.len()` / iteration all
779    /// behave identically on a `Process` whose status is `None` and
780    /// on one whose status carries an empty `flux_resources` slot —
781    /// matching what the pre-lift `.unwrap_or_default()` produced
782    /// (an empty `Vec`).
783    ///
784    /// A future normalization step (a per-ref canonicalization pass
785    /// that skips duplicated refs, an owner-filter that returns only
786    /// refs stamped with the CURRENT `metadata.generation`, a
787    /// staleness gate that drops refs whose `last_check` predates a
788    /// reconcile deadline) lands at ONE substrate method here and
789    /// both downstream consumers pick up the upgrade mechanically —
790    /// no per-callsite hand-edit at `handle_running` /
791    /// `handle_attested`.
792    ///
793    /// Sibling to the [`Self::coordinates_or_none`] borrow-first
794    /// primitive on the metadata axis; this method opens the
795    /// analogous borrow-first primitive on the status-projection
796    /// axis. Future status projections (`observed_attestation` on
797    /// the attestation-chain axis, `observed_pid` on the PID axis,
798    /// `observed_children` on the child-fan-out axis) land as peer
799    /// methods on this same axis.
800    ///
801    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
802    /// the 5-line status-projection chain recurred at two hand-
803    /// authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
804    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
805    /// invariant 5 (composition preserves proofs — the pins bind the
806    /// missing-`status` corner + the slice-lifetime borrow discipline
807    /// + the byte-identical parity with the pre-lift 5-line chain, so
808    /// a regression that drifted any of the three surfaces at
809    /// `tests::observed_flux_resources_*` rather than as silent
810    /// operator-facing skew between the VERIFY-phase and ATTEST-
811    /// heartbeat consumers).
812    pub fn observed_flux_resources(&self) -> &[FluxResourceRef] {
813        self.status
814            .as_ref()
815            .map(|s| s.flux_resources.as_slice())
816            .unwrap_or(&[])
817    }
818
819    /// The borrow-form status-projection primitive on the PID axis:
820    /// returns the hierarchical PID path (e.g. `"seph.1.7"`) the
821    /// reconciler currently persists at `status.pid`, with BOTH the
822    /// missing-`status` corner AND the empty-slot corner collapsed
823    /// to `None` — the ONE-liner collapse of the paired
824    /// `self.status.as_ref().and_then(|s| s.pid.clone())` incantation
825    /// every consumer restated by hand pre-lift.
826    ///
827    /// Pre-lift the 3-line `.status.as_ref().and_then(|s| s.pid
828    /// .clone())` chain was hand-authored at TWO sites past the ★★
829    /// PRIME-DIRECTIVE ≥ 2 duplication threshold in
830    /// `tatara-reconciler::phase_machine`:
831    /// * `handle_forking` — the ALLOCATE-PID gate that short-
832    ///   circuits the PID allocator when the reconciler already
833    ///   assigned a PID on a prior reconcile pass (pre-lift the
834    ///   chain composed with `.is_some()` and threw the clone away
835    ///   without ever reading the string).
836    /// * `handle_exiting` — the SIGTERM cascade that enumerates
837    ///   child Processes and terminates them by matching each
838    ///   child's `spec.identity.parent` against the PID this Process
839    ///   currently owns (pre-lift the chain bound an owned
840    ///   `Option<String>` and threaded `pid.as_str()` into the
841    ///   downstream `.as_deref() == Some(...)` comparator).
842    ///
843    /// Both sites walked the SAME 3-line chain — clone the `String`
844    /// eagerly, then either drop it (the `handle_forking` gate) or
845    /// re-borrow it through `.as_str()` (the `handle_exiting`
846    /// comparator) — even though neither site ever mutates the PID
847    /// nor keeps it alive past the enclosing async fn. Post-lift
848    /// both callers borrow the PID directly from `self.status`; the
849    /// pre-lift `.clone()` at both sites disappears because the
850    /// `&str` lives for the borrow of `&self`, and both call sites'
851    /// subsequent downstream calls (the K8s API list/patch, the
852    /// child-Process comparator) do not touch the borrowed
853    /// `p: &Process`, so the borrow lifetime holds.
854    ///
855    /// Return-form axis: `Option<&str>` mirrors the existing
856    /// borrow-first discipline every pre-lift consumer already
857    /// re-borrowed through `.as_str()` before use, and the shape of
858    /// [`Self::coordinates_or_none`]'s `Option<(&str, &str)>`
859    /// projection extends mechanically to the single-slot
860    /// projection here. The missing-`status` corner AND the
861    /// populated-status-with-`pid=None` corner BOTH collapse to
862    /// `None` so `.is_some()` / `if let Some(_)` / `.map(...)`
863    /// behave identically on a `Process` whose status is `None`
864    /// and on one whose status carries an unpopulated `pid` slot —
865    /// matching what the pre-lift `.and_then(...)` chain produced.
866    ///
867    /// A future normalization step (a per-slot canonicalization
868    /// pass that rejects malformed hierarchical PIDs, a
869    /// generation-filter that returns `None` for a PID stamped
870    /// with a stale `metadata.generation`, a staleness gate that
871    /// drops a PID whose observing `phase_since` predates a
872    /// reconcile deadline) lands at ONE substrate method here and
873    /// both downstream consumers pick up the upgrade mechanically
874    /// — no per-callsite hand-edit at `handle_forking` /
875    /// `handle_exiting`.
876    ///
877    /// Sibling to the peer [`Self::observed_flux_resources`]
878    /// borrow-first primitive on the flux-resources axis; both
879    /// methods compose the same missing-`status` fallback +
880    /// borrow-form return-shape skeleton on distinct
881    /// `ProcessStatus` slots. Future status projections
882    /// (`observed_parent` on the parent-pointer axis,
883    /// `observed_message` on the human-readable-status axis,
884    /// `observed_attestation` on the attestation-chain axis) land
885    /// as peer methods on this same axis.
886    ///
887    /// Theory anchor: THEORY.md §VI.1 (generation over
888    /// composition — the 3-line status-projection chain recurred
889    /// at two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
890    /// duplication trigger, and is lifted to ONE owner here).
891    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
892    /// the pins bind the missing-`status` corner + the empty-slot
893    /// corner + the borrow-form `&str` lifetime + the
894    /// byte-identical parity with the pre-lift 3-line chain, so a
895    /// regression that drifted any surface at
896    /// `tests::observed_pid_*` rather than as silent operator-
897    /// facing skew between the ALLOCATE-PID gate and the SIGTERM
898    /// cascade on the SAME `Process`).
899    pub fn observed_pid(&self) -> Option<&str> {
900        self.status.as_ref().and_then(|s| s.pid.as_deref())
901    }
902
903    /// The borrow-form status-projection primitive on the
904    /// attestation-chain axis: returns the last
905    /// [`ProcessAttestation`] the reconciler persisted at
906    /// `status.attestation`, with the missing-`status` corner AND the
907    /// empty-slot corner BOTH collapsed to `None` — the ONE-liner
908    /// collapse of the paired `self.status.as_ref().and_then(|s|
909    /// s.attestation.as_ref())` incantation every consumer restated
910    /// by hand pre-lift.
911    ///
912    /// Pre-lift the 3-line `.status.as_ref().and_then(|s| s
913    /// .attestation.as_ref())` chain was hand-authored at TWO sites
914    /// past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold in
915    /// `tatara-reconciler`:
916    /// * `phase_machine::advance_to_attested` — the ATTEST composer
917    ///   that chains `prior.next(pillars)` when a prior attestation
918    ///   is persisted and seeds with `ProcessAttestation::initial`
919    ///   otherwise.
920    /// * `render::render_export_jobs` — the ephemeral-export Job
921    ///   builder that pulls the prior `composed_root` off the last
922    ///   persisted attestation and threads it into every rendered
923    ///   Job's `previousRoot` env var, so the export receipt chains
924    ///   into the Process's BLAKE3 attestation tree at the correct
925    ///   generation boundary.
926    ///
927    /// Both sites walked the SAME 3-line chain — the borrow-form
928    /// `Option<&ProcessAttestation>` shape both consumers wanted
929    /// already — even though neither site ever mutated the
930    /// attestation nor kept it alive past the enclosing async fn.
931    /// Post-lift both callers borrow the attestation directly from
932    /// `self.status`; the pre-lift 3-line chain shrinks to a single
933    /// method call at both sites, and both consumers' subsequent
934    /// downstream calls (`ProcessAttestation::next` for the ATTEST
935    /// composer, `.composed_root.clone()` for the export Job builder)
936    /// do not touch the borrowed `p: &Process`, so the borrow
937    /// lifetime holds.
938    ///
939    /// Return-form axis: `Option<&ProcessAttestation>` mirrors the
940    /// existing borrow-first discipline every pre-lift consumer
941    /// already re-borrowed through `.as_ref()`, and the shape of the
942    /// peer [`Self::observed_pid`] projection extends mechanically
943    /// to the whole-attestation-record projection here. The missing-
944    /// `status` corner AND the populated-status-with-`attestation
945    /// =None` corner BOTH collapse to `None` so `.is_some()` / `if
946    /// let Some(_)` / `.map(...)` behave identically on a `Process`
947    /// whose status is `None` and on one whose status carries an
948    /// unpopulated `attestation` slot — matching what the pre-lift
949    /// `.and_then(...)` chain produced.
950    ///
951    /// A future normalization step (a per-slot canonicalization pass
952    /// that rejects a persisted attestation whose `composed_root`
953    /// fails `verify`, a generation-filter that returns `None` for
954    /// an attestation stamped with a stale `metadata.generation`, a
955    /// staleness gate that drops an attestation whose `attested_at`
956    /// predates a reconcile deadline) lands at ONE substrate method
957    /// here and both downstream consumers pick up the upgrade
958    /// mechanically — no per-callsite hand-edit at
959    /// `advance_to_attested` / `render_export_jobs`.
960    ///
961    /// Sibling to the peer [`Self::observed_pid`] +
962    /// [`Self::observed_flux_resources`] borrow-first primitives on
963    /// the PID + flux-resources axes; all three methods compose the
964    /// same missing-`status` fallback + borrow-form return-shape
965    /// skeleton on distinct `ProcessStatus` slots. Future status
966    /// projections (`observed_parent` on the parent-pointer axis,
967    /// `observed_message` on the human-readable-status axis) land
968    /// as peer methods on this same axis.
969    ///
970    /// Theory anchor: THEORY.md §VI.1 (generation over composition
971    /// — the 3-line status-projection chain recurred at two hand-
972    /// authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
973    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
974    /// invariant 5 (composition preserves proofs — the pins bind
975    /// the missing-`status` corner + the empty-slot corner + the
976    /// borrow-form `&ProcessAttestation` lifetime + the byte-
977    /// identical parity with the pre-lift 3-line chain, so a
978    /// regression that drifted any surface at
979    /// `tests::observed_attestation_*` rather than as silent
980    /// operator-facing skew between the ATTEST composer and the
981    /// ephemeral-export receipt chain on the SAME `Process`).
982    pub fn observed_attestation(&self) -> Option<&ProcessAttestation> {
983        self.status.as_ref().and_then(|s| s.attestation.as_ref())
984    }
985
986    /// The borrow-form status-projection primitive on the resolved-
987    /// identity axis: returns the [`Identity`] the reconciler
988    /// currently persists at `status.identity` (name + content hash +
989    /// override flag), with the missing-`status` corner AND the
990    /// empty-slot corner BOTH collapsed to `None` — the ONE-liner
991    /// collapse of the paired `self.status.as_ref().and_then(|s|
992    /// s.identity.as_ref())` incantation every consumer restated by
993    /// hand pre-lift.
994    ///
995    /// Pre-lift the paired `.status.as_ref().and_then(|s|
996    /// s.identity.<clone|as_ref>())` chain was hand-authored at TWO
997    /// sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold
998    /// in `tatara-reconciler`:
999    /// * `phase_machine::handle_forking` — the FORK-time identity
1000    ///   seed that reuses the reconciler-persisted `Identity` if
1001    ///   present and falls back to a fresh `derive_identity(&spec,
1002    ///   name_override)` otherwise. Pre-lift the site cloned the
1003    ///   whole `Identity` off the borrow before threading it through
1004    ///   `.unwrap_or_else(...)` even though the fallback path
1005    ///   allocates its own owned `Identity` — the pre-lift clone
1006    ///   allocated a fresh `Identity` on the happy path just so the
1007    ///   `Option`'s shape matched the fallback's `Identity` return
1008    ///   type.
1009    /// * `ssapply::inject_annotations` — the SSA-time annotation
1010    ///   composer that stamps the content-hash annotation onto every
1011    ///   owned resource. Pre-lift the site nested the identity
1012    ///   borrow-form check inside a manual `if let Some(status) =
1013    ///   &process.status { … }` guard alongside sibling `status.pid`
1014    ///   and `status.attestation` accesses — three siblings the peer
1015    ///   primitives [`Self::observed_pid`] and
1016    ///   [`Self::observed_attestation`] already own, so the outer
1017    ///   status guard was the last hand-authored `.status.as_ref()`
1018    ///   destructure at this composer.
1019    ///
1020    /// Both sites walked the SAME 3-line chain (one via `.clone()`,
1021    /// one via `.as_ref()`) — the borrow-form
1022    /// `Option<&Identity>` shape both consumers wanted already, even
1023    /// though the FORK-time seed then had to `.clone()` off the
1024    /// borrow to compose with the owned-`Identity` fallback. Post-
1025    /// lift the seed calls `.observed_identity().cloned()` at the
1026    /// exact composition point where the owned value is required
1027    /// (the empty-borrow corner clones nothing, since
1028    /// `Option::cloned` on `None` is `None`), and the SSA-time
1029    /// consumer drops the outer status guard entirely — the
1030    /// three-sibling primitive family (pid + identity + attestation)
1031    /// now peers through `observed_pid` +
1032    /// `observed_identity` + `observed_attestation` at ONE call each
1033    /// with no shared status destructure between them.
1034    ///
1035    /// Return-form axis: `Option<&Identity>` mirrors the
1036    /// existing borrow-first discipline every pre-lift consumer
1037    /// already re-borrowed through `.as_ref()` / re-cloned through
1038    /// `.clone()`, and the shape of the peer
1039    /// [`Self::observed_attestation`] projection extends
1040    /// mechanically to the whole-`Identity`-record projection here.
1041    /// The missing-`status` corner AND the populated-status-with-
1042    /// `identity=None` corner BOTH collapse to `None` so
1043    /// `.is_some()` / `if let Some(_)` / `.map(...)` behave
1044    /// identically on a `Process` whose status is `None` and on one
1045    /// whose status carries an unpopulated `identity` slot —
1046    /// matching what the pre-lift `.and_then(...)` chain produced.
1047    ///
1048    /// A future normalization step (a per-slot canonicalization
1049    /// pass that rejects an `Identity` whose `content_hash` fails
1050    /// re-derivation against the current spec, a generation-filter
1051    /// that returns `None` for an identity stamped with a stale
1052    /// `metadata.generation`, a staleness gate that drops an
1053    /// identity whose observing `phase_since` predates a reconcile
1054    /// deadline) lands at ONE substrate method here and both
1055    /// downstream consumers pick up the upgrade mechanically — no
1056    /// per-callsite hand-edit at `handle_forking` /
1057    /// `inject_annotations`.
1058    ///
1059    /// Sibling to the peer [`Self::observed_pid`] +
1060    /// [`Self::observed_attestation`] +
1061    /// [`Self::observed_flux_resources`] borrow-first primitives on
1062    /// the PID + attestation-chain + flux-resources axes; all four
1063    /// methods compose the same missing-`status` fallback +
1064    /// borrow-form return-shape skeleton on distinct `ProcessStatus`
1065    /// slots. Future status projections (`observed_parent` on the
1066    /// parent-pointer axis, `observed_message` on the human-
1067    /// readable-status axis) land as peer methods on this same
1068    /// axis.
1069    ///
1070    /// Theory anchor: THEORY.md §VI.1 (generation over composition
1071    /// — the 3-line status-projection chain recurred at two hand-
1072    /// authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication
1073    /// trigger, and is lifted to ONE owner here). THEORY.md §II.1
1074    /// invariant 5 (composition preserves proofs — the pins bind
1075    /// the missing-`status` corner + the empty-slot corner + the
1076    /// borrow-form `&Identity` lifetime + the byte-identical parity
1077    /// with the pre-lift 3-line chain, so a regression that drifted
1078    /// any surface at `tests::observed_identity_*` rather than as
1079    /// silent operator-facing skew between the FORK-time identity
1080    /// seed and the SSA-time content-hash annotation stamp on the
1081    /// SAME `Process`).
1082    pub fn observed_identity(&self) -> Option<&Identity> {
1083        self.status.as_ref().and_then(|s| s.identity.as_ref())
1084    }
1085
1086    /// The copy-form status-projection primitive on the phase axis:
1087    /// returns the [`ProcessPhase`] the reconciler currently persists
1088    /// at `status.phase`, wrapped in an `Option` so the missing-
1089    /// `status` corner collapses to `None` — the ONE-liner collapse
1090    /// of the paired `self.status.as_ref().map(|s| s.phase)`
1091    /// incantation every consumer restated by hand pre-lift.
1092    ///
1093    /// Peer to the borrow-form projections
1094    /// [`Self::observed_pid`] (PID axis, `Option<&str>`),
1095    /// [`Self::observed_flux_resources`] (flux-resources axis,
1096    /// `&[FluxResourceRef]`), and [`Self::observed_attestation`]
1097    /// (attestation-chain axis, `Option<&ProcessAttestation>`); this
1098    /// method opens the copy-form peer for `ProcessPhase` — a
1099    /// `Copy` scalar with a `Default` impl (`Pending`), so the
1100    /// return is `Option<ProcessPhase>` rather than
1101    /// `Option<&ProcessPhase>` (borrow would give the caller
1102    /// nothing over the copy for a 1-byte enum) and neither the
1103    /// missing-`status` corner nor a "empty slot" corner is
1104    /// meaningful — the underlying slot is a bare `ProcessPhase`,
1105    /// not `Option<ProcessPhase>`, so the primitive returns `None`
1106    /// iff `status: None`.
1107    ///
1108    /// Pre-lift the 3-line `.status.as_ref().map(|s| s.phase)`
1109    /// chain was hand-authored at FIVE sites past the ★★
1110    /// PRIME-DIRECTIVE ≥ 2 duplication threshold in
1111    /// `tatara-reconciler`:
1112    /// * `controller::reconcile` — the top-level dispatcher's
1113    ///   `current_phase` seed that feeds the deletion-preempt +
1114    ///   signal-ingestion gates + the per-phase handler dispatch.
1115    ///   Pre-lift `.unwrap_or(ProcessPhase::Pending)`.
1116    /// * `boundary::evaluate_process_phase` — the boundary
1117    ///   evaluator's `ProcessPhase` condition (a peer-Process
1118    ///   `phase`-reached postcondition). Pre-lift
1119    ///   `.unwrap_or(ProcessPhase::Pending)`.
1120    /// * `boundary::check_depends_on` — the `depends_on`
1121    ///   pre-condition audit that stashes the observed phase into
1122    ///   the `UnmetDependency::actual: Option<ProcessPhase>` slot
1123    ///   (keeps the `Option` form). Pre-lift the raw
1124    ///   `.map(|s| s.phase)` shape.
1125    /// * `phase_machine::p_current_phase_str` — the released-from
1126    ///   annotation composer that emits `"Attested"` for every
1127    ///   non-`Failed` phase (SIGSTOP/SIGCONT release gate).
1128    ///   Pre-lift `.unwrap_or(ProcessPhase::Attested)` — the ONE
1129    ///   site whose default is not `Pending`; the primitive
1130    ///   returns the raw `Option` so the caller's `.unwrap_or`
1131    ///   default choice stays local rather than baked in.
1132    /// * `table_controller::stable_name_group_key` — the routing-
1133    ///   groupby seed that pairs the phase with the PID + creation
1134    ///   timestamp when partitioning Processes claiming the same
1135    ///   stable name. Pre-lift `.unwrap_or(ProcessPhase::Pending)`.
1136    ///
1137    /// All FIVE sites walked the SAME 3-line `.status.as_ref()
1138    /// .map(|s| s.phase)` chain — three closed with `unwrap_or
1139    /// (ProcessPhase::Pending)` (the `Default`), one closed with
1140    /// `unwrap_or(ProcessPhase::Attested)`, one kept the raw
1141    /// `Option<ProcessPhase>` — so the ONE substrate accessor
1142    /// returns the raw `Option<ProcessPhase>` and each consumer
1143    /// keeps its `.unwrap_or(...)` default choice at its own site.
1144    ///
1145    /// A future normalization step (a generation-filter that
1146    /// returns `None` for a phase stamped with a stale
1147    /// `metadata.generation`, a staleness gate that drops a phase
1148    /// whose observing `phase_since` predates a reconcile
1149    /// deadline, a canonicalization pass that maps a phase that
1150    /// no longer belongs to the CRD's closed set to `None`) lands
1151    /// at ONE substrate method here and all five consumers pick
1152    /// up the upgrade mechanically — no per-callsite hand-edit at
1153    /// `reconcile` / `evaluate_process_phase` / `check_depends_on`
1154    /// / `p_current_phase_str` / `stable_name_group_key`.
1155    ///
1156    /// Future status projections (`observed_parent` on the
1157    /// parent-pointer axis, `observed_message` on the human-
1158    /// readable-status axis, `observed_children` on the child
1159    /// fan-out axis, `observed_exit_code` on the terminal-exit
1160    /// axis) land as peer methods on this same axis.
1161    ///
1162    /// Theory anchor: THEORY.md §VI.1 (generation over
1163    /// composition — the 3-line status-projection chain recurred
1164    /// at FIVE hand-authored sites past the ★★ PRIME-DIRECTIVE
1165    /// ≥ 2 duplication trigger, and is lifted to ONE owner here).
1166    /// THEORY.md §II.1 invariant 5 (composition preserves proofs
1167    /// — the pins bind the missing-`status` corner + the
1168    /// per-variant enum round-trip + the byte-identical parity
1169    /// with the pre-lift 3-line chain, so a regression that
1170    /// drifted any surface at `tests::observed_phase_*` rather
1171    /// than as silent operator-facing skew between the
1172    /// controller's dispatch seed and the boundary evaluator's
1173    /// depends-on audit on the SAME `Process` within one
1174    /// reconcile pass).
1175    pub fn observed_phase(&self) -> Option<ProcessPhase> {
1176        self.status.as_ref().map(|s| s.phase)
1177    }
1178
1179    /// The copy-form status-projection primitive on the phase axis
1180    /// with the `Pending` sink applied — the ONE-liner collapse of
1181    /// the paired `self.observed_phase().unwrap_or(ProcessPhase::
1182    /// Pending)` incantation every reconciler consumer restated by
1183    /// hand at the `Option`-flattening tail of the `observed_phase`
1184    /// call. Sibling to [`Self::observed_phase`] on the (return-form
1185    /// × fallback shape) axis pair — the raw-`Option` corner stays
1186    /// as `observed_phase`, this method opens the `Pending`-defaulted
1187    /// corner that four of the five hand-authored `observed_phase`
1188    /// consumers chose (the fifth chose `Attested`; it keeps the raw
1189    /// `Option` accessor because a `Pending` sink would silently drop
1190    /// its released-from-annotation branch into the wrong label).
1191    ///
1192    /// The primitive returns [`ProcessPhase::Pending`] on any missing
1193    /// `status` slot — the same sentinel [`ProcessPhase::default`]
1194    /// returns, and the same fallback all four pre-lift consumers
1195    /// wrote by hand. `ProcessPhase::Pending` is load-bearing as the
1196    /// "not yet observed" default because the top-level dispatcher's
1197    /// `Pending → Forking` transition, the boundary evaluator's
1198    /// per-Process phase-reached postcondition, the routing groupby's
1199    /// stable-name claim-arbiter row seed, and the pool controller's
1200    /// desired-count snapshot all read a freshly-forked Process (no
1201    /// `status` yet stamped by the reconciler) as being at the
1202    /// entrypoint phase of the closed lifecycle. A caller with a
1203    /// different default choice (currently only the SIGSTOP/SIGCONT
1204    /// release gate's `Attested` fallback in
1205    /// `phase_machine::p_current_phase_str`) keeps the raw
1206    /// [`Self::observed_phase`] accessor at its own site.
1207    ///
1208    /// Pre-lift the two-link `.observed_phase().unwrap_or
1209    /// (ProcessPhase::Pending)` chain was hand-authored at FOUR
1210    /// sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold
1211    /// across the workspace:
1212    /// * `tatara-reconciler::controller::reconcile` — the top-level
1213    ///   dispatcher's `current_phase` seed that feeds the
1214    ///   deletion-preempt + signal-ingestion gates + the per-phase
1215    ///   handler dispatch.
1216    /// * `tatara-reconciler::boundary::evaluate_process_phase` — the
1217    ///   boundary evaluator's [`ConditionKind::ProcessPhase`]
1218    ///   evaluator that compares a peer-Process's observed phase
1219    ///   against the operator-declared `phase`-reached postcondition.
1220    /// * `tatara-reconciler::table_controller::stable_name_group_key`
1221    ///   — the routing-groupby seed that pairs the phase with the
1222    ///   PID + creation timestamp when partitioning Processes
1223    ///   claiming the same stable name.
1224    /// * `tatara-pool-reconciler::controller_pool::reconcile_pool` —
1225    ///   the desired-count loop's per-member snapshot seed that feeds
1226    ///   `decide_pool_convergence` with each owned Process's
1227    ///   `(phase, created_at)` pair.
1228    ///
1229    /// All FOUR sites walked the SAME two-link chain and all four
1230    /// closed with `ProcessPhase::Pending` as the sink; post-lift
1231    /// each callsite reads `process.observed_phase_or_pending()` and
1232    /// the produced `ProcessPhase` feeds the same downstream branch
1233    /// (dispatch on the `current_phase` value, comparison against a
1234    /// declared threshold, groupby-key composition, member-state
1235    /// snapshot construction) unchanged.
1236    ///
1237    /// Return-form axis: `ProcessPhase` matches the copy discipline
1238    /// of [`Self::observed_phase`] (a `Copy` scalar one byte wide),
1239    /// with the [`Option`] wrapper collapsed at the primitive rather
1240    /// than at every consumer. A caller that needs the missing-`status`
1241    /// corner as a distinguishable value keeps the raw
1242    /// [`Self::observed_phase`] accessor.
1243    ///
1244    /// A future normalization step (a generation-filter that
1245    /// treats a phase stamped with a stale `metadata.generation` as
1246    /// unobserved and therefore `Pending`, a staleness gate that
1247    /// drops a phase whose observing `phase_since` predates a
1248    /// reconcile deadline, a canonicalization pass that maps a phase
1249    /// that no longer belongs to the CRD's closed set to `Pending`)
1250    /// lands at ONE substrate method here — because this primitive
1251    /// composes on top of [`Self::observed_phase`], the normalization
1252    /// applies to both the raw-`Option` and the `Pending`-sinked
1253    /// return through the SAME upstream body — and all four
1254    /// downstream consumers pick up the upgrade mechanically.
1255    ///
1256    /// Peer to the sibling defaulted-fallback primitive family
1257    /// [`Self::namespace_or_default`] +
1258    /// [`Self::name_or_placeholder`] + [`Self::uid_or_empty`] on the
1259    /// (return-shape × fallback-value) axis — those three open the
1260    /// borrow-form defaulted corner for the metadata slots; this
1261    /// method opens the copy-form defaulted corner for the phase
1262    /// slot on `status`. Future defaulted-fallback status
1263    /// projections (an `observed_pid_or_empty` on the PID axis, an
1264    /// `observed_exit_code_or_zero` on the terminal-exit axis) land
1265    /// as peer methods on this same axis.
1266    ///
1267    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
1268    /// the two-link `.observed_phase().unwrap_or(Pending)` chain
1269    /// recurred at four hand-authored sites past the ★★
1270    /// PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE
1271    /// owner here). THEORY.md §II.1 invariant 5 (composition
1272    /// preserves proofs — the pins bind the missing-`status` sink to
1273    /// `Pending` + populated-status pass-through + every
1274    /// `ProcessPhase` variant round-trip + byte-identical parity
1275    /// with the pre-lift two-link chain, so a regression that
1276    /// drifted any surface at `tests::observed_phase_or_pending_*`
1277    /// rather than as silent operator-facing skew between the
1278    /// top-level dispatcher's `Pending → Forking` seed and the
1279    /// boundary evaluator's per-Process phase-reached postcondition
1280    /// on the SAME `Process` within one reconcile pass).
1281    pub fn observed_phase_or_pending(&self) -> ProcessPhase {
1282        self.observed_phase().unwrap_or(ProcessPhase::Pending)
1283    }
1284
1285    /// Copy-form metadata-projection primitive on the deletion-tombstone
1286    /// axis: returns `true` iff the K8s API server has stamped a
1287    /// `metadata.deletionTimestamp` on this Process (the moment the
1288    /// object entered the "being deleted" corner of its lifecycle,
1289    /// after which further mutating writes are refused and finalizers
1290    /// are drained before the object is actually removed) — the ONE-
1291    /// liner collapse of the paired `self.metadata.deletion_timestamp
1292    /// .is_some()` incantation every consumer restated by hand
1293    /// pre-lift.
1294    ///
1295    /// Pre-lift the `.metadata.deletion_timestamp.is_some()` chain
1296    /// was hand-authored at TWO sites past the ★★ PRIME-DIRECTIVE
1297    /// ≥ 2 duplication threshold in `tatara-reconciler`, both
1298    /// projecting the SAME tombstone-presence predicate on a
1299    /// `Process` value:
1300    /// * `controller::reconcile` — the top-level dispatcher's
1301    ///   deletion-preempt gate that forces the SIGTERM cascade
1302    ///   (`→ Exiting`) as soon as the API server stamps the
1303    ///   tombstone, before the phase handler for the current
1304    ///   [`ProcessPhase`] gets a chance to run. Composed with
1305    ///   [`ProcessPhase::is_alive`] so the preempt only fires on a
1306    ///   Process still in an alive phase — a Process already in
1307    ///   `Zombie` / `Reaped` / `Failed` runs its normal handler.
1308    /// * `phase_machine::handle_exiting` — the SIGTERM cascade's
1309    ///   child-fan-out loop that enumerates every child Process and
1310    ///   skips ones the API server has already tombstoned (so the
1311    ///   reconciler does not re-issue a `DELETE` against a child
1312    ///   whose deletion the API server is already draining through
1313    ///   its own finalizer). The skip composes with
1314    ///   [`Self::coordinates_or_none`]'s name-required probe so a
1315    ///   child missing either its tombstone-absent gate or its
1316    ///   `metadata.name` slot is a clean `continue` rather than an
1317    ///   attempted `child_api.delete("")` no-op.
1318    ///
1319    /// Both sites walked the SAME `.metadata.deletion_timestamp
1320    /// .is_some()` chain and both wanted the `bool` form the
1321    /// primitive returns — the `controller::reconcile` site to gate
1322    /// the SIGTERM preempt with `&& current_phase.is_alive()` and
1323    /// the `handle_exiting` site to gate the DELETE-skip with a
1324    /// bare `if child.is_being_deleted() { continue; }`. Post-lift
1325    /// each callsite reads `process.is_being_deleted()` and the
1326    /// produced `bool` feeds the same downstream gate unchanged.
1327    ///
1328    /// Return-form axis: `bool` matches the copy-form discipline of
1329    /// [`Self::observed_phase`] (an `Option<Copy>` scalar) — the
1330    /// underlying slot is a wire-format `Option<Time>` that carries
1331    /// only presence information at this axis (the RFC-3339 timestamp
1332    /// payload itself is not what the two consumers read; both only
1333    /// probe presence to detect the tombstone-stamped state).
1334    /// Returning the raw `Option<&Time>` would push the `.is_some()`
1335    /// probe back to every callsite, restating the pre-lift chain
1336    /// one link shorter without collapsing the primitive.
1337    ///
1338    /// Peer to the metadata-fallback primitives
1339    /// [`Self::namespace_or_default`], [`Self::name_or_placeholder`],
1340    /// [`Self::uid_or_empty`], [`Self::coordinates_or_defaults`],
1341    /// [`Self::coordinates_or_none`], [`Self::owned_coordinates_or_err`],
1342    /// [`Self::annotation`] on the metadata axis; this method opens
1343    /// the copy-form peer for the presence-probe corner. Future
1344    /// metadata-presence projections (an `is_being_finalized`
1345    /// projection on `metadata.finalizers.is_empty()`'s negation,
1346    /// a `has_owner` projection on `metadata.owner_references.is_empty()`'s
1347    /// negation) land as peer methods on this same axis.
1348    ///
1349    /// A future normalization step (a per-tombstone staleness gate
1350    /// that returns `false` for a tombstone older than the reconciler's
1351    /// grace-period budget, a canonicalization pass that treats a
1352    /// tombstone from a paused controller as absent, a cross-cluster
1353    /// tombstone-observation clock skew guard) lands at ONE substrate
1354    /// method here and both downstream consumers pick up the upgrade
1355    /// mechanically — no per-callsite hand-edit at
1356    /// `controller::reconcile` / `phase_machine::handle_exiting`.
1357    ///
1358    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
1359    /// the `.metadata.deletion_timestamp.is_some()` chain recurred at
1360    /// two hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2
1361    /// duplication trigger, and is lifted to ONE owner here).
1362    /// THEORY.md §II.1 invariant 5 (composition preserves proofs —
1363    /// the pins bind the missing-tombstone corner + the present-
1364    /// tombstone corner + the copy-form `bool` return + the byte-
1365    /// identical parity with the pre-lift `.is_some()` chain, so a
1366    /// regression that drifted any surface at
1367    /// `tests::is_being_deleted_*` rather than as silent operator-
1368    /// facing skew between the top-level dispatcher's SIGTERM
1369    /// preempt and the SIGTERM cascade's child-fan-out DELETE-skip
1370    /// on the SAME `Process` within one reconcile pass).
1371    pub fn is_being_deleted(&self) -> bool {
1372        self.metadata.deletion_timestamp.is_some()
1373    }
1374
1375    /// Copy-form metadata-projection primitive on the
1376    /// `metadata.creationTimestamp` axis: returns the K8s-API-server-
1377    /// assigned creation moment as a `DateTime<Utc>`, hiding the wire-
1378    /// format `k8s_openapi::apimachinery::pkg::apis::meta::v1::Time`
1379    /// newtype behind an inherent projection — the ONE-liner collapse
1380    /// of the paired `self.metadata.creation_timestamp.as_ref().map(|t|
1381    /// t.0)` incantation every timestamp-driven consumer restated by
1382    /// hand pre-lift.
1383    ///
1384    /// Pre-lift the paired `.metadata.creation_timestamp.as_ref()` +
1385    /// `t.0` unwrap chain was hand-authored at THREE sites past the
1386    /// ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold across the
1387    /// workspace, all projecting the SAME creation-moment `DateTime<Utc>`
1388    /// on a `Process`:
1389    /// * `tatara-process::lifetime_clock::evaluate` — TTL-expiry gate
1390    ///   in the ephemeral-lifetime decision (`elapsed = now
1391    ///   .signed_duration_since(creation.0)`), inside the non-terminal-
1392    ///   phase guard that fires the `AutoTerminate::Now { TtlExpired }`
1393    ///   branch. Pre-lift the site read `if let Some(creation) = process
1394    ///   .metadata.creation_timestamp.as_ref() { ... creation.0 ... }`.
1395    /// * `tatara-process::lifetime_clock::requeue_with_ttl` — sleep-
1396    ///   budget picker for the reconciler's next requeue, choosing the
1397    ///   smaller of HEARTBEAT and TTL-remaining so the reconciler
1398    ///   doesn't oversleep past a TTL boundary. Pre-lift the site read
1399    ///   `let Some(creation) = process.metadata.creation_timestamp
1400    ///   .as_ref() else { return default; };` + `creation.0`.
1401    /// * `tatara-reconciler::table_controller::reconcile_process_table`
1402    ///   — stable-name claim-arbiter row builder, seeding each
1403    ///   candidate row's `created_at` for the tie-break ordering
1404    ///   (oldest wins). Pre-lift the site read `p.metadata
1405    ///   .creation_timestamp.as_ref().map(|t| t.0).unwrap_or_else(Utc
1406    ///   ::now)`.
1407    ///
1408    /// All THREE sites walked the SAME two-link chain — read the
1409    /// `Option<Time>` slot as a borrow, then unwrap the `Time` newtype
1410    /// to its inner `DateTime<Utc>` — differing only in the tail
1411    /// (`if-let-Some` guard, `let-else` short-circuit, `Utc::now`
1412    /// fallback). Post-lift each callsite reads
1413    /// `process.created_at()` and applies its own tail at its own site
1414    /// (`if let Some(creation) = ...`, `let Some(creation) = ... else`,
1415    /// `.unwrap_or_else(Utc::now)`).
1416    ///
1417    /// Return-form axis: `Option<DateTime<Utc>>` matches the copy-form
1418    /// discipline of the sibling status-projection primitive
1419    /// [`Self::observed_phase`] — both return `Option<T>` where `T:
1420    /// Copy` and hide the wire-format wrapper (`ProcessStatus` on the
1421    /// status side; `Time` on the metadata side). Returning the raw
1422    /// `Option<&Time>` would push the `.0` unwrap back to every
1423    /// callsite, restating the pre-lift chain one link shorter without
1424    /// collapsing the primitive; returning owned `Option<Time>` would
1425    /// force a `Time` import at every consumer for a projection every
1426    /// consumer immediately discards past `.0`.
1427    ///
1428    /// Peer to the metadata-fallback + presence-probe primitives
1429    /// [`Self::namespace_or_default`], [`Self::name_or_placeholder`],
1430    /// [`Self::uid_or_empty`], [`Self::coordinates_or_defaults`],
1431    /// [`Self::coordinates_or_none`], [`Self::owned_coordinates_or_err`],
1432    /// [`Self::annotation`], [`Self::is_being_deleted`] on the metadata
1433    /// axis; this method opens the copy-form timestamp corner. Future
1434    /// metadata-timestamp projections (a
1435    /// `deletion_at() -> Option<DateTime<Utc>>` peer on the
1436    /// tombstone-payload axis for staleness gates that need the
1437    /// timestamp value alongside the presence bit) land as peer
1438    /// methods on this same axis.
1439    ///
1440    /// A future normalization step (a per-cluster clock-skew guard
1441    /// that offsets the returned timestamp by the observing controller's
1442    /// measured skew, a canonicalization pass that maps a suspiciously-
1443    /// zero creation moment to `None`, a per-namespace override that
1444    /// substitutes a `spec.identity`-declared creation anchor for the
1445    /// metadata slot on adopted resources) lands at ONE substrate
1446    /// method here and all three downstream consumers pick up the
1447    /// upgrade mechanically — no per-callsite hand-edit at `evaluate`
1448    /// / `requeue_with_ttl` / `reconcile_process_table`.
1449    ///
1450    /// Theory anchor: THEORY.md §VI.1 (generation over composition —
1451    /// the `.metadata.creation_timestamp.as_ref().map(|t| t.0)` chain
1452    /// recurred at three hand-authored sites past the ★★
1453    /// PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE
1454    /// owner here). THEORY.md §II.1 invariant 5 (composition preserves
1455    /// proofs — the pins bind the missing-timestamp corner + the
1456    /// present-timestamp corner + the copy-form `DateTime<Utc>` return
1457    /// + the byte-identical parity with the pre-lift `.as_ref().map(|t|
1458    /// t.0)` chain, so a regression that drifted any surface at
1459    /// `tests::created_at_*` rather than as silent operator-facing
1460    /// skew between the TTL-expiry gate, the requeue-budget picker,
1461    /// and the stable-name claim-arbiter tie-break on the SAME
1462    /// `Process` within one reconcile pass).
1463    pub fn created_at(&self) -> Option<DateTime<Utc>> {
1464        self.metadata.creation_timestamp.as_ref().map(|t| t.0)
1465    }
1466}
1467
1468/// Process status — every field optional until the reconciler writes it.
1469#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema)]
1470#[serde(rename_all = "camelCase")]
1471pub struct ProcessStatus {
1472    /// Hierarchical PID path — e.g., `"seph.1.7"`.
1473    #[serde(default, skip_serializing_if = "Option::is_none")]
1474    pub pid: Option<String>,
1475
1476    /// Parent PID path (mirror of `spec.identity.parent`, resolved at fork).
1477    #[serde(default, skip_serializing_if = "Option::is_none")]
1478    pub parent: Option<String>,
1479
1480    /// Direct children's PID paths.
1481    #[serde(default)]
1482    pub children: Vec<String>,
1483
1484    /// Resolved identity (name + content hash).
1485    #[serde(default, skip_serializing_if = "Option::is_none")]
1486    pub identity: Option<Identity>,
1487
1488    /// Current phase.
1489    #[serde(default)]
1490    pub phase: ProcessPhase,
1491
1492    /// When the process entered the current phase.
1493    #[serde(default, skip_serializing_if = "Option::is_none")]
1494    pub phase_since: Option<DateTime<Utc>>,
1495
1496    /// Three-pillar attestation (written at end of every successful cycle).
1497    #[serde(default, skip_serializing_if = "Option::is_none")]
1498    pub attestation: Option<ProcessAttestation>,
1499
1500    /// FluxCD resources currently owned by this Process.
1501    #[serde(default)]
1502    pub flux_resources: Vec<FluxResourceRef>,
1503
1504    /// Boundary verification state.
1505    #[serde(default)]
1506    pub boundary: BoundaryStatus,
1507
1508    /// Compliance summary at the latest attestation.
1509    #[serde(default)]
1510    pub compliance: ComplianceStatus,
1511
1512    /// Pending signals (delivered, not yet handled).
1513    #[serde(default)]
1514    pub signal_queue: Vec<ProcessSignal>,
1515
1516    /// Standard K8s Conditions.
1517    #[serde(default)]
1518    pub conditions: Vec<ProcessCondition>,
1519
1520    /// Human-readable last status message.
1521    #[serde(default, skip_serializing_if = "Option::is_none")]
1522    pub message: Option<String>,
1523
1524    /// Exit code (only set on Failed / Reaped).
1525    #[serde(default, skip_serializing_if = "Option::is_none")]
1526    pub exit_code: Option<i32>,
1527}
1528
1529#[cfg(test)]
1530mod tests {
1531    use super::*;
1532    use crate::classification::{ConvergencePointType, SubstrateType};
1533    use crate::intent::NixIntent;
1534
1535    #[test]
1536    fn minimal_spec_serializes() {
1537        let spec = ProcessSpec {
1538            identity: IdentitySpec::default(),
1539            classification: Classification {
1540                point_type: ConvergencePointType::Gate,
1541                substrate: SubstrateType::Observability,
1542                horizon: Default::default(),
1543                calm: Default::default(),
1544                data_classification: Default::default(),
1545            },
1546            intent: Intent {
1547                nix: Some(NixIntent {
1548                    flake_ref: "github:pleme-io/k8s".into(),
1549                    attribute: "obs".into(),
1550                    system: None,
1551                    attic_cache: None,
1552                    extra_args: vec![],
1553                    delegate_to_nix_build: false,
1554                }),
1555                ..Intent::default()
1556            },
1557            boundary: Default::default(),
1558            compliance: Default::default(),
1559            depends_on: vec![],
1560            signals: Default::default(),
1561            lifetime: Default::default(),
1562            routing: None,
1563            encapsulates: None,
1564            suspended: false,
1565        };
1566        let yaml = serde_yaml::to_string(&spec).unwrap();
1567        assert!(yaml.contains("pointType: Gate"));
1568        assert!(yaml.contains("substrate: Observability"));
1569        assert!(yaml.contains("flakeRef: github:pleme-io/k8s"));
1570    }
1571
1572    // ─── Process::coordinates_or_defaults substrate pins ────────────────
1573    //
1574    // Pins the (namespace, name) coordinate-primitive family on the
1575    // (metadata slot × fallback shape) axis. Fail-before-pass-after
1576    // granularity: a regression that flipped either fallback string,
1577    // swapped the return-tuple axis order, or dropped the
1578    // `Option::as_deref` unwrap surfaces here rather than as silent
1579    // drift at every downstream annotation writer / claim-arbiter row
1580    // builder / render owner-metadata seed.
1581
1582    fn empty_spec() -> ProcessSpec {
1583        ProcessSpec {
1584            identity: IdentitySpec::default(),
1585            classification: Classification {
1586                point_type: ConvergencePointType::Gate,
1587                substrate: SubstrateType::Compute,
1588                horizon: Default::default(),
1589                calm: Default::default(),
1590                data_classification: Default::default(),
1591            },
1592            intent: Intent::default(),
1593            boundary: Default::default(),
1594            compliance: Default::default(),
1595            depends_on: vec![],
1596            signals: Default::default(),
1597            lifetime: Default::default(),
1598            routing: None,
1599            encapsulates: None,
1600            suspended: false,
1601        }
1602    }
1603
1604    #[test]
1605    fn default_namespace_constant_is_k8s_canonical_default() {
1606        // Pins the load-bearing convention that this primitive's
1607        // namespace fallback matches K8s's own implicit-namespace
1608        // spelling. A regression that renamed this to "kube-system"
1609        // or any other K8s-reserved name would silently misroute
1610        // every downstream namespaced-Api call on a Process without
1611        // a metadata.namespace.
1612        assert_eq!(Process::DEFAULT_NAMESPACE, "default");
1613    }
1614
1615    #[test]
1616    fn unnamed_placeholder_constant_matches_prior_annotation_writer_fallback() {
1617        // Pins the load-bearing convention that this primitive's name
1618        // fallback matches the exact spelling every annotation writer
1619        // (tatara-reconciler::ssapply::inject_annotations,
1620        // tatara-reconciler::render::render, and
1621        // tatara-reconciler::table_controller's claim-row builder)
1622        // was hand-authoring pre-lift ("unnamed", NOT "<unnamed>" or
1623        // ""). A regression that renamed this would break the
1624        // annotation-writer / claim-arbiter grep contract silently.
1625        assert_eq!(Process::UNNAMED_PLACEHOLDER, "unnamed");
1626    }
1627
1628    #[test]
1629    fn namespace_or_default_falls_back_when_metadata_namespace_is_none() {
1630        let mut p = Process::new("some-proc", empty_spec());
1631        p.metadata.namespace = None;
1632        assert_eq!(p.namespace_or_default(), Process::DEFAULT_NAMESPACE);
1633    }
1634
1635    #[test]
1636    fn namespace_or_default_returns_metadata_slice_when_some() {
1637        let mut p = Process::new("some-proc", empty_spec());
1638        p.metadata.namespace = Some("prod-app".into());
1639        assert_eq!(p.namespace_or_default(), "prod-app");
1640    }
1641
1642    #[test]
1643    fn name_or_placeholder_falls_back_when_metadata_name_is_none() {
1644        let mut p = Process::new("real-name", empty_spec());
1645        p.metadata.name = None;
1646        assert_eq!(p.name_or_placeholder(), Process::UNNAMED_PLACEHOLDER);
1647    }
1648
1649    #[test]
1650    fn name_or_placeholder_returns_metadata_slice_when_some() {
1651        let p = Process::new("api-gateway", empty_spec());
1652        assert_eq!(p.name_or_placeholder(), "api-gateway");
1653    }
1654
1655    #[test]
1656    fn coordinates_or_defaults_composes_both_halves() {
1657        // Both slots present — returns metadata slices in
1658        // (namespace, name) axis order.
1659        let mut p = Process::new("api", empty_spec());
1660        p.metadata.namespace = Some("staging".into());
1661        assert_eq!(p.coordinates_or_defaults(), ("staging", "api"));
1662    }
1663
1664    #[test]
1665    fn coordinates_or_defaults_falls_back_on_both_slots() {
1666        // Both slots None — returns (DEFAULT_NAMESPACE,
1667        // UNNAMED_PLACEHOLDER) in axis order.
1668        let mut p = Process::new("scratch", empty_spec());
1669        p.metadata.name = None;
1670        p.metadata.namespace = None;
1671        assert_eq!(
1672            p.coordinates_or_defaults(),
1673            (Process::DEFAULT_NAMESPACE, Process::UNNAMED_PLACEHOLDER)
1674        );
1675    }
1676
1677    #[test]
1678    fn coordinates_or_defaults_mixes_slotted_and_fallback_halves() {
1679        // Namespace set, name missing — the (namespace, name) tuple
1680        // pins each half independently. A regression that returned
1681        // BOTH fallbacks when EITHER metadata slot was None would
1682        // surface here rather than at every downstream reader.
1683        let mut p = Process::new("kept-name", empty_spec());
1684        p.metadata.namespace = Some("prod".into());
1685        assert_eq!(p.coordinates_or_defaults(), ("prod", "kept-name"));
1686
1687        // Name set, namespace missing — the peer corner.
1688        let mut q = Process::new("api", empty_spec());
1689        q.metadata.namespace = None;
1690        assert_eq!(
1691            q.coordinates_or_defaults(),
1692            (Process::DEFAULT_NAMESPACE, "api")
1693        );
1694    }
1695
1696    // ─── Process::owned_coordinates_or_err substrate pins ──────────────
1697    //
1698    // Pins the owned + name-required peer of the coordinate-primitive
1699    // family on the (return-form × name gate) axis pair. Fail-before-
1700    // pass-after granularity: a regression that flipped the namespace
1701    // fallback string, dropped the `Option::clone` unwrap, changed the
1702    // return-tuple axis order, or altered the "Process has no
1703    // metadata.name" error wording surfaces here rather than as silent
1704    // drift at every pre-lift caller (10 sites in
1705    // `tatara-reconciler::phase_machine` + 2 sites in
1706    // `tatara-reconciler::signals` pre-lift).
1707
1708    #[test]
1709    fn owned_coordinates_or_err_returns_owned_strings_when_both_slots_present() {
1710        // Happy path — both slots populated, method returns owned
1711        // Strings in (namespace, name) axis order.
1712        let mut p = Process::new("api-gateway", empty_spec());
1713        p.metadata.namespace = Some("prod-app".into());
1714        let (ns, name) = p.owned_coordinates_or_err().unwrap();
1715        assert_eq!(ns, "prod-app");
1716        assert_eq!(name, "api-gateway");
1717        // Ownership pin: type inference above binds ns/name as
1718        // owned Strings — a regression that returned &str would
1719        // fail to compile at the following .push() call. This
1720        // holds the "owned" half of the primitive's contract.
1721        let mut owned_ns = ns;
1722        owned_ns.push_str("-mutated");
1723        assert_eq!(owned_ns, "prod-app-mutated");
1724    }
1725
1726    #[test]
1727    fn owned_coordinates_or_err_falls_back_on_namespace_but_returns_owned_name() {
1728        // Namespace absent → DEFAULT_NAMESPACE. Name present → owned.
1729        let p = Process::new("api", empty_spec());
1730        // Process::new leaves metadata.namespace = None by default.
1731        let (ns, name) = p.owned_coordinates_or_err().unwrap();
1732        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1733        assert_eq!(name, "api");
1734    }
1735
1736    #[test]
1737    fn owned_coordinates_or_err_errors_when_metadata_name_absent_regardless_of_namespace() {
1738        // Name absent → Err, REGARDLESS of whether the namespace is
1739        // populated. The name gate is strictly on `metadata.name` and
1740        // does NOT fall back to `Self::UNNAMED_PLACEHOLDER` (that
1741        // fallback is on the peer `coordinates_or_defaults`, which
1742        // exists precisely for consumers that can tolerate a
1743        // display placeholder).
1744        for ns_slot in [None, Some("prod".to_string())] {
1745            let mut p = Process::new("scratch", empty_spec());
1746            p.metadata.name = None;
1747            p.metadata.namespace = ns_slot.clone();
1748            let err = p.owned_coordinates_or_err().unwrap_err();
1749            assert!(
1750                err.to_string().contains("metadata.name"),
1751                "err on missing name (ns={ns_slot:?}) should mention metadata.name; got {err}"
1752            );
1753        }
1754    }
1755
1756    #[test]
1757    fn owned_coordinates_or_err_error_message_matches_pre_lift_reconciler_wording() {
1758        // Load-bearing wording pin — every pre-lift `tatara-reconciler`
1759        // helper (`phase_machine::namespace_and_name`,
1760        // `signals::ingest`, `signals::consume_effect`) errored with
1761        // EXACTLY this wording. Post-lift the substrate owner produces
1762        // the same wording so log-line / test greps that anchored on
1763        // it keep matching, and no operator-visible message drift
1764        // lands as a side effect of the substrate move.
1765        let mut p = Process::new("scratch", empty_spec());
1766        p.metadata.name = None;
1767        let err = p.owned_coordinates_or_err().unwrap_err();
1768        assert_eq!(err.to_string(), "Process has no metadata.name");
1769    }
1770
1771    #[test]
1772    fn owned_coordinates_or_err_namespace_fallback_matches_default_namespace_const() {
1773        // Byte-identity pin between the owned form's namespace
1774        // fallback and the workspace-wide `DEFAULT_NAMESPACE` const.
1775        // A regression that spelled this fallback as any other
1776        // string ("kube-system", "", "default-ns") would silently
1777        // misroute every downstream namespaced-Api call on a
1778        // Process without a metadata.namespace — surfaces here
1779        // rather than at every kube-rs API caller.
1780        let mut p = Process::new("api", empty_spec());
1781        p.metadata.namespace = None;
1782        let (ns, _) = p.owned_coordinates_or_err().unwrap();
1783        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1784    }
1785
1786    #[test]
1787    fn owned_coordinates_or_err_matches_pre_lift_reconciler_helper_shape() {
1788        // Byte-identical parity pin between the owned + name-required
1789        // primitive here and the pre-lift `tatara-reconciler` helper
1790        // shape — the exact 2-slot unwrap chain each pre-lift caller
1791        // spelled by hand:
1792        //
1793        //   let ns = p.metadata.namespace.clone().unwrap_or_else(|| "default".into());
1794        //   let name = p.metadata.name.clone().ok_or_else(|| anyhow!(...))?;
1795        //   Ok((ns, name))
1796        //
1797        // Sweeps every corner every callsite plausibly encounters
1798        // (both slots present, namespace absent, name absent, both
1799        // absent). A regression that inserted a normalization step
1800        // at the primitive that the pre-lift chain does NOT apply —
1801        // or vice versa — surfaces here rather than as silent drift
1802        // between the 12 pre-lift consumer callsites and the ONE
1803        // substrate owner they now route through.
1804        fn pre_lift(p: &Process) -> anyhow::Result<(String, String)> {
1805            let ns = p
1806                .metadata
1807                .namespace
1808                .clone()
1809                .unwrap_or_else(|| "default".into());
1810            let name = p
1811                .metadata
1812                .name
1813                .clone()
1814                .ok_or_else(|| anyhow::anyhow!("Process has no metadata.name"))?;
1815            Ok((ns, name))
1816        }
1817        // Both present.
1818        let mut p = Process::new("api", empty_spec());
1819        p.metadata.namespace = Some("prod".into());
1820        assert_eq!(p.owned_coordinates_or_err().unwrap(), pre_lift(&p).unwrap());
1821        // Namespace absent.
1822        let p = Process::new("api", empty_spec());
1823        assert_eq!(p.owned_coordinates_or_err().unwrap(), pre_lift(&p).unwrap());
1824        // Name absent → both variants error with the same wording.
1825        let mut p = Process::new("api", empty_spec());
1826        p.metadata.name = None;
1827        p.metadata.namespace = Some("prod".into());
1828        assert_eq!(
1829            p.owned_coordinates_or_err().unwrap_err().to_string(),
1830            pre_lift(&p).unwrap_err().to_string(),
1831        );
1832        // Both absent → still errors on the name gate.
1833        let mut p = Process::new("api", empty_spec());
1834        p.metadata.name = None;
1835        p.metadata.namespace = None;
1836        assert_eq!(
1837            p.owned_coordinates_or_err().unwrap_err().to_string(),
1838            pre_lift(&p).unwrap_err().to_string(),
1839        );
1840    }
1841
1842    #[test]
1843    fn owned_coordinates_or_err_axis_order_matches_coordinates_or_defaults() {
1844        // Cross-primitive coherence pin between the owned + name-
1845        // required form and the borrow + name-defaulted peer:
1846        // (namespace, name) axis order is IDENTICAL across both
1847        // return-forms. A regression that swapped the tuple slots on
1848        // only ONE of the two primitives would silently misroute
1849        // every consumer that picked between the two forms based on
1850        // its callsite's ownership needs. The pin re-reads both
1851        // primitives at test time so the equality holds iff both
1852        // live paths are the current implementation.
1853        let mut p = Process::new("app", empty_spec());
1854        p.metadata.namespace = Some("infra".into());
1855        let (borrow_ns, borrow_name) = p.coordinates_or_defaults();
1856        let (owned_ns, owned_name) = p.owned_coordinates_or_err().unwrap();
1857        assert_eq!(owned_ns, borrow_ns);
1858        assert_eq!(owned_name, borrow_name);
1859        // Explicit slot labels — pins the (namespace, name) axis
1860        // order as opposed to (name, namespace).
1861        assert_eq!(owned_ns, "infra"); // NOT "app"
1862        assert_eq!(owned_name, "app"); // NOT "infra"
1863    }
1864
1865    // ─── Process::coordinates_or_none substrate pins ──────────────────
1866    //
1867    // Pins the borrow + name-required peer of the coordinate-primitive
1868    // family on the (return-form × name-gate) axis pair. Closes the
1869    // corner previously left open (borrow + name-required) so the
1870    // three consumer shapes (child-Process delete-fan-out at
1871    // `phase_machine::handle_exiting`, claim-arbiter probe at
1872    // `phase_machine::process_holds_any_claim`, any future non-fatal
1873    // skip site) route through ONE primitive rather than three hand-
1874    // authored empty-string / `unwrap_or_default()` sentinel chains.
1875    // Fail-before-pass-after granularity: a regression that flipped
1876    // the namespace fallback, swapped the return-tuple axis order,
1877    // returned an owned form, or promoted a missing name to an error
1878    // rather than `None` surfaces here rather than as silent drift at
1879    // every borrow + name-required consumer.
1880
1881    #[test]
1882    fn coordinates_or_none_returns_slices_when_both_slots_present() {
1883        // Happy path — both slots populated, method returns borrowed
1884        // (&str, &str) in (namespace, name) axis order wrapped in
1885        // `Some`.
1886        let mut p = Process::new("api-gateway", empty_spec());
1887        p.metadata.namespace = Some("prod-app".into());
1888        let (ns, name) = p.coordinates_or_none().expect("Some when name set");
1889        assert_eq!(ns, "prod-app");
1890        assert_eq!(name, "api-gateway");
1891    }
1892
1893    #[test]
1894    fn coordinates_or_none_falls_back_on_namespace_but_returns_name_slice() {
1895        // Namespace absent → DEFAULT_NAMESPACE (shared with the peer
1896        // `coordinates_or_defaults` + `namespace_or_default`). Name
1897        // present → the metadata slice, wrapped in `Some`.
1898        let mut p = Process::new("api", empty_spec());
1899        p.metadata.namespace = None;
1900        let (ns, name) = p.coordinates_or_none().expect("Some when name set");
1901        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1902        assert_eq!(name, "api");
1903    }
1904
1905    #[test]
1906    fn coordinates_or_none_returns_none_when_metadata_name_absent_regardless_of_namespace() {
1907        // Name absent → `None`, REGARDLESS of whether the namespace
1908        // slot is populated. The name gate is strictly on
1909        // `metadata.name` and does NOT fall back to
1910        // `Self::UNNAMED_PLACEHOLDER` (that fallback is on the peer
1911        // `coordinates_or_defaults`, which exists precisely for
1912        // consumers that tolerate a display placeholder). Peer to
1913        // `owned_coordinates_or_err_errors_when_metadata_name_absent_regardless_of_namespace`
1914        // on the sibling primitive; a regression that widened THIS
1915        // form to substitute the placeholder while leaving the owned
1916        // form strict would silently drift the two borrow-form
1917        // primitives out of the coherence the family carries.
1918        for ns_slot in [None, Some("prod".to_string())] {
1919            let mut p = Process::new("scratch", empty_spec());
1920            p.metadata.name = None;
1921            p.metadata.namespace = ns_slot.clone();
1922            assert!(
1923                p.coordinates_or_none().is_none(),
1924                "coordinates_or_none must be None on missing name (ns={ns_slot:?})",
1925            );
1926        }
1927    }
1928
1929    #[test]
1930    fn coordinates_or_none_namespace_fallback_matches_default_namespace_const() {
1931        // Byte-identity pin between the borrow + name-required form's
1932        // namespace fallback and the workspace-wide `DEFAULT_NAMESPACE`
1933        // const. Sibling to
1934        // `owned_coordinates_or_err_namespace_fallback_matches_default_namespace_const`
1935        // on the peer primitive — the two forms MUST substitute the
1936        // same fallback string, else a consumer that switches between
1937        // them based on its ownership need silently observes a
1938        // different namespace-fallback shape as a side effect.
1939        let mut p = Process::new("api", empty_spec());
1940        p.metadata.namespace = None;
1941        let (ns, _) = p.coordinates_or_none().unwrap();
1942        assert_eq!(ns, Process::DEFAULT_NAMESPACE);
1943    }
1944
1945    #[test]
1946    fn coordinates_or_none_axis_order_matches_coordinates_or_defaults_when_name_present() {
1947        // Cross-primitive coherence pin between the two borrow-form
1948        // primitives: when the name is present, the (namespace, name)
1949        // return-tuple axis order is IDENTICAL across the two forms,
1950        // and the returned slices are the SAME `&str` view onto the
1951        // same metadata slots. A regression that swapped the tuple
1952        // slots on ONE form would silently misroute every consumer
1953        // that picked between the two forms based on its name-gate
1954        // need. The pin re-reads both primitives at test time so the
1955        // equality holds iff both live paths are the current
1956        // implementation.
1957        let mut p = Process::new("app", empty_spec());
1958        p.metadata.namespace = Some("infra".into());
1959        let (defaulted_ns, defaulted_name) = p.coordinates_or_defaults();
1960        let (required_ns, required_name) = p.coordinates_or_none().unwrap();
1961        assert_eq!(defaulted_ns, required_ns);
1962        assert_eq!(defaulted_name, required_name);
1963        // Explicit slot labels — pins the (namespace, name) axis order
1964        // as opposed to (name, namespace).
1965        assert_eq!(required_ns, "infra"); // NOT "app"
1966        assert_eq!(required_name, "app"); // NOT "infra"
1967    }
1968
1969    #[test]
1970    fn coordinates_or_none_axis_pair_diverges_from_coordinates_or_defaults_on_missing_name() {
1971        // Divergence pin between the two borrow-form primitives when
1972        // the name gate fires: `coordinates_or_defaults` substitutes
1973        // the display placeholder AND still returns a tuple;
1974        // `coordinates_or_none` returns `None`. A regression that
1975        // collapsed the two behaviors (either by dropping the gate
1976        // from the required form or by adding a `None` corner to the
1977        // defaulted form) would blur the axis pair's whole reason to
1978        // exist as two peer primitives.
1979        let mut p = Process::new("scratch", empty_spec());
1980        p.metadata.name = None;
1981        p.metadata.namespace = Some("prod".into());
1982        // Defaulted form: substitutes placeholder, no gate.
1983        assert_eq!(
1984            p.coordinates_or_defaults(),
1985            ("prod", Process::UNNAMED_PLACEHOLDER)
1986        );
1987        // Required form: gate fires, `None`.
1988        assert!(p.coordinates_or_none().is_none());
1989    }
1990
1991    #[test]
1992    fn coordinates_or_none_matches_pre_lift_reconciler_helper_shape() {
1993        // Byte-identical parity pin between the borrow + name-required
1994        // primitive here and the pre-lift `tatara-reconciler` helper
1995        // shapes — the exact 2-slot unwrap + gate chains each pre-lift
1996        // caller spelled by hand (`phase_machine::process_holds_any_claim`
1997        // spelled it as `unwrap_or("")` + `is_empty` early-return;
1998        // `phase_machine::handle_exiting`'s child-fan-out spelled it
1999        // as `unwrap_or_default()` + implicit no-op delete on the
2000        // empty API-path). Sweeps every corner every callsite plausibly
2001        // encounters (both slots present, namespace absent, name
2002        // absent + ns present, both absent). A regression that
2003        // inserted a normalization step at the primitive the pre-lift
2004        // chain does NOT apply — or vice versa — surfaces here rather
2005        // than as silent drift between the pre-lift consumer sites
2006        // and the ONE substrate owner they now route through.
2007        fn pre_lift_holds_any_claim(p: &Process) -> Option<(&str, &str)> {
2008            let ns = p.metadata.namespace.as_deref().unwrap_or("default");
2009            let name = p.metadata.name.as_deref().unwrap_or("");
2010            if name.is_empty() {
2011                return None;
2012            }
2013            Some((ns, name))
2014        }
2015        // Both present.
2016        let mut p = Process::new("api", empty_spec());
2017        p.metadata.namespace = Some("prod".into());
2018        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
2019        // Namespace absent.
2020        let p = Process::new("api", empty_spec());
2021        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
2022        // Name absent → both variants return `None` regardless of ns.
2023        let mut p = Process::new("api", empty_spec());
2024        p.metadata.name = None;
2025        p.metadata.namespace = Some("prod".into());
2026        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
2027        // Both absent → still `None` on the name gate.
2028        let mut p = Process::new("api", empty_spec());
2029        p.metadata.name = None;
2030        p.metadata.namespace = None;
2031        assert_eq!(p.coordinates_or_none(), pre_lift_holds_any_claim(&p));
2032    }
2033
2034    #[test]
2035    fn coordinates_or_none_axis_order_matches_owned_coordinates_or_err_on_happy_path() {
2036        // Cross-primitive coherence pin at the sibling corner: when
2037        // BOTH slots are present, the borrow + name-required form
2038        // (this method) and the owned + name-required peer
2039        // (`owned_coordinates_or_err`) return the SAME `(ns, name)`
2040        // pair — the axis order is IDENTICAL and neither primitive
2041        // silently applies a normalization the other omits. A
2042        // regression that skewed one form's normalization would
2043        // surface here rather than as silent drift between the two
2044        // name-required corners of the primitive family.
2045        let mut p = Process::new("app", empty_spec());
2046        p.metadata.namespace = Some("infra".into());
2047        let (borrow_ns, borrow_name) = p.coordinates_or_none().unwrap();
2048        let (owned_ns, owned_name) = p.owned_coordinates_or_err().unwrap();
2049        assert_eq!(borrow_ns, owned_ns.as_str());
2050        assert_eq!(borrow_name, owned_name.as_str());
2051    }
2052
2053    #[test]
2054    fn coordinates_or_defaults_axis_order_matches_qualified_process_ref() {
2055        // Pins the load-bearing convention that the return-tuple
2056        // axis order is (namespace, name) — the exact positional
2057        // argument order the substrate's paired-composer primitive
2058        // `tatara_reconciler::ssapply::qualified_process_ref(ns,
2059        // name)` consumes. A regression that swapped the tuple
2060        // slots would silently misroute every annotation writer /
2061        // claim-arbiter row / owner-metadata seed built by feeding
2062        // this pair into the composer — every downstream `<ns>/
2063        // <name>` grep would suddenly see `<name>/<ns>`. The test
2064        // verifies the tuple's first slot is what a hand-authored
2065        // `.metadata.namespace.as_deref()...` produced pre-lift, and
2066        // the second slot is what `.metadata.name.as_deref()...`
2067        // produced.
2068        let mut p = Process::new("app", empty_spec());
2069        p.metadata.namespace = Some("infra".into());
2070        let (ns, name) = p.coordinates_or_defaults();
2071        assert_eq!(ns, "infra"); // NOT "app"
2072        assert_eq!(name, "app"); // NOT "infra"
2073    }
2074
2075    // ─── Process::annotation substrate pins ────────────────────────────
2076    //
2077    // Pins the borrow-form annotation-lookup primitive that owns the
2078    // 3-line `.metadata.annotations.as_ref().and_then(|m| m.get(KEY))`
2079    // chain three hand-authored sites restated by hand pre-lift:
2080    // `tatara-reconciler::signals::ingest` (SIGNAL),
2081    // `tatara-reconciler::phase_machine::released_from_annotation`
2082    // (RELEASED_FROM), and
2083    // `tatara-pool-reconciler::controller_pool::process_belongs_to_pool`
2084    // (POOL). Fail-before-pass-after granularity: a regression that
2085    // widened the missing-`annotations` corner (returning `Some("")`
2086    // instead of `None`), promoted a missing key to an error, dropped
2087    // the borrow-form return, or changed the two swallowed corners'
2088    // shared collapse to `None` surfaces here rather than as silent
2089    // drift at the three consumer sites.
2090    fn process_with_annotation(key: &str, value: &str) -> Process {
2091        let mut p = Process::new("some-proc", empty_spec());
2092        let mut anns = std::collections::BTreeMap::new();
2093        anns.insert(key.to_string(), value.to_string());
2094        p.metadata.annotations = Some(anns);
2095        p
2096    }
2097
2098    #[test]
2099    fn annotation_returns_none_when_metadata_annotations_is_none() {
2100        // Missing-`annotations` corner: a Process with no annotations
2101        // block at all returns `None` for every key. Peer to
2102        // `observed_flux_resources_returns_empty_slice_when_status_is_none`
2103        // on the status-projection axis; both primitives collapse the
2104        // outer `Option` corner rather than requiring each consumer
2105        // to spell the guard by hand.
2106        let mut p = Process::new("scratch", empty_spec());
2107        p.metadata.annotations = None;
2108        assert!(p.annotation("tatara.pleme.io/signal").is_none());
2109        assert!(p.annotation("tatara.pleme.io/pool").is_none());
2110        assert!(p.annotation("").is_none());
2111    }
2112
2113    #[test]
2114    fn annotation_returns_none_when_key_absent_from_populated_map() {
2115        // Missing-key corner: annotations block populated with OTHER
2116        // keys returns `None` for the queried key. Symmetric with the
2117        // missing-`annotations` corner — both corners collapse to the
2118        // same `None`, matching the pre-lift `.and_then(...)`
2119        // behavior every consumer relied on.
2120        let p = process_with_annotation("tatara.pleme.io/other", "value");
2121        assert!(p.annotation("tatara.pleme.io/signal").is_none());
2122        assert!(p.annotation("").is_none());
2123    }
2124
2125    #[test]
2126    fn annotation_returns_borrowed_slice_when_key_present() {
2127        // Happy path: annotations block populated + key present →
2128        // `Some(&str)` borrowed from the underlying `String` in the
2129        // map. A regression that returned an owned `String` (defeating
2130        // the primitive's role as a zero-copy projection) would
2131        // surface at the lifetime of the returned reference — the
2132        // `&str` outlives the borrow of `&p` here.
2133        let p = process_with_annotation("tatara.pleme.io/signal", "SIGHUP");
2134        assert_eq!(p.annotation("tatara.pleme.io/signal"), Some("SIGHUP"));
2135    }
2136
2137    #[test]
2138    fn annotation_returns_borrowed_empty_string_slice_when_value_is_empty() {
2139        // Edge corner between the missing-key `None` and the present-
2140        // key `Some("")` — a Process whose annotation is EXPLICITLY
2141        // set to an empty string returns `Some("")`, NOT `None`. A
2142        // regression that normalized the empty-string value to `None`
2143        // (a plausible "defensive" simplification) would silently
2144        // reshape the corner every callsite pre-lift kept distinct via
2145        // `.cloned().unwrap_or_default()` (which collapses BOTH to
2146        // `""`) or `.map(String::as_str)` (which keeps them distinct
2147        // as `None` vs `Some("")`).
2148        let p = process_with_annotation("tatara.pleme.io/signal", "");
2149        assert_eq!(p.annotation("tatara.pleme.io/signal"), Some(""));
2150    }
2151
2152    #[test]
2153    fn annotation_is_a_pure_projection() {
2154        // Purity pin — repeated calls return equal results and the
2155        // primitive does not mutate `self`. Peer to
2156        // `observed_flux_resources_is_a_pure_projection` on the
2157        // status-projection axis.
2158        let p = process_with_annotation("tatara.pleme.io/released-from", "Attested");
2159        let a = p.annotation("tatara.pleme.io/released-from");
2160        let b = p.annotation("tatara.pleme.io/released-from");
2161        assert_eq!(a, b);
2162        assert_eq!(a, Some("Attested"));
2163    }
2164
2165    #[test]
2166    fn annotation_matches_pre_lift_reconciler_chain_shape() {
2167        // Byte-identical parity pin between the borrow-form primitive
2168        // here and the pre-lift `tatara-reconciler` / `tatara-pool-
2169        // reconciler` chain shape — the exact 3-line
2170        // `.metadata.annotations.as_ref().and_then(|m| m.get(KEY))
2171        // .map(String::as_str)` incantation each pre-lift caller
2172        // spelled by hand (three variants of tail collapsed onto ONE
2173        // borrow-form primitive here; each caller reapplies its own
2174        // tail at its own site). Sweeps every corner (missing
2175        // annotations map, missing key, present key with value,
2176        // present key with empty value) so a regression that inserted
2177        // a normalization at the primitive the pre-lift chain does
2178        // NOT apply — or vice versa — surfaces here rather than as
2179        // silent drift between the ONE substrate owner and the three
2180        // consumer sites.
2181        fn pre_lift<'a>(p: &'a Process, key: &str) -> Option<&'a str> {
2182            p.metadata
2183                .annotations
2184                .as_ref()
2185                .and_then(|m| m.get(key))
2186                .map(String::as_str)
2187        }
2188        // Missing annotations map.
2189        let mut p = Process::new("x", empty_spec());
2190        p.metadata.annotations = None;
2191        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
2192        // Missing key in populated map.
2193        let p = process_with_annotation("other", "v");
2194        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
2195        // Present key with non-empty value.
2196        let p = process_with_annotation("k", "v");
2197        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
2198        // Present key with explicitly-empty value — the corner
2199        // `.cloned().unwrap_or_default()` collapses to `""` post-tail
2200        // but the primitive-level shape stays `Some("")`.
2201        let p = process_with_annotation("k", "");
2202        assert_eq!(p.annotation("k"), pre_lift(&p, "k"));
2203    }
2204
2205    #[test]
2206    fn annotation_composes_owned_tail_matching_pre_lift_signals_ingest() {
2207        // Pins the exact tail shape `tatara-reconciler::signals::
2208        // ingest` composed pre-lift: an `Option<String>` for the
2209        // downstream `let Some(raw) = raw else { ... }` guard.
2210        // Post-lift the callsite composes `.map(str::to_string)` at
2211        // its own site; this test pins the composition matches the
2212        // pre-lift `.cloned()` tail byte-for-byte on both corners the
2213        // consumer's downstream distinguishes (annotation present →
2214        // `Some(String)`; absent → `None`).
2215        let p = process_with_annotation("tatara.pleme.io/signal", "SIGUSR1");
2216        assert_eq!(
2217            p.annotation("tatara.pleme.io/signal").map(str::to_string),
2218            Some("SIGUSR1".to_string())
2219        );
2220        let mut q = Process::new("y", empty_spec());
2221        q.metadata.annotations = None;
2222        assert_eq!(
2223            q.annotation("tatara.pleme.io/signal").map(str::to_string),
2224            None
2225        );
2226    }
2227
2228    #[test]
2229    fn annotation_composes_default_tail_matching_pre_lift_released_from() {
2230        // Pins the exact tail shape
2231        // `tatara-reconciler::phase_machine::released_from_annotation`
2232        // composed pre-lift: a bare `String` via `.cloned()
2233        // .unwrap_or_default()` for the downstream
2234        // `match v.as_str()` dispatch. Post-lift the callsite matches
2235        // directly on `Option<&str>` (Some("Failed") vs _); this test
2236        // pins that the borrow-form primitive plus the `.unwrap_or("")`
2237        // fallback reproduces the pre-lift bare-string shape on both
2238        // corners.
2239        let p = process_with_annotation("tatara.pleme.io/released-from", "Failed");
2240        assert_eq!(
2241            p.annotation("tatara.pleme.io/released-from").unwrap_or(""),
2242            "Failed"
2243        );
2244        let mut q = Process::new("y", empty_spec());
2245        q.metadata.annotations = None;
2246        assert_eq!(
2247            q.annotation("tatara.pleme.io/released-from").unwrap_or(""),
2248            ""
2249        );
2250    }
2251
2252    #[test]
2253    fn annotation_composes_borrow_equality_tail_matching_pre_lift_pool() {
2254        // Pins the exact tail shape `tatara-pool-reconciler::
2255        // controller_pool::process_belongs_to_pool` composed pre-lift:
2256        // an `Option<&str>` compared with `== Some(pool_name)` for the
2257        // membership gate. Post-lift the callsite composes
2258        // `p.annotation(POOL) == Some(pool_name)` verbatim; this test
2259        // pins that the borrow-form primitive returns exactly the
2260        // shape the equality gate expects.
2261        let p = process_with_annotation("tatara.pleme.io/pool", "demo-pool");
2262        assert_eq!(
2263            p.annotation("tatara.pleme.io/pool") == Some("demo-pool"),
2264            true
2265        );
2266        assert_eq!(p.annotation("tatara.pleme.io/pool") == Some("other"), false);
2267    }
2268
2269    // ─── Process::uid_or_empty substrate pins ──────────────────────────
2270    //
2271    // Pins the borrow-form metadata-projection primitive on the
2272    // `metadata.uid` axis that owns the `.metadata.uid.as_deref()
2273    // .unwrap_or("")` chain the two hand-authored
2274    // `tatara-reconciler::render` sites (`render_routing` +
2275    // `render_export_jobs`) restated by hand pre-lift. Peer to the
2276    // sibling `namespace_or_default_*` + `name_or_placeholder_*` pin
2277    // families on the metadata-slot × fallback-shape axis; all three
2278    // primitives return borrows of an owned-metadata slot with a slot-
2279    // specific fallback baked in (`"default"` for namespace, `"unnamed"`
2280    // for name, `""` for uid — the load-bearing gate value for
2281    // `owner_references_json`'s `is_empty` check). Fail-before-pass-
2282    // after granularity: `uid_or_empty` did not exist pre-lift, so any
2283    // test invoking it fails to compile pre-lift and passes post-lift.
2284
2285    #[test]
2286    fn uid_or_empty_returns_empty_string_when_metadata_uid_is_none() {
2287        // Empty-slot corner pin: the primitive collapses the no-uid
2288        // case to `""`, matching the pre-lift `.as_deref().unwrap_or("")`
2289        // chain's `""` byte-identically at both render consumer sites.
2290        // Semantically corresponds to a Process pre-metadata (fixtured
2291        // in tests, or caught mid-Forking before the API server has
2292        // stamped a `uid`); the downstream `owner_references_json`
2293        // composer gates on this exact `""` sentinel to stamp
2294        // `metadata.ownerReferences: []` rather than emit an owner-ref
2295        // pointing at a placeholder uid.
2296        let mut p = Process::new("scratch", empty_spec());
2297        p.metadata.uid = None;
2298        assert_eq!(p.uid_or_empty(), "");
2299    }
2300
2301    #[test]
2302    fn uid_or_empty_returns_borrowed_str_when_slot_is_populated() {
2303        // Happy-path pin: with a populated `metadata.uid` slot, the
2304        // primitive returns a borrowed `&str` whose contents match the
2305        // persisted `String`. A regression that reshaped / normalized
2306        // / cross-cluster-stripped the uid without touching this pin
2307        // would surface here rather than as silent skew at the two
2308        // `owner_references_json(name, uid)` emitters on the SAME
2309        // Process.
2310        let mut p = Process::new("owned-proc", empty_spec());
2311        p.metadata.uid = Some("uid-abc-123".into());
2312        assert_eq!(p.uid_or_empty(), "uid-abc-123");
2313    }
2314
2315    #[test]
2316    fn uid_or_empty_returns_empty_string_when_slot_is_explicitly_empty_string() {
2317        // Corner between the missing-slot `None` and the explicitly-
2318        // empty-string `Some("")` — both collapse to `""` at the
2319        // primitive because the downstream gate at
2320        // `owner_references_json` treats `.is_empty()` uniformly (the
2321        // empty-slot posture is what the whole primitive family
2322        // encodes: "no admissible owner reference, stamp `[]`"). A
2323        // regression that discriminated the two corners (returning a
2324        // sentinel `"<none>"` for the missing slot but `""` for the
2325        // explicit slot) would break the composition with
2326        // `owner_references_json` at the exactly-two-corner gate.
2327        let mut p = Process::new("owned-proc", empty_spec());
2328        p.metadata.uid = Some(String::new());
2329        assert_eq!(p.uid_or_empty(), "");
2330    }
2331
2332    #[test]
2333    fn uid_or_empty_is_a_zero_copy_borrow_projection() {
2334        // Borrow-discipline pin: the returned `&str` borrows the
2335        // persisted `String`'s underlying byte buffer in place — NOT
2336        // a fresh allocation or a clone. A regression that switched
2337        // the projection to an owned `String` (via `.clone()` or a
2338        // `format!` wrap) would defeat the zero-copy contract the
2339        // lift's primary strict-widening delivers, and would surface
2340        // here via pointer-identity comparison.
2341        let mut p = Process::new("owned-proc", empty_spec());
2342        p.metadata.uid = Some("uid-borrow-pin".into());
2343        let slice = p.uid_or_empty();
2344        assert!(std::ptr::eq(
2345            slice.as_ptr(),
2346            p.metadata.uid.as_ref().unwrap().as_ptr()
2347        ));
2348    }
2349
2350    #[test]
2351    fn uid_or_empty_is_a_pure_projection() {
2352        // Purity pin — repeated calls return byte-identical slices
2353        // (same pointer, same length). A regression that introduced
2354        // state (a lazy-cached normalized slot, a first-call
2355        // canonicalization pass) would surface here rather than as
2356        // silent drift between the two render consumer sites on the
2357        // SAME Process within one render pass.
2358        let mut p = Process::new("owned-proc", empty_spec());
2359        p.metadata.uid = Some("uid-pure".into());
2360        let a = p.uid_or_empty();
2361        let b = p.uid_or_empty();
2362        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2363        assert_eq!(a.len(), b.len());
2364    }
2365
2366    #[test]
2367    fn uid_or_empty_matches_pre_lift_render_chain_shape() {
2368        // Byte-identical parity pin between the borrow-form primitive
2369        // here and the pre-lift `tatara-reconciler::render` chain shape
2370        // — the exact `.metadata.uid.as_deref().unwrap_or("")`
2371        // incantation both `render_routing` (line 514) and
2372        // `render_export_jobs` (line 653) spelled by hand pre-lift.
2373        // Sweeps every corner (missing uid slot, populated uid slot,
2374        // explicitly-empty uid slot) so a regression that inserted a
2375        // normalization the pre-lift chain does NOT apply — or vice
2376        // versa — surfaces here rather than as silent drift between
2377        // the ONE substrate owner and the two consumer sites.
2378        fn pre_lift(p: &Process) -> &str {
2379            p.metadata.uid.as_deref().unwrap_or("")
2380        }
2381        // Missing slot.
2382        let mut p = Process::new("x", empty_spec());
2383        p.metadata.uid = None;
2384        assert_eq!(p.uid_or_empty(), pre_lift(&p));
2385        // Populated slot.
2386        let mut p = Process::new("x", empty_spec());
2387        p.metadata.uid = Some("uid-42".into());
2388        assert_eq!(p.uid_or_empty(), pre_lift(&p));
2389        // Explicitly-empty slot.
2390        let mut p = Process::new("x", empty_spec());
2391        p.metadata.uid = Some(String::new());
2392        assert_eq!(p.uid_or_empty(), pre_lift(&p));
2393    }
2394
2395    #[test]
2396    fn uid_or_empty_composes_with_owner_references_json_empty_gate() {
2397        // Cross-primitive composition pin — the empty-string sentinel
2398        // this primitive returns for the missing-uid corner is EXACTLY
2399        // the sentinel the sibling substrate composer
2400        // `owner_references_json(name, uid)` gates on to stamp
2401        // `metadata.ownerReferences: []`. A regression that changed
2402        // the sentinel at either end (this primitive returning
2403        // `"<none>"`, `owner_references_json` gating on `uid == "0"`
2404        // instead of `uid.is_empty()`) would break the composition
2405        // and surface here rather than as an operator-observed
2406        // orphan resource after apply.
2407        let mut p = Process::new("x", empty_spec());
2408        p.metadata.uid = None;
2409        let refs = crate::owner_references_json("some-name", p.uid_or_empty());
2410        assert!(
2411            refs.is_empty(),
2412            "empty-uid corner must produce empty owner-refs array"
2413        );
2414
2415        p.metadata.uid = Some("real-uid".into());
2416        let refs = crate::owner_references_json("some-name", p.uid_or_empty());
2417        assert_eq!(
2418            refs.len(),
2419            1,
2420            "populated-uid corner must produce one owner-ref entry"
2421        );
2422    }
2423
2424    // ─── Process::owned_name_or_empty substrate pins ─────────────────
2425    //
2426    // Pins the owned-form metadata-projection primitive on the
2427    // `metadata.name` axis that owns the
2428    // `.metadata.name.clone().unwrap_or_default()` chain the two hand-
2429    // authored `tatara-pool-reconciler::controller_pool` sites (the
2430    // `PoolMember` seed at line 68 + the `PoolMemberSnapshot` desired-
2431    // count seed at line 108) restated by hand pre-lift. Peer to the
2432    // sibling `uid_or_empty` pin family on the (return-form × fallback-
2433    // value) axis pair — `uid_or_empty` owns the BORROW + empty-sentinel
2434    // corner (`&str` for owner-ref emitters gating on `.is_empty()`);
2435    // this method owns the OWNED + empty-sentinel corner (`String` for
2436    // struct-literal / HashMap-key row-builder consumers whose
2437    // downstream fills a `String` field with the load-bearing `""`
2438    // sentinel). Fail-before-pass-after granularity: `owned_name_or_empty`
2439    // did not exist pre-lift, so any test invoking it fails to compile
2440    // pre-lift and passes post-lift.
2441
2442    #[test]
2443    fn owned_name_or_empty_returns_empty_string_when_metadata_name_is_none() {
2444        // Empty-slot corner pin: the primitive collapses the no-name
2445        // case to `String::new()`, matching the pre-lift
2446        // `.clone().unwrap_or_default()` chain's empty `String` byte-
2447        // identically at both pool-reconciler consumer sites.
2448        // Semantically corresponds to a Process pre-metadata-name (test
2449        // fixture, dynamic API response pre-name-resolution); the
2450        // downstream `PoolMember { process_name, .. }` slot then holds
2451        // `""` as a stable "no name to key by" signal rather than a
2452        // display placeholder that would silently alias distinct rows.
2453        let mut p = Process::new("scratch", empty_spec());
2454        p.metadata.name = None;
2455        assert_eq!(p.owned_name_or_empty(), String::new());
2456    }
2457
2458    #[test]
2459    fn owned_name_or_empty_returns_owned_string_when_slot_is_populated() {
2460        // Happy-path pin: with a populated `metadata.name` slot, the
2461        // primitive returns an owned `String` whose contents match the
2462        // persisted `String`. A regression that reshaped / normalized
2463        // / case-folded the name without touching this pin would surface
2464        // here rather than as silent skew between the two pool-member
2465        // seeds keying on the SAME Process's name.
2466        let p = Process::new("api", empty_spec());
2467        assert_eq!(p.owned_name_or_empty(), "api");
2468    }
2469
2470    #[test]
2471    fn owned_name_or_empty_returns_empty_string_when_slot_is_explicitly_empty_string() {
2472        // Corner between the missing-slot `None` and the explicitly-
2473        // empty-string `Some(String::new())` — both collapse to `""` at
2474        // the primitive because the downstream pool-member consumers
2475        // treat both corners uniformly (no name, no key). A regression
2476        // that discriminated the two corners (returning a sentinel
2477        // `"<none>"` for the missing slot but `""` for the explicit
2478        // slot) would break `String::is_empty` gating at the row-builder
2479        // callsites without moving this pin.
2480        let mut p = Process::new("scratch", empty_spec());
2481        p.metadata.name = Some(String::new());
2482        assert_eq!(p.owned_name_or_empty(), String::new());
2483        assert!(p.owned_name_or_empty().is_empty());
2484    }
2485
2486    #[test]
2487    fn owned_name_or_empty_is_a_pure_projection() {
2488        // Purity pin — repeated calls return byte-identical `String`
2489        // values. A regression that introduced state (a lazy-cached
2490        // normalized slot, a first-call canonicalization pass) would
2491        // surface here rather than as silent drift between the pool-
2492        // member seed and the desired-count snapshot seed on the SAME
2493        // Process within one reconcile pass.
2494        let p = Process::new("stable-name", empty_spec());
2495        assert_eq!(p.owned_name_or_empty(), p.owned_name_or_empty());
2496    }
2497
2498    #[test]
2499    fn owned_name_or_empty_returns_independent_owned_string() {
2500        // Owned-discipline pin: the returned `String` is an independent
2501        // allocation the caller may consume, `.push_str` into, or move
2502        // into a struct-literal `process_name: String` slot — NOT a
2503        // shared reference into `metadata.name`. A regression that
2504        // switched the projection to a `Cow`-shaped variant or a slice-
2505        // form projection would defeat the owned-form contract the two
2506        // pool-reconciler struct-literal consumers depend on (a slice
2507        // cannot land in a `process_name: String` slot without a re-
2508        // clone), and would surface here at compile time via the mutate-
2509        // in-place test below.
2510        let p = Process::new("owned-proc", empty_spec());
2511        let mut owned = p.owned_name_or_empty();
2512        owned.push_str("-mutated");
2513        assert_eq!(owned, "owned-proc-mutated");
2514        // The Process's own slot is unchanged — the returned String
2515        // owns its own byte buffer, disjoint from `metadata.name`.
2516        assert_eq!(p.metadata.name.as_deref(), Some("owned-proc"));
2517    }
2518
2519    #[test]
2520    fn owned_name_or_empty_matches_pre_lift_controller_pool_chain_shape() {
2521        // Byte-identical parity pin between the owned-form primitive
2522        // here and the pre-lift `tatara-pool-reconciler::controller_pool`
2523        // chain shape — the exact `.metadata.name.clone().unwrap_or_default()`
2524        // incantation both `PoolMember` seed (line 68) and
2525        // `PoolMemberSnapshot` seed (line 108) spelled by hand pre-lift.
2526        // Sweeps every corner (missing name slot, populated name slot,
2527        // explicitly-empty name slot) so a regression that inserted a
2528        // normalization the pre-lift chain does NOT apply — or vice
2529        // versa — surfaces here rather than as silent drift between
2530        // the ONE substrate owner and the two consumer sites.
2531        fn pre_lift(p: &Process) -> String {
2532            p.metadata.name.clone().unwrap_or_default()
2533        }
2534        // Missing slot.
2535        let mut p = Process::new("x", empty_spec());
2536        p.metadata.name = None;
2537        assert_eq!(p.owned_name_or_empty(), pre_lift(&p));
2538        // Populated slot.
2539        let p = Process::new("real-name", empty_spec());
2540        assert_eq!(p.owned_name_or_empty(), pre_lift(&p));
2541        // Explicitly-empty slot.
2542        let mut p = Process::new("x", empty_spec());
2543        p.metadata.name = Some(String::new());
2544        assert_eq!(p.owned_name_or_empty(), pre_lift(&p));
2545    }
2546
2547    #[test]
2548    fn owned_name_or_empty_shares_empty_sentinel_with_uid_or_empty() {
2549        // Cross-primitive coherence pin — the empty-string fallback this
2550        // primitive returns for the missing-name corner is the SAME
2551        // sentinel the sibling borrow-form primitive `uid_or_empty`
2552        // returns for the missing-uid corner. Both partition the OWNED
2553        // × BORROW corner of the metadata-slot family on identical
2554        // fallback semantics ("the slot is unset"), so a consumer that
2555        // switches between them based on downstream ownership
2556        // requirements never sees a different missing-slot spelling as
2557        // a side effect. A regression that drifted either sentinel
2558        // (this primitive returning `"<unnamed>"`, `uid_or_empty`
2559        // returning `"<none>"`) would break the partition and surface
2560        // here rather than as silent shape drift across the family.
2561        let mut p = Process::new("scratch", empty_spec());
2562        p.metadata.name = None;
2563        p.metadata.uid = None;
2564        assert_eq!(p.owned_name_or_empty(), p.uid_or_empty());
2565        assert!(p.owned_name_or_empty().is_empty());
2566        assert!(p.uid_or_empty().is_empty());
2567    }
2568
2569    #[test]
2570    fn owned_name_or_empty_returns_distinct_fallback_from_name_or_placeholder() {
2571        // Axis-partition pin — the owned + empty-sentinel primitive here
2572        // and the borrow + display-placeholder primitive
2573        // [`Self::name_or_placeholder`] MUST return distinct fallback
2574        // values on the missing-name corner. The distinction is load-
2575        // bearing: `owned_name_or_empty` is for HashMap-key / row-builder
2576        // consumers that need distinct keys for missing-name Processes
2577        // (empty string collides only with other missing-name rows,
2578        // never with a real "unnamed" Process); `name_or_placeholder`
2579        // is for log-line / display consumers that render the
2580        // `"unnamed"` word to operators. A regression that unified the
2581        // two fallbacks (either primitive returning the other's
2582        // sentinel) would silently collapse missing-name pool members
2583        // into a display-string key or expose the empty sentinel to
2584        // operator log lines. This pin catches either drift.
2585        let mut p = Process::new("scratch", empty_spec());
2586        p.metadata.name = None;
2587        assert_eq!(p.owned_name_or_empty(), "");
2588        assert_eq!(p.name_or_placeholder(), Process::UNNAMED_PLACEHOLDER);
2589        assert_ne!(p.owned_name_or_empty(), p.name_or_placeholder());
2590    }
2591
2592    // ─── Process::declared_parent_pid substrate pins ─────────────────
2593    //
2594    // Pins the borrow-form spec-projection primitive on the declared
2595    // parent-PID axis that owns the `.spec.identity.parent.as_deref()`
2596    // chain the two hand-authored `tatara-reconciler::phase_machine`
2597    // sites (`handle_forking` ALLOCATE-PID composer + `handle_exiting`
2598    // SIGTERM-cascade child-fan-out filter) restated by hand pre-lift.
2599    // Peer to the sibling `observed_pid_*` pin family on the (spec-
2600    // declared × status-observed) axis pair; both compose the same
2601    // borrow-form `Option<&str>` return-shape skeleton on distinct
2602    // slots (`spec.identity.parent` vs. `status.pid`). Fail-before-
2603    // pass-after granularity: `declared_parent_pid` did not exist
2604    // pre-lift, so any test invoking it fails to compile pre-lift and
2605    // passes post-lift.
2606    fn process_with_declared_parent(parent: Option<&str>) -> Process {
2607        let mut spec = empty_spec();
2608        spec.identity.parent = parent.map(str::to_string);
2609        Process::new("child-proc", spec)
2610    }
2611
2612    #[test]
2613    fn declared_parent_pid_returns_none_when_slot_is_none() {
2614        // Empty-slot corner pin: the primitive collapses the no-
2615        // parent case to `None`, matching the pre-lift `.as_deref()`
2616        // chain's `None` byte-identically at both reconciler consumer
2617        // sites. Semantically corresponds to a Process authored at
2618        // cluster init (PID 1) with no upstream parent — the
2619        // ALLOCATE-PID composer feeds `None` into `pid::allocate_pid`
2620        // to signal "no prefix", and the SIGTERM cascade's filter
2621        // never matches such a Process because a child's declared
2622        // parent can never equal `Some(pid)` when the slot is `None`.
2623        let p = process_with_declared_parent(None);
2624        assert!(p.declared_parent_pid().is_none());
2625    }
2626
2627    #[test]
2628    fn declared_parent_pid_returns_borrowed_str_when_slot_is_populated() {
2629        // Happy-path pin: with a populated `spec.identity.parent`
2630        // slot, the primitive returns a borrowed `&str` whose
2631        // contents match the persisted `String`. A regression that
2632        // filtered / reshaped / canonicalized the string would
2633        // surface here rather than as silent skew at the child-fan-
2634        // out filter's `.declared_parent_pid() == Some(pid)`
2635        // equality check on the SAME parent-child pair.
2636        let p = process_with_declared_parent(Some("seph.1"));
2637        assert_eq!(p.declared_parent_pid(), Some("seph.1"));
2638    }
2639
2640    #[test]
2641    fn declared_parent_pid_is_a_zero_copy_borrow_projection() {
2642        // Borrow-discipline pin: the returned `&str` borrows the
2643        // persisted `String`'s underlying byte buffer in place —
2644        // NOT a fresh allocation or a clone. A regression that
2645        // switched the projection to an owned `String` (via
2646        // `.clone()` or `.to_owned()`) would defeat the zero-copy
2647        // contract the lift's primary strict-widening delivers.
2648        // The `handle_exiting` cascade filter runs per candidate
2649        // child across the cluster-wide Process list; a per-row
2650        // `String::clone` would allocate one heap block per non-
2651        // matching row, so the borrow-form primitive is load-
2652        // bearing for large clusters. Peer to the sibling
2653        // `observed_pid_is_a_zero_copy_borrow_projection` pin on
2654        // the status-observed side of the axis pair.
2655        let p = process_with_declared_parent(Some("seph.1"));
2656        let borrowed = p.declared_parent_pid().expect("populated slot");
2657        let persisted = p.spec.identity.parent.as_ref().unwrap();
2658        assert!(std::ptr::eq(borrowed.as_ptr(), persisted.as_ptr()));
2659    }
2660
2661    #[test]
2662    fn declared_parent_pid_is_a_pure_projection() {
2663        // Purity pin: calling the projection twice on the same
2664        // `Process` returns byte-identical `&str`s (same pointer,
2665        // same length). A regression that introduced state — a
2666        // lazy-cached slice materialized on first call, a
2667        // normalization step that ran once and cached — would
2668        // surface here rather than as silent drift between the
2669        // ALLOCATE-PID composer and the SIGTERM cascade's child-
2670        // fan-out filter within one reconcile pass.
2671        let p = process_with_declared_parent(Some("seph.1.3"));
2672        let a = p.declared_parent_pid().expect("populated slot");
2673        let b = p.declared_parent_pid().expect("populated slot");
2674        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2675        assert_eq!(a.len(), b.len());
2676    }
2677
2678    #[test]
2679    fn declared_parent_pid_matches_pre_lift_reconciler_chain_shape() {
2680        // Byte-identical parity pin between the borrow-form primitive
2681        // here and the pre-lift `tatara-reconciler::phase_machine`
2682        // `.spec.identity.parent.as_deref()` chain shape. Sweeps
2683        // every corner every callsite plausibly encounters (empty
2684        // slot, populated with a hierarchical PID). A regression
2685        // that inserted a normalization step at the primitive the
2686        // pre-lift chain does NOT apply — or vice versa — surfaces
2687        // here rather than as silent drift between the pre-lift
2688        // consumer sites and the ONE substrate owner they now route
2689        // through. Peer to
2690        // `observed_pid_matches_pre_lift_reconciler_chain_shape` on
2691        // the sibling axis's borrow-form primitive.
2692        fn pre_lift(p: &Process) -> Option<&str> {
2693            p.spec.identity.parent.as_deref()
2694        }
2695        // Empty slot.
2696        let p = process_with_declared_parent(None);
2697        assert_eq!(p.declared_parent_pid(), pre_lift(&p));
2698        // Populated with a hierarchical PID.
2699        let p = process_with_declared_parent(Some("seph.1"));
2700        assert_eq!(p.declared_parent_pid(), pre_lift(&p));
2701        // Populated with a deeper hierarchical PID.
2702        let p = process_with_declared_parent(Some("seph.1.7.42"));
2703        assert_eq!(p.declared_parent_pid(), pre_lift(&p));
2704    }
2705
2706    #[test]
2707    fn declared_parent_pid_preserves_hierarchical_pid_format() {
2708        // Format-preservation pin: the hierarchical PID path
2709        // (dotted-segment form `seph.1.7`, matching the ported
2710        // `convergence-controller/src/identity.rs` scheme) reaches
2711        // the caller with segments and separators byte-identical
2712        // to the persisted `String`. A regression that inserted a
2713        // canonicalization pass (a segment-count validator, a
2714        // separator swap `.` → `/`, a leading/trailing whitespace
2715        // trim) would silently misroute the SIGTERM cascade's
2716        // `declared_parent_pid() == Some(pid)` comparator against
2717        // children whose `parent` field was authored in the ported
2718        // scheme's exact form — the SAME children the observed_pid
2719        // primitive is pinned to match on the other side of the
2720        // axis pair.
2721        for parent in ["seph", "seph.1", "seph.1.7", "seph.1.7.42"] {
2722            let p = process_with_declared_parent(Some(parent));
2723            assert_eq!(p.declared_parent_pid(), Some(parent));
2724        }
2725    }
2726
2727    #[test]
2728    fn declared_parent_pid_composes_with_observed_pid_for_child_fanout_filter() {
2729        // Cross-axis coherence pin against the sibling
2730        // [`Self::observed_pid`] on the (spec-declared × status-
2731        // observed) axis pair: a child's `.declared_parent_pid()`
2732        // and its parent's `.observed_pid()` compose through the
2733        // SAME borrow-form `Option<&str>` skeleton so the
2734        // `handle_exiting` cascade filter's equality gate holds
2735        // structurally. A regression that skewed EITHER primitive's
2736        // return-form (return-shape, borrow discipline, empty-slot
2737        // collapse) would silently misroute every SIGTERM cascade
2738        // on the parent-child pair. This pin re-reads both primitives
2739        // at test time so the composition holds iff both live paths
2740        // are the current implementation.
2741        // Parent Process: has an observed PID.
2742        let mut parent = Process::new("parent-proc", empty_spec());
2743        parent.status = Some(ProcessStatus {
2744            pid: Some("seph.1".to_string()),
2745            ..Default::default()
2746        });
2747        // Child Process: declared parent matches parent's observed PID.
2748        let child = process_with_declared_parent(Some("seph.1"));
2749        // The `handle_exiting` filter's equality gate:
2750        // `child.declared_parent_pid() == Some(parent.observed_pid()?)`.
2751        let parent_pid = parent.observed_pid().expect("parent has PID");
2752        assert_eq!(child.declared_parent_pid(), Some(parent_pid));
2753        // Sibling Process with an unrelated declared parent must NOT
2754        // match the same parent — pins that the filter's SKIP branch
2755        // holds on the other side of the axis pair.
2756        let sibling = process_with_declared_parent(Some("seph.2"));
2757        assert_ne!(sibling.declared_parent_pid(), Some(parent_pid));
2758    }
2759
2760    // ─── Process::declared_name_override substrate pins ──────────────
2761    //
2762    // Pins the borrow-form spec-projection primitive on the declared
2763    // name-override sub-axis of the declared-identity axis that owns
2764    // the `.spec.identity.name_override.as_deref()` chain the two
2765    // hand-authored `tatara-reconciler::phase_machine` sites
2766    // (`handle_pending` DECLARE composer + `handle_forking` ALLOCATE-
2767    // PID rehydration branch) restated by hand pre-lift. Peer to the
2768    // sibling `declared_parent_pid_*` pin family on the (parent ×
2769    // name-override) sub-axis pair; both compose the same borrow-form
2770    // `Option<&str>` return-shape skeleton on distinct slots
2771    // (`spec.identity.name_override` vs `spec.identity.parent`).
2772    // Fail-before-pass-after granularity: `declared_name_override`
2773    // did not exist pre-lift, so any test invoking it fails to
2774    // compile pre-lift and passes post-lift.
2775    fn process_with_declared_name_override(name_override: Option<&str>) -> Process {
2776        let mut spec = empty_spec();
2777        spec.identity.name_override = name_override.map(str::to_string);
2778        Process::new("some-proc", spec)
2779    }
2780
2781    #[test]
2782    fn declared_name_override_returns_none_when_slot_is_none() {
2783        // Empty-slot corner pin: the primitive collapses the no-
2784        // override case to `None`, matching the pre-lift `.as_deref()`
2785        // chain's `None` byte-identically at both reconciler consumer
2786        // sites. Semantically corresponds to a Process authored
2787        // WITHOUT the human-name-override escape hatch — the default;
2788        // `derive_identity` then computes the name from the content
2789        // hash and stamps `name_override: false` on the resulting
2790        // [`Identity`].
2791        let p = process_with_declared_name_override(None);
2792        assert!(p.declared_name_override().is_none());
2793    }
2794
2795    #[test]
2796    fn declared_name_override_returns_borrowed_str_when_slot_is_populated() {
2797        // Happy-path pin: with a populated `spec.identity
2798        // .name_override` slot, the primitive returns a borrowed
2799        // `&str` whose contents match the persisted `String`. A
2800        // regression that filtered / reshaped / canonicalized the
2801        // string at the primitive (as opposed to inside
2802        // `derive_identity`, where the trim/empty-filter lives today)
2803        // would surface here rather than as silent skew between the
2804        // DECLARE composer and the ALLOCATE-PID rehydration branch on
2805        // the SAME Process spec.
2806        let p = process_with_declared_name_override(Some("observability-stack"));
2807        assert_eq!(p.declared_name_override(), Some("observability-stack"));
2808    }
2809
2810    #[test]
2811    fn declared_name_override_is_a_zero_copy_borrow_projection() {
2812        // Borrow-discipline pin: the returned `&str` borrows the
2813        // persisted `String`'s underlying byte buffer in place —
2814        // NOT a fresh allocation or a clone. Peer to the sibling
2815        // `declared_parent_pid_is_a_zero_copy_borrow_projection` pin
2816        // on the other side of the (parent × name-override) sub-axis
2817        // pair; the borrow discipline holds structurally on BOTH
2818        // sub-axes so a future `declared_identity` composite that
2819        // returns both halves together can compose them without
2820        // dropping into an owning form.
2821        let p = process_with_declared_name_override(Some("observability-stack"));
2822        let borrowed = p.declared_name_override().expect("populated slot");
2823        let persisted = p.spec.identity.name_override.as_ref().unwrap();
2824        assert!(std::ptr::eq(borrowed.as_ptr(), persisted.as_ptr()));
2825    }
2826
2827    #[test]
2828    fn declared_name_override_is_a_pure_projection() {
2829        // Purity pin: calling the projection twice on the same
2830        // `Process` returns byte-identical `&str`s (same pointer,
2831        // same length). A regression that introduced state — a
2832        // lazy-cached slice materialized on first call, a
2833        // normalization step that ran once and cached — would
2834        // surface here rather than as silent drift between the
2835        // DECLARE composer and the ALLOCATE-PID rehydration branch
2836        // within one reconcile pass.
2837        let p = process_with_declared_name_override(Some("gateway-primary"));
2838        let a = p.declared_name_override().expect("populated slot");
2839        let b = p.declared_name_override().expect("populated slot");
2840        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
2841        assert_eq!(a.len(), b.len());
2842    }
2843
2844    #[test]
2845    fn declared_name_override_matches_pre_lift_reconciler_chain_shape() {
2846        // Byte-identical parity pin between the borrow-form primitive
2847        // here and the pre-lift `tatara-reconciler::phase_machine`
2848        // `.spec.identity.name_override.as_deref()` chain shape.
2849        // Sweeps every corner every callsite plausibly encounters
2850        // (empty slot, populated with a bare name, populated with a
2851        // whitespace-containing name that `derive_identity`'s
2852        // internal trim would collapse, populated with an explicitly
2853        // empty string that `derive_identity`'s internal
2854        // `!s.is_empty()` filter would reject). A regression that
2855        // inserted a normalization step at the primitive the pre-
2856        // lift chain does NOT apply — or vice versa — surfaces here
2857        // rather than as silent drift between the pre-lift consumer
2858        // sites and the ONE substrate owner they now route through.
2859        // Peer to
2860        // `declared_parent_pid_matches_pre_lift_reconciler_chain_shape`
2861        // on the sibling sub-axis's borrow-form primitive.
2862        fn pre_lift(p: &Process) -> Option<&str> {
2863            p.spec.identity.name_override.as_deref()
2864        }
2865        // Empty slot.
2866        let p = process_with_declared_name_override(None);
2867        assert_eq!(p.declared_name_override(), pre_lift(&p));
2868        // Populated with a bare name.
2869        let p = process_with_declared_name_override(Some("observability-stack"));
2870        assert_eq!(p.declared_name_override(), pre_lift(&p));
2871        // Populated with a whitespace-containing name.
2872        let p = process_with_declared_name_override(Some("  observability-stack  "));
2873        assert_eq!(p.declared_name_override(), pre_lift(&p));
2874        // Populated with an explicitly empty string. Distinct from
2875        // the missing-slot `None` corner both at the primitive here
2876        // and at the pre-lift chain (the trim/filter that collapses
2877        // these two into the same `false`-branched
2878        // `Identity { name_override: false, .. }` lives INSIDE
2879        // `derive_identity`, NOT at the borrow site) — the primitive
2880        // MUST preserve the distinction so a future lift of the trim/
2881        // filter OUT of `derive_identity` INTO the primitive is a
2882        // conscious substrate change, not a silent one.
2883        let p = process_with_declared_name_override(Some(""));
2884        assert_eq!(p.declared_name_override(), pre_lift(&p));
2885    }
2886
2887    #[test]
2888    fn declared_name_override_preserves_raw_slot_verbatim() {
2889        // Invariance-under-`derive_identity`-normalization pin: the
2890        // primitive returns the slot's raw byte contents verbatim —
2891        // no trim, no empty-string filter, no case fold, no
2892        // normalization of any kind. `derive_identity` internally
2893        // applies `.map(str::trim).filter(|s| !s.is_empty())` before
2894        // dispatching on `Some(non_empty)` vs `None | Some(empty |
2895        // whitespace)`, but that transform lives IN `derive_identity`,
2896        // NOT at the borrow site. A regression that pulled the trim/
2897        // filter forward INTO the primitive would silently collapse
2898        // three currently-distinct corners at the borrow site (bare
2899        // populated → `Some(name)`; whitespace-only → `Some("   ")`;
2900        // empty → `Some("")`) into two (bare → `Some(name)`; the
2901        // other two → `None`). That collapse might be an intentional
2902        // substrate change some future run wants to make; if so, it
2903        // lands as a conscious edit here (with this pin updated in
2904        // the same commit) rather than as silent behavior drift.
2905        for value in ["bare", "  padded  ", "\ttabs\t", "   ", ""] {
2906            let p = process_with_declared_name_override(Some(value));
2907            assert_eq!(
2908                p.declared_name_override(),
2909                Some(value),
2910                "declared_name_override must preserve raw slot verbatim for value {value:?}"
2911            );
2912        }
2913    }
2914
2915    #[test]
2916    fn declared_name_override_composes_with_derive_identity_call_shape() {
2917        // Cross-primitive coherence pin against the [`derive_identity`]
2918        // consumer: the two live `tatara-reconciler::phase_machine`
2919        // callsites feed `p.declared_name_override()` as the second
2920        // positional argument to `derive_identity(&p.spec, …)`. This
2921        // pin exercises that exact call shape at test time so a
2922        // regression that skewed the primitive's return-form (return-
2923        // shape, borrow discipline, empty-slot collapse) surfaces
2924        // here as a shape mismatch at the [`derive_identity`] call
2925        // site rather than as silent operator-facing skew between the
2926        // DECLARE composer and the ALLOCATE-PID rehydration branch.
2927        // Populated with a bare non-empty name: `derive_identity`
2928        // dispatches on `Some(non_empty)` and stamps
2929        // `name_override: true` on the resulting [`Identity`], with
2930        // the resulting `.name` equal to the raw slot value.
2931        let p = process_with_declared_name_override(Some("gateway-primary"));
2932        let id = crate::identity::derive_identity(&p.spec, p.declared_name_override());
2933        assert!(id.name_override);
2934        assert_eq!(id.name, "gateway-primary");
2935        // Empty slot: `derive_identity` dispatches on `None` and
2936        // stamps `name_override: false` on the resulting [`Identity`],
2937        // with the resulting `.name` derived from the content hash
2938        // (NOT equal to any operator-authored slot value).
2939        let p = process_with_declared_name_override(None);
2940        let id = crate::identity::derive_identity(&p.spec, p.declared_name_override());
2941        assert!(!id.name_override);
2942    }
2943
2944    // ─── Process::observed_flux_resources substrate pins ───────────────
2945    //
2946    // Pins the borrow-form status-projection primitive that owns the
2947    // 5-line `.status.as_ref().map(|s| s.flux_resources.clone())
2948    // .unwrap_or_default()` chain the two hand-authored
2949    // `tatara-reconciler::phase_machine` sites (`handle_running` +
2950    // `handle_attested`) restated by hand pre-lift. Fail-before-pass-
2951    // after granularity: a regression that widened the missing-`status`
2952    // corner, dropped the slot, or drifted the borrow discipline
2953    // surfaces here rather than as silent operator-facing skew between
2954    // the VERIFY-phase readiness probe and the ATTEST-heartbeat drift
2955    // detector.
2956
2957    fn sample_flux_ref(name: &str) -> FluxResourceRef {
2958        // Distinct slot values so a swap between adjacent tuple
2959        // positions surfaces as an equality failure at the assertion
2960        // site — a slot-inversion regression cannot masquerade as
2961        // identity by accident. Peer to the sibling
2962        // `tatara_process::status::tests::sample_flux_ref` discipline
2963        // on the fetch-coords axis.
2964        FluxResourceRef {
2965            api_version: "kustomize.toolkit.fluxcd.io/v1".to_string(),
2966            kind: "Kustomization".to_string(),
2967            name: name.to_string(),
2968            namespace: "flux-system".to_string(),
2969            ready: false,
2970            message: None,
2971            last_check: None,
2972        }
2973    }
2974
2975    fn process_with_flux_resources(refs: Vec<FluxResourceRef>) -> Process {
2976        let mut p = Process::new("api-gateway", empty_spec());
2977        p.metadata.namespace = Some("prod".into());
2978        let mut status = ProcessStatus::default();
2979        status.flux_resources = refs;
2980        p.status = Some(status);
2981        p
2982    }
2983
2984    #[test]
2985    fn observed_flux_resources_returns_empty_slice_when_status_is_none() {
2986        // Missing-`status` corner pin: the primitive collapses the
2987        // no-status case to `&[]` so downstream `.is_empty()` /
2988        // `.len()` / iteration behave identically on a `Process`
2989        // whose status field is `None` and on one whose status
2990        // carries an empty `flux_resources` slot. Matches the
2991        // pre-lift `.unwrap_or_default()`'s empty-`Vec` corner
2992        // byte-identically at every reconciler consumer's downstream
2993        // shape.
2994        let mut p = Process::new("api", empty_spec());
2995        p.status = None;
2996        assert!(p.observed_flux_resources().is_empty());
2997        assert_eq!(p.observed_flux_resources().len(), 0);
2998    }
2999
3000    #[test]
3001    fn observed_flux_resources_returns_empty_slice_when_flux_resources_is_empty() {
3002        // Zero-refs-under-populated-status corner pin: the primitive
3003        // returns an empty slice, matching the missing-`status`
3004        // corner byte-identically. A regression that treated the two
3005        // corners differently (a `None`-vs-empty signal that
3006        // downstream consumers could grep on) would silently promote
3007        // an internal representation detail (whether the reconciler
3008        // has ever written a status subresource) into observable
3009        // behavior.
3010        let p = process_with_flux_resources(vec![]);
3011        assert!(p.observed_flux_resources().is_empty());
3012        assert_eq!(p.observed_flux_resources().len(), 0);
3013    }
3014
3015    #[test]
3016    fn observed_flux_resources_returns_slice_of_persisted_vec() {
3017        // Happy-path pin: with a populated `status.flux_resources`
3018        // slot, the primitive returns a borrowed slice whose length
3019        // and per-element identity match the persisted vector. A
3020        // regression that filtered / reshaped / deduplicated the
3021        // slice would surface here rather than as silent skew at the
3022        // downstream fetch consumers.
3023        let refs = vec![
3024            sample_flux_ref("observability-stack"),
3025            sample_flux_ref("gateway"),
3026        ];
3027        let p = process_with_flux_resources(refs.clone());
3028        let observed = p.observed_flux_resources();
3029        assert_eq!(observed.len(), 2);
3030        assert_eq!(observed[0].name, "observability-stack");
3031        assert_eq!(observed[1].name, "gateway");
3032    }
3033
3034    #[test]
3035    fn observed_flux_resources_is_a_zero_copy_borrow_projection() {
3036        // Borrow-discipline pin: the returned slice borrows the
3037        // persisted `Vec<FluxResourceRef>` in place — NOT a fresh
3038        // allocation or a clone. A regression that switched the
3039        // projection to owned refs (via `.clone()` or `.to_vec()`)
3040        // would defeat the zero-copy contract the lift's primary
3041        // strict-widening delivers (the pre-lift 5-line chain
3042        // eagerly cloned the whole vector per reconcile pass; the
3043        // post-lift primitive borrows). Peer to the sibling
3044        // `flux_resource_ref_fetch_coords_returns_borrows_of_owned_slots`
3045        // pin on the per-ref borrow-projection axis.
3046        let refs = vec![sample_flux_ref("observability-stack")];
3047        let p = process_with_flux_resources(refs);
3048        let observed = p.observed_flux_resources();
3049        let persisted = &p.status.as_ref().unwrap().flux_resources;
3050        assert!(std::ptr::eq(observed.as_ptr(), persisted.as_ptr()));
3051    }
3052
3053    #[test]
3054    fn observed_flux_resources_is_a_pure_projection() {
3055        // Purity pin: calling the projection twice on the same
3056        // `Process` returns byte-identical slices (same pointer,
3057        // same length). A regression that introduced state — a
3058        // lazy-cached slice materialized on first call, a
3059        // normalization step that ran once and cached — would
3060        // surface here rather than as silent drift between the
3061        // VERIFY-phase and ATTEST-heartbeat consumers on the SAME
3062        // `Process` within one reconcile pass.
3063        let refs = vec![sample_flux_ref("observability-stack")];
3064        let p = process_with_flux_resources(refs);
3065        let a = p.observed_flux_resources();
3066        let b = p.observed_flux_resources();
3067        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
3068        assert_eq!(a.len(), b.len());
3069    }
3070
3071    #[test]
3072    fn observed_flux_resources_matches_pre_lift_reconciler_chain_shape() {
3073        // Byte-identical parity pin between the borrow-form primitive
3074        // here and the pre-lift `tatara-reconciler::phase_machine`
3075        // 5-line chain shape. Sweeps every corner every callsite
3076        // plausibly encounters (missing status, empty flux_resources,
3077        // populated flux_resources with one ref, populated with
3078        // multiple refs). A regression that inserted a normalization
3079        // step at the primitive the pre-lift chain does NOT apply —
3080        // or vice versa — surfaces here rather than as silent drift
3081        // between the pre-lift consumer sites and the ONE substrate
3082        // owner they now route through. Peer to
3083        // `coordinates_or_none_matches_pre_lift_reconciler_helper_shape`
3084        // on the metadata axis's borrow-form primitive.
3085        // `FluxResourceRef` does not derive `PartialEq` — the parity
3086        // check walks the per-ref fetch-coords tuple (the same 4-slot
3087        // borrow projection every downstream fetch consumer routes
3088        // through) so a regression that reshaped ANY slot at ANY
3089        // index surfaces here through the sibling
3090        // `FluxResourceRef::fetch_coords` typed projection.
3091        fn pre_lift(p: &Process) -> Vec<FluxResourceRef> {
3092            p.status
3093                .as_ref()
3094                .map(|s| s.flux_resources.clone())
3095                .unwrap_or_default()
3096        }
3097        fn coord_shape(refs: &[FluxResourceRef]) -> Vec<(String, String, String, String)> {
3098            refs.iter()
3099                .map(|r| {
3100                    let (ns, av, kind, name) = r.fetch_coords();
3101                    (
3102                        ns.to_string(),
3103                        av.to_string(),
3104                        kind.to_string(),
3105                        name.to_string(),
3106                    )
3107                })
3108                .collect()
3109        }
3110        // Missing status.
3111        let mut p = Process::new("api", empty_spec());
3112        p.status = None;
3113        assert_eq!(
3114            coord_shape(p.observed_flux_resources()),
3115            coord_shape(&pre_lift(&p))
3116        );
3117        // Populated status, empty slot.
3118        let p = process_with_flux_resources(vec![]);
3119        assert_eq!(
3120            coord_shape(p.observed_flux_resources()),
3121            coord_shape(&pre_lift(&p))
3122        );
3123        // Populated status, one ref.
3124        let p = process_with_flux_resources(vec![sample_flux_ref("obs")]);
3125        assert_eq!(
3126            coord_shape(p.observed_flux_resources()),
3127            coord_shape(&pre_lift(&p))
3128        );
3129        // Populated status, multiple refs.
3130        let p = process_with_flux_resources(vec![
3131            sample_flux_ref("obs"),
3132            sample_flux_ref("gw"),
3133            sample_flux_ref("api"),
3134        ]);
3135        assert_eq!(
3136            coord_shape(p.observed_flux_resources()),
3137            coord_shape(&pre_lift(&p))
3138        );
3139    }
3140
3141    #[test]
3142    fn observed_flux_resources_missing_status_and_empty_slot_collapse_to_the_same_slice_shape() {
3143        // Cross-corner coherence pin: the missing-`status` corner and
3144        // the populated-empty-slot corner return slices whose
3145        // `.is_empty()` / `.len()` observations are IDENTICAL. A
3146        // regression that promoted the missing-`status` corner to
3147        // returning `None` (via a signature change) — or that widened
3148        // the empty-slot corner to a synthetic single-element slice
3149        // — would surface here rather than as silent operator-facing
3150        // divergence between a never-status-written Process and a
3151        // status-emptied Process.
3152        let mut p_no_status = Process::new("api", empty_spec());
3153        p_no_status.status = None;
3154        let p_empty_status = process_with_flux_resources(vec![]);
3155        assert_eq!(
3156            p_no_status.observed_flux_resources().len(),
3157            p_empty_status.observed_flux_resources().len()
3158        );
3159        assert_eq!(
3160            p_no_status.observed_flux_resources().is_empty(),
3161            p_empty_status.observed_flux_resources().is_empty()
3162        );
3163    }
3164
3165    #[test]
3166    fn observed_flux_resources_slice_preserves_persisted_ordering() {
3167        // Ordering-preservation pin: the borrowed slice preserves
3168        // the exact insertion order of the persisted vector — no
3169        // sort, no dedup, no reshape. A regression that inserted a
3170        // sort or reordering would silently misroute per-ref
3171        // observations at the downstream VERIFY-phase / ATTEST-
3172        // heartbeat consumers, both of which walk the slice
3173        // positionally and correlate the position to the observed
3174        // readiness.
3175        let refs = vec![
3176            sample_flux_ref("z-last"),
3177            sample_flux_ref("a-first"),
3178            sample_flux_ref("m-middle"),
3179        ];
3180        let p = process_with_flux_resources(refs);
3181        let observed = p.observed_flux_resources();
3182        assert_eq!(observed[0].name, "z-last");
3183        assert_eq!(observed[1].name, "a-first");
3184        assert_eq!(observed[2].name, "m-middle");
3185    }
3186
3187    // ─── Process::observed_pid substrate pins ─────────────────────────
3188    //
3189    // Pins the borrow-form status-projection primitive on the PID axis
3190    // that owns the 3-line `.status.as_ref().and_then(|s| s.pid.clone())`
3191    // chain the two hand-authored `tatara-reconciler::phase_machine`
3192    // sites (`handle_forking` ALLOCATE-PID gate + `handle_exiting`
3193    // SIGTERM cascade) restated by hand pre-lift. Peer to the sibling
3194    // `observed_flux_resources_*` pin family on the flux-resources
3195    // axis; both compose the missing-`status` fallback + borrow-form
3196    // return-shape skeleton on distinct `ProcessStatus` slots. Fail-
3197    // before-pass-after granularity: `observed_pid` did not exist
3198    // pre-lift, so any test invoking it fails to compile pre-lift and
3199    // passes post-lift.
3200
3201    fn process_with_pid(pid: Option<&str>) -> Process {
3202        let mut p = Process::new("api-gateway", empty_spec());
3203        p.metadata.namespace = Some("prod".into());
3204        let mut status = ProcessStatus::default();
3205        status.pid = pid.map(str::to_string);
3206        p.status = Some(status);
3207        p
3208    }
3209
3210    #[test]
3211    fn observed_pid_returns_none_when_status_is_none() {
3212        // Missing-`status` corner pin: the primitive collapses the
3213        // no-status case to `None` so downstream `.is_some()` /
3214        // `if let Some(_)` / `.map(...)` behave identically on a
3215        // `Process` whose status field is `None` and on one whose
3216        // status carries an unpopulated `pid` slot. Matches the
3217        // pre-lift `.and_then(...)` chain's `None` byte-identically
3218        // at every reconciler consumer's downstream shape.
3219        let mut p = Process::new("api", empty_spec());
3220        p.status = None;
3221        assert!(p.observed_pid().is_none());
3222    }
3223
3224    #[test]
3225    fn observed_pid_returns_none_when_pid_slot_is_none() {
3226        // Empty-slot-under-populated-status corner pin: the
3227        // primitive returns `None`, matching the missing-`status`
3228        // corner byte-identically. A regression that treated the
3229        // two corners differently (a `None`-vs-`Some("")` signal
3230        // that downstream consumers could grep on) would silently
3231        // promote an internal representation detail (whether the
3232        // reconciler has ever written a status subresource) into
3233        // observable behavior at the ALLOCATE-PID gate.
3234        let p = process_with_pid(None);
3235        assert!(p.observed_pid().is_none());
3236    }
3237
3238    #[test]
3239    fn observed_pid_returns_borrowed_str_when_pid_slot_is_populated() {
3240        // Happy-path pin: with a populated `status.pid` slot, the
3241        // primitive returns a borrowed `&str` whose contents match
3242        // the persisted `String`. A regression that filtered /
3243        // reshaped / canonicalized the string would surface here
3244        // rather than as silent skew at the downstream cascade
3245        // comparator's `.as_deref() == Some(...)` equality check.
3246        let p = process_with_pid(Some("seph.1.7"));
3247        assert_eq!(p.observed_pid(), Some("seph.1.7"));
3248    }
3249
3250    #[test]
3251    fn observed_pid_is_a_zero_copy_borrow_projection() {
3252        // Borrow-discipline pin: the returned `&str` borrows the
3253        // persisted `String`'s underlying byte buffer in place —
3254        // NOT a fresh allocation or a clone. A regression that
3255        // switched the projection to an owned `String` (via
3256        // `.clone()` or `.to_owned()`) would defeat the zero-copy
3257        // contract the lift's primary strict-widening delivers
3258        // (the pre-lift 3-line chain eagerly cloned the `String`
3259        // per reconcile pass at BOTH call sites even though the
3260        // ALLOCATE-PID gate immediately dropped the clone and the
3261        // SIGTERM cascade only re-borrowed it via `.as_str()`; the
3262        // post-lift primitive borrows). Peer to the sibling
3263        // `observed_flux_resources_is_a_zero_copy_borrow_projection`
3264        // pin on the flux-resources borrow-projection axis.
3265        let p = process_with_pid(Some("seph.1.7"));
3266        let observed = p.observed_pid().expect("populated slot");
3267        let persisted = p.status.as_ref().unwrap().pid.as_ref().unwrap();
3268        assert!(std::ptr::eq(observed.as_ptr(), persisted.as_ptr()));
3269    }
3270
3271    #[test]
3272    fn observed_pid_is_a_pure_projection() {
3273        // Purity pin: calling the projection twice on the same
3274        // `Process` returns byte-identical `&str`s (same pointer,
3275        // same length). A regression that introduced state — a
3276        // lazy-cached slice materialized on first call, a
3277        // normalization step that ran once and cached — would
3278        // surface here rather than as silent drift between the
3279        // ALLOCATE-PID gate and the SIGTERM cascade on the SAME
3280        // `Process` within one reconcile pass.
3281        let p = process_with_pid(Some("seph.1.7"));
3282        let a = p.observed_pid().expect("populated slot");
3283        let b = p.observed_pid().expect("populated slot");
3284        assert!(std::ptr::eq(a.as_ptr(), b.as_ptr()));
3285        assert_eq!(a.len(), b.len());
3286    }
3287
3288    #[test]
3289    fn observed_pid_matches_pre_lift_reconciler_chain_shape() {
3290        // Byte-identical parity pin between the borrow-form
3291        // primitive here and the pre-lift `tatara-reconciler
3292        // ::phase_machine` 3-line chain shape. Sweeps every corner
3293        // every callsite plausibly encounters (missing status,
3294        // empty pid slot, populated pid slot). A regression that
3295        // inserted a normalization step at the primitive the pre-
3296        // lift chain does NOT apply — or vice versa — surfaces
3297        // here rather than as silent drift between the pre-lift
3298        // consumer sites and the ONE substrate owner they now
3299        // route through. Peer to
3300        // `observed_flux_resources_matches_pre_lift_reconciler_chain_shape`
3301        // on the flux-resources axis's borrow-form primitive.
3302        fn pre_lift(p: &Process) -> Option<String> {
3303            p.status.as_ref().and_then(|s| s.pid.clone())
3304        }
3305        // Missing status.
3306        let mut p = Process::new("api", empty_spec());
3307        p.status = None;
3308        assert_eq!(p.observed_pid().map(str::to_string), pre_lift(&p));
3309        // Populated status, empty pid slot.
3310        let p = process_with_pid(None);
3311        assert_eq!(p.observed_pid().map(str::to_string), pre_lift(&p));
3312        // Populated status, populated pid slot.
3313        let p = process_with_pid(Some("seph.1.7"));
3314        assert_eq!(p.observed_pid().map(str::to_string), pre_lift(&p));
3315    }
3316
3317    #[test]
3318    fn observed_pid_missing_status_and_empty_slot_collapse_to_the_same_option_shape() {
3319        // Cross-corner coherence pin: the missing-`status` corner
3320        // and the populated-empty-slot corner return `Option`s whose
3321        // `.is_none()` observations are IDENTICAL. A regression
3322        // that promoted the missing-`status` corner to returning a
3323        // typed error (via a signature change to `Result<_, _>`) —
3324        // or that widened the empty-slot corner to a synthetic
3325        // `Some("")` — would surface here rather than as silent
3326        // operator-facing divergence between a never-status-
3327        // written Process and a status-emptied Process on the
3328        // ALLOCATE-PID gate.
3329        let mut p_no_status = Process::new("api", empty_spec());
3330        p_no_status.status = None;
3331        let p_empty_slot = process_with_pid(None);
3332        assert_eq!(
3333            p_no_status.observed_pid().is_none(),
3334            p_empty_slot.observed_pid().is_none()
3335        );
3336        assert_eq!(
3337            p_no_status.observed_pid().is_some(),
3338            p_empty_slot.observed_pid().is_some()
3339        );
3340    }
3341
3342    #[test]
3343    fn observed_pid_preserves_hierarchical_pid_format() {
3344        // Format-preservation pin: the hierarchical PID path
3345        // (dotted-segment form `seph.1.7`, matching the ported
3346        // `convergence-controller/src/identity.rs` scheme) reaches
3347        // the caller with segments and separators byte-identical
3348        // to the persisted `String`. A regression that inserted a
3349        // canonicalization pass (a segment-count validator, a
3350        // separator swap `.` → `/`, a leading/trailing whitespace
3351        // trim) would silently misroute the SIGTERM cascade's
3352        // `spec.identity.parent == Some(pid)` comparator against
3353        // children whose `parent` field was authored in the ported
3354        // scheme's exact form.
3355        for pid in ["seph", "seph.1", "seph.1.7", "seph.1.7.42"] {
3356            let p = process_with_pid(Some(pid));
3357            assert_eq!(p.observed_pid(), Some(pid));
3358        }
3359    }
3360
3361    // ─── Process::observed_attestation substrate pins ─────────────────
3362    //
3363    // Pins the borrow-form status-projection primitive on the
3364    // attestation-chain axis that owns the 3-line
3365    // `.status.as_ref().and_then(|s| s.attestation.as_ref())` chain
3366    // the two hand-authored `tatara-reconciler` sites
3367    // (`phase_machine::advance_to_attested` ATTEST composer +
3368    // `render::render_export_jobs` export-Job builder) restated by
3369    // hand pre-lift. Peer to the sibling `observed_pid_*` +
3370    // `observed_flux_resources_*` pin families; all three compose
3371    // the missing-`status` fallback + borrow-form return-shape
3372    // skeleton on distinct `ProcessStatus` slots. Fail-before-pass-
3373    // after granularity: `observed_attestation` did not exist
3374    // pre-lift, so any test invoking it fails to compile pre-lift
3375    // and passes post-lift.
3376
3377    fn sample_attestation(artifact: &str, intent: &str) -> ProcessAttestation {
3378        // Distinct pillar strings so a regression that swapped the
3379        // artifact / intent pillars silently surfaces as an
3380        // equality failure at the composed-root parity pin.
3381        ProcessAttestation::initial(artifact.to_string(), None, intent.to_string())
3382    }
3383
3384    fn process_with_attestation(attestation: Option<ProcessAttestation>) -> Process {
3385        let mut p = Process::new("api-gateway", empty_spec());
3386        p.metadata.namespace = Some("prod".into());
3387        let mut status = ProcessStatus::default();
3388        status.attestation = attestation;
3389        p.status = Some(status);
3390        p
3391    }
3392
3393    #[test]
3394    fn observed_attestation_returns_none_when_status_is_none() {
3395        // Missing-`status` corner pin: the primitive collapses the
3396        // no-status case to `None` so downstream `.is_some()` /
3397        // `if let Some(_)` / `.map(...)` behave identically on a
3398        // `Process` whose status field is `None` and on one whose
3399        // status carries an unpopulated `attestation` slot.
3400        // Matches the pre-lift `.and_then(...)` chain's `None`
3401        // byte-identically at every reconciler consumer's
3402        // downstream shape.
3403        let mut p = Process::new("api", empty_spec());
3404        p.status = None;
3405        assert!(p.observed_attestation().is_none());
3406    }
3407
3408    #[test]
3409    fn observed_attestation_returns_none_when_attestation_slot_is_none() {
3410        // Empty-slot-under-populated-status corner pin: the
3411        // primitive returns `None`, matching the missing-`status`
3412        // corner byte-identically. A regression that treated the
3413        // two corners differently (a `None`-vs-`Some(_)` signal
3414        // that downstream consumers could grep on) would silently
3415        // promote an internal representation detail (whether the
3416        // reconciler has ever written a status subresource) into
3417        // observable behavior at the ATTEST composer's
3418        // seed-vs-chain branch.
3419        let p = process_with_attestation(None);
3420        assert!(p.observed_attestation().is_none());
3421    }
3422
3423    #[test]
3424    fn observed_attestation_returns_borrow_when_slot_is_populated() {
3425        // Happy-path pin: with a populated `status.attestation`
3426        // slot, the primitive returns a borrowed
3427        // `&ProcessAttestation` whose fields match the persisted
3428        // record. A regression that filtered / reshaped /
3429        // canonicalized the record would surface here rather than
3430        // as silent skew at the downstream `prior.next(pillars)`
3431        // chain composer + the ephemeral-export receipt's
3432        // `previous_root` linker.
3433        let att = sample_attestation("art-1", "int-1");
3434        let composed_root = att.composed_root.clone();
3435        let p = process_with_attestation(Some(att));
3436        let observed = p.observed_attestation().expect("populated slot");
3437        assert_eq!(observed.artifact_hash, "art-1");
3438        assert_eq!(observed.intent_hash, "int-1");
3439        assert_eq!(observed.composed_root, composed_root);
3440        assert_eq!(observed.generation, 0);
3441        assert!(observed.previous_root.is_none());
3442    }
3443
3444    #[test]
3445    fn observed_attestation_is_a_zero_copy_borrow_projection() {
3446        // Borrow-discipline pin: the returned reference points at
3447        // the persisted `ProcessAttestation` in place — NOT a fresh
3448        // allocation or a clone. A regression that switched the
3449        // projection to an owned `ProcessAttestation` (via
3450        // `.clone()`) would defeat the zero-copy contract the
3451        // lift's primary strict-widening delivers (the pre-lift
3452        // 3-line chain returned a borrow, but the export-Job
3453        // builder then cloned `composed_root` off it; the post-
3454        // lift primitive preserves the borrow all the way to the
3455        // consumer's own cloning choice). Peer to the sibling
3456        // `observed_pid_is_a_zero_copy_borrow_projection` +
3457        // `observed_flux_resources_is_a_zero_copy_borrow_projection`
3458        // pins on the PID + flux-resources borrow-projection axes.
3459        let att = sample_attestation("art-1", "int-1");
3460        let p = process_with_attestation(Some(att));
3461        let observed = p.observed_attestation().expect("populated slot") as *const _;
3462        let persisted = p.status.as_ref().unwrap().attestation.as_ref().unwrap() as *const _;
3463        assert!(std::ptr::eq(observed, persisted));
3464    }
3465
3466    #[test]
3467    fn observed_attestation_is_a_pure_projection() {
3468        // Purity pin: calling the projection twice on the same
3469        // `Process` returns byte-identical borrows (same pointer).
3470        // A regression that introduced state — a lazy-cached
3471        // reference materialized on first call, a normalization
3472        // step that ran once and cached — would surface here
3473        // rather than as silent drift between the ATTEST composer
3474        // and the ephemeral-export receipt chain on the SAME
3475        // `Process` within one reconcile pass.
3476        let att = sample_attestation("art-1", "int-1");
3477        let p = process_with_attestation(Some(att));
3478        let a = p.observed_attestation().expect("populated slot") as *const _;
3479        let b = p.observed_attestation().expect("populated slot") as *const _;
3480        assert!(std::ptr::eq(a, b));
3481    }
3482
3483    #[test]
3484    fn observed_attestation_matches_pre_lift_reconciler_chain_shape() {
3485        // Byte-identical parity pin between the borrow-form
3486        // primitive here and the pre-lift `tatara-reconciler`
3487        // 3-line chain shape. Sweeps every corner every callsite
3488        // plausibly encounters (missing status, empty attestation
3489        // slot, populated attestation slot). A regression that
3490        // inserted a normalization step at the primitive the pre-
3491        // lift chain does NOT apply — or vice versa — surfaces
3492        // here rather than as silent drift between the pre-lift
3493        // consumer sites and the ONE substrate owner they now
3494        // route through. Peer to
3495        // `observed_pid_matches_pre_lift_reconciler_chain_shape` +
3496        // `observed_flux_resources_matches_pre_lift_reconciler_chain_shape`
3497        // on the PID + flux-resources axes.
3498        // `ProcessAttestation` does not derive `PartialEq` — the
3499        // parity check walks the `composed_root` field (the
3500        // byte-string every downstream consumer keys off) so a
3501        // regression that reshaped the record without touching
3502        // the composed-root observation surfaces here through
3503        // the receipt-chain projection.
3504        fn pre_lift(p: &Process) -> Option<String> {
3505            p.status
3506                .as_ref()
3507                .and_then(|s| s.attestation.as_ref())
3508                .map(|a| a.composed_root.clone())
3509        }
3510        // Missing status.
3511        let mut p = Process::new("api", empty_spec());
3512        p.status = None;
3513        assert_eq!(
3514            p.observed_attestation().map(|a| a.composed_root.clone()),
3515            pre_lift(&p)
3516        );
3517        // Populated status, empty attestation slot.
3518        let p = process_with_attestation(None);
3519        assert_eq!(
3520            p.observed_attestation().map(|a| a.composed_root.clone()),
3521            pre_lift(&p)
3522        );
3523        // Populated status, populated attestation slot.
3524        let p = process_with_attestation(Some(sample_attestation("art-1", "int-1")));
3525        assert_eq!(
3526            p.observed_attestation().map(|a| a.composed_root.clone()),
3527            pre_lift(&p)
3528        );
3529    }
3530
3531    #[test]
3532    fn observed_attestation_missing_status_and_empty_slot_collapse_to_the_same_option_shape() {
3533        // Cross-corner coherence pin: the missing-`status` corner
3534        // and the populated-empty-slot corner return `Option`s
3535        // whose `.is_none()` observations are IDENTICAL. A
3536        // regression that promoted the missing-`status` corner to
3537        // returning a typed error (via a signature change to
3538        // `Result<_, _>`) — or that widened the empty-slot corner
3539        // to a synthetic `Some(default_attestation)` — would
3540        // surface here rather than as silent operator-facing
3541        // divergence between a never-status-written Process and
3542        // an attestation-emptied Process on the ATTEST composer's
3543        // seed-vs-chain branch.
3544        let mut p_no_status = Process::new("api", empty_spec());
3545        p_no_status.status = None;
3546        let p_empty_slot = process_with_attestation(None);
3547        assert_eq!(
3548            p_no_status.observed_attestation().is_none(),
3549            p_empty_slot.observed_attestation().is_none()
3550        );
3551        assert_eq!(
3552            p_no_status.observed_attestation().is_some(),
3553            p_empty_slot.observed_attestation().is_some()
3554        );
3555    }
3556
3557    #[test]
3558    fn observed_attestation_preserves_chain_generation_field() {
3559        // Generation-preservation pin: a chained attestation
3560        // (`prior.next(...)` at generation N ≥ 1 with a
3561        // `previous_root` linked to `prior.composed_root`) reaches
3562        // the caller with its `generation` counter + `previous_root`
3563        // link byte-identical to the persisted record. The pre-lift
3564        // ATTEST composer discriminated exactly on this borrow's
3565        // `Some(prior)` vs `None` arm; a regression that dropped
3566        // the chain's `generation` counter (say, by folding
3567        // `next(...)` into a fresh `initial(...)` on every
3568        // reconcile pass) would silently reset every chain and
3569        // orphan every downstream `previous_root` link, but that
3570        // drift is invisible to a Process CRD reader who only
3571        // observes the LATEST composed_root.
3572        let prior = sample_attestation("art-0", "int-0");
3573        let chained = prior.next("art-1".to_string(), None, "int-1".to_string());
3574        let expected_generation = chained.generation;
3575        let expected_previous = chained.previous_root.clone();
3576        let p = process_with_attestation(Some(chained));
3577        let observed = p.observed_attestation().expect("populated slot");
3578        assert_eq!(observed.generation, expected_generation);
3579        assert_eq!(observed.generation, 1);
3580        assert_eq!(observed.previous_root, expected_previous);
3581        assert_eq!(
3582            observed.previous_root.as_deref(),
3583            Some(prior.composed_root.as_str())
3584        );
3585    }
3586
3587    // ─── Process::observed_identity substrate pins ────────────────────
3588    //
3589    // The borrow-form status-projection primitive on the resolved-
3590    // identity axis. Collapses the paired 3-line `.status.as_ref()
3591    // .and_then(|s| s.identity.<clone|as_ref>())` chain every
3592    // consumer in `tatara-reconciler` restated by hand pre-lift at
3593    // TWO sites (`phase_machine::handle_forking` seed +
3594    // `ssapply::inject_annotations` content-hash annotation
3595    // composer). Peer to the sibling `observed_pid_*` +
3596    // `observed_attestation_*` + `observed_flux_resources_*` pin
3597    // families; all four compose the same missing-`status` fallback
3598    // + borrow-form return-shape skeleton on distinct
3599    // `ProcessStatus` slots. Each pin fails-before-pass-after
3600    // granularity: `observed_identity` did not exist pre-lift, so
3601    // any test invoking it fails to compile pre-lift and passes
3602    // post-lift.
3603
3604    fn sample_identity(name: &str) -> Identity {
3605        // Distinct name + content_hash + override flag so a
3606        // regression that reshaped one slot surfaces at the
3607        // populated-slot pin's field-equality check without
3608        // aliasing the sibling slots.
3609        Identity {
3610            name: name.to_string(),
3611            content_hash: "a".repeat(26),
3612            name_override: true,
3613        }
3614    }
3615
3616    fn process_with_identity(identity: Option<Identity>) -> Process {
3617        let mut p = Process::new("api-gateway", empty_spec());
3618        p.metadata.namespace = Some("prod".into());
3619        let mut status = ProcessStatus::default();
3620        status.identity = identity;
3621        p.status = Some(status);
3622        p
3623    }
3624
3625    #[test]
3626    fn observed_identity_returns_none_when_status_is_none() {
3627        // Missing-`status` corner pin: the primitive collapses the
3628        // no-status case to `None` so downstream `.is_some()` /
3629        // `if let Some(_)` / `.cloned().unwrap_or_else(...)` behave
3630        // identically on a `Process` whose status field is `None`
3631        // and on one whose status carries an unpopulated `identity`
3632        // slot. Matches the pre-lift `.and_then(...)` chain's `None`
3633        // byte-identically at every reconciler consumer's
3634        // downstream shape.
3635        let mut p = Process::new("api", empty_spec());
3636        p.status = None;
3637        assert!(p.observed_identity().is_none());
3638    }
3639
3640    #[test]
3641    fn observed_identity_returns_none_when_identity_slot_is_none() {
3642        // Empty-slot-under-populated-status corner pin: the
3643        // primitive returns `None`, matching the missing-`status`
3644        // corner byte-identically. A regression that treated the
3645        // two corners differently (a `None`-vs-`Some(_)` signal
3646        // that downstream consumers could grep on) would silently
3647        // promote an internal representation detail (whether the
3648        // reconciler has ever written a status subresource) into
3649        // observable behavior at the FORK-time `derive_identity`
3650        // fallback branch.
3651        let p = process_with_identity(None);
3652        assert!(p.observed_identity().is_none());
3653    }
3654
3655    #[test]
3656    fn observed_identity_returns_borrow_when_slot_is_populated() {
3657        // Happy-path pin: with a populated `status.identity` slot,
3658        // the primitive returns a borrowed `&Identity` whose fields
3659        // match the persisted record. A regression that filtered /
3660        // reshaped / canonicalized the record would surface here
3661        // rather than as silent skew at the FORK-time seed's
3662        // `.cloned().unwrap_or_else(derive_identity)` composition
3663        // + the SSA-time content-hash annotation stamp on the SAME
3664        // Process.
3665        let id = sample_identity("seph");
3666        let expected = id.clone();
3667        let p = process_with_identity(Some(id));
3668        let observed = p.observed_identity().expect("populated slot");
3669        assert_eq!(observed, &expected);
3670        assert_eq!(observed.name, "seph");
3671        assert_eq!(observed.content_hash, "a".repeat(26));
3672        assert!(observed.name_override);
3673    }
3674
3675    #[test]
3676    fn observed_identity_is_a_zero_copy_borrow_projection() {
3677        // Borrow-discipline pin: the returned reference points at
3678        // the persisted `Identity` in place — NOT a fresh
3679        // allocation or a clone. A regression that switched the
3680        // projection to an owned `Identity` (via `.clone()`) would
3681        // defeat the zero-copy contract the lift's primary strict-
3682        // widening delivers (the SSA-time consumer never clones the
3683        // whole `Identity`, only the `content_hash` field it stamps
3684        // onto the annotation map, so the borrow-form return
3685        // shape's happy-path allocation count is exactly ZERO).
3686        // Peer to the sibling
3687        // `observed_attestation_is_a_zero_copy_borrow_projection`
3688        // + `observed_pid_is_a_zero_copy_borrow_projection` +
3689        // `observed_flux_resources_is_a_zero_copy_borrow_projection`
3690        // pins on the attestation-chain + PID + flux-resources
3691        // borrow-projection axes.
3692        let id = sample_identity("seph");
3693        let p = process_with_identity(Some(id));
3694        let observed = p.observed_identity().expect("populated slot") as *const _;
3695        let persisted = p.status.as_ref().unwrap().identity.as_ref().unwrap() as *const _;
3696        assert!(std::ptr::eq(observed, persisted));
3697    }
3698
3699    #[test]
3700    fn observed_identity_is_a_pure_projection() {
3701        // Purity pin: calling the projection twice on the same
3702        // `Process` returns byte-identical borrows (same pointer).
3703        // A regression that introduced state — a lazy-cached
3704        // reference materialized on first call, a normalization
3705        // step that ran once and cached — would surface here
3706        // rather than as silent drift between the FORK-time
3707        // identity seed and the SSA-time content-hash annotation
3708        // stamp on the SAME `Process` within one reconcile pass.
3709        let p = process_with_identity(Some(sample_identity("seph")));
3710        let a = p.observed_identity().expect("populated slot") as *const _;
3711        let b = p.observed_identity().expect("populated slot") as *const _;
3712        assert!(std::ptr::eq(a, b));
3713    }
3714
3715    #[test]
3716    fn observed_identity_matches_pre_lift_reconciler_chain_shape() {
3717        // Byte-identical parity pin between the borrow-form
3718        // primitive here and the pre-lift `tatara-reconciler`
3719        // 3-line chain shape. Sweeps every corner every callsite
3720        // plausibly encounters (missing status, empty identity
3721        // slot, populated identity slot). A regression that
3722        // inserted a normalization step at the primitive the pre-
3723        // lift chain does NOT apply — or vice versa — surfaces
3724        // here rather than as silent drift between the pre-lift
3725        // consumer sites and the ONE substrate owner they now
3726        // route through. Peer to
3727        // `observed_attestation_matches_pre_lift_reconciler_chain_shape`
3728        // + `observed_pid_matches_pre_lift_reconciler_chain_shape`
3729        // + `observed_flux_resources_matches_pre_lift_reconciler_chain_shape`
3730        // on the attestation-chain + PID + flux-resources axes.
3731        fn pre_lift(p: &Process) -> Option<Identity> {
3732            p.status.as_ref().and_then(|s| s.identity.clone())
3733        }
3734        // Missing status.
3735        let mut p = Process::new("api", empty_spec());
3736        p.status = None;
3737        assert_eq!(p.observed_identity().cloned(), pre_lift(&p));
3738        // Populated status, empty identity slot.
3739        let p = process_with_identity(None);
3740        assert_eq!(p.observed_identity().cloned(), pre_lift(&p));
3741        // Populated status, populated identity slot.
3742        let p = process_with_identity(Some(sample_identity("seph")));
3743        assert_eq!(p.observed_identity().cloned(), pre_lift(&p));
3744    }
3745
3746    #[test]
3747    fn observed_identity_missing_status_and_empty_slot_collapse_to_the_same_option_shape() {
3748        // Cross-corner coherence pin: the missing-`status` corner
3749        // and the populated-empty-slot corner return `Option`s
3750        // whose `.is_none()` observations are IDENTICAL. A
3751        // regression that promoted the missing-`status` corner to
3752        // returning a typed error (via a signature change to
3753        // `Result<_, _>`) — or that widened the empty-slot corner
3754        // to a synthetic `Some(derive_identity(default_spec))` —
3755        // would surface here rather than as silent operator-facing
3756        // divergence between a never-status-written Process and an
3757        // identity-cleared Process on the FORK-time seed branch.
3758        let mut p_no_status = Process::new("api", empty_spec());
3759        p_no_status.status = None;
3760        let p_empty_slot = process_with_identity(None);
3761        assert_eq!(
3762            p_no_status.observed_identity().is_none(),
3763            p_empty_slot.observed_identity().is_none()
3764        );
3765        assert_eq!(
3766            p_no_status.observed_identity().is_some(),
3767            p_empty_slot.observed_identity().is_some()
3768        );
3769    }
3770
3771    #[test]
3772    fn observed_identity_cloned_composes_with_derive_identity_fallback() {
3773        // Cross-primitive composition pin: the borrow-form
3774        // primitive threaded through `.cloned().unwrap_or_else(||
3775        // derive_identity(...))` reproduces the pre-lift FORK-time
3776        // seed's owned-`Identity` shape at every corner. Binds the
3777        // exact composition the `phase_machine::handle_forking`
3778        // consumer performs: on the populated-slot corner the
3779        // reconciler-persisted `Identity` is returned verbatim (the
3780        // fallback never fires), and on both empty corners
3781        // (missing-status + empty-slot) the fallback fires
3782        // producing a fresh `derive_identity(&spec,
3783        // name_override)`. A regression that (a) swapped the
3784        // fallback direction, (b) made `.cloned()` re-derive
3785        // instead of clone, or (c) made the empty-slot corner
3786        // return a synthetic `Some(default_identity)` collides
3787        // with the fallback surfaces here rather than as silent
3788        // FORK-time PID allocator skew.
3789        let spec = empty_spec();
3790        let fallback_expected = crate::identity::derive_identity(&spec, None);
3791        // Populated-slot corner: the seed returns the persisted
3792        // identity, NOT the derive fallback.
3793        let persisted = sample_identity("seph");
3794        let p = process_with_identity(Some(persisted.clone()));
3795        let seed = p.observed_identity().cloned().unwrap_or_else(|| {
3796            crate::identity::derive_identity(&p.spec, p.declared_name_override())
3797        });
3798        assert_eq!(seed, persisted);
3799        assert_ne!(seed, fallback_expected);
3800        // Empty-slot corner: the seed fires the derive fallback.
3801        let p = process_with_identity(None);
3802        let seed = p.observed_identity().cloned().unwrap_or_else(|| {
3803            crate::identity::derive_identity(&p.spec, p.declared_name_override())
3804        });
3805        assert_eq!(seed, fallback_expected);
3806        // Missing-status corner: the seed fires the derive
3807        // fallback, byte-identical to the empty-slot corner.
3808        let mut p = Process::new("api-gateway", empty_spec());
3809        p.metadata.namespace = Some("prod".into());
3810        p.status = None;
3811        let seed = p.observed_identity().cloned().unwrap_or_else(|| {
3812            crate::identity::derive_identity(&p.spec, p.declared_name_override())
3813        });
3814        assert_eq!(seed, fallback_expected);
3815    }
3816
3817    // ─── Process::observed_phase substrate pins ───────────────────────
3818    //
3819    // The copy-form status-projection primitive on the phase axis.
3820    // Collapses the paired 3-line `.status.as_ref().map(|s| s.phase)`
3821    // chain every consumer in `tatara-reconciler` restated by hand
3822    // pre-lift at FIVE sites. Peer to the borrow-form
3823    // `observed_pid_*` + `observed_flux_resources_*` +
3824    // `observed_attestation_*` pin families; all four compose the
3825    // same missing-`status` fallback skeleton on distinct
3826    // `ProcessStatus` slots, with the phase-axis form returning
3827    // `Option<ProcessPhase>` (copy of a `Copy` scalar) rather than
3828    // `Option<&T>` (borrow) because the underlying slot is a bare
3829    // `ProcessPhase` — no allocation to borrow past, and the enum
3830    // is one byte on the wire. Each pin fails-before-pass-after
3831    // granularity: `observed_phase` did not exist pre-lift, so any
3832    // test invoking it fails to compile pre-lift and passes
3833    // post-lift.
3834
3835    fn process_with_phase(phase: Option<ProcessPhase>) -> Process {
3836        let mut p = Process::new("api-gateway", empty_spec());
3837        p.metadata.namespace = Some("prod".into());
3838        if let Some(ph) = phase {
3839            let mut status = ProcessStatus::default();
3840            status.phase = ph;
3841            p.status = Some(status);
3842        }
3843        p
3844    }
3845
3846    #[test]
3847    fn observed_phase_returns_none_when_status_is_none() {
3848        // Missing-`status` corner pin: the primitive collapses the
3849        // no-status case to `None` so downstream `.unwrap_or(...)`
3850        // at every reconciler consumer chooses the default
3851        // deliberately (`Pending` for the top-level dispatch seed
3852        // + boundary evaluator + routing groupby; `Attested` for
3853        // the released-from annotation composer). Matches the
3854        // pre-lift `.map(|s| s.phase)` chain's `None`
3855        // byte-identically at every consumer's downstream shape.
3856        let mut p = Process::new("api", empty_spec());
3857        p.status = None;
3858        assert!(p.observed_phase().is_none());
3859    }
3860
3861    #[test]
3862    fn observed_phase_returns_some_default_when_status_is_populated_with_default_phase() {
3863        // Populated-status corner pin: the primitive returns
3864        // `Some(ProcessPhase::default())` — a `ProcessStatus`
3865        // constructed via `default()` carries `phase: Pending`
3866        // because the phase field is a bare `ProcessPhase` (not
3867        // `Option<ProcessPhase>`), so there is NO "empty slot"
3868        // corner peer to the borrow-form projections' empty-slot
3869        // pins. A regression that reshaped the return type to
3870        // filter out `Pending` (treating it as "unset") would
3871        // surface here and silently break the top-level
3872        // dispatcher's Pending → Forking transition on a Process
3873        // freshly written by the reconciler.
3874        let p = process_with_phase(Some(ProcessPhase::default()));
3875        assert_eq!(p.observed_phase(), Some(ProcessPhase::Pending));
3876        assert_eq!(p.observed_phase(), Some(ProcessPhase::default()));
3877    }
3878
3879    #[test]
3880    fn observed_phase_returns_persisted_phase_when_status_is_populated() {
3881        // Happy-path pin: with a populated `status.phase` slot,
3882        // the primitive returns the persisted `ProcessPhase`.
3883        // A regression that filtered / reshaped / canonicalized
3884        // the phase would surface here rather than as silent
3885        // skew at the top-level dispatcher's phase handler
3886        // dispatch on the SAME Process.
3887        let p = process_with_phase(Some(ProcessPhase::Running));
3888        assert_eq!(p.observed_phase(), Some(ProcessPhase::Running));
3889    }
3890
3891    #[test]
3892    fn observed_phase_is_a_pure_projection() {
3893        // Purity pin: two consecutive calls return byte-identical
3894        // `Option<ProcessPhase>` values (no lazy materialization,
3895        // no interior mutation of `self`). Peer to the sibling
3896        // `observed_pid_is_a_pure_projection` +
3897        // `observed_flux_resources_is_a_pure_projection` +
3898        // `observed_attestation_is_a_pure_projection` pins; all
3899        // four bind the pure-projection discipline on the ONE
3900        // substrate accessor per status slot.
3901        let p = process_with_phase(Some(ProcessPhase::Attested));
3902        let a = p.observed_phase();
3903        let b = p.observed_phase();
3904        assert_eq!(a, b);
3905        assert_eq!(a, Some(ProcessPhase::Attested));
3906    }
3907
3908    #[test]
3909    fn observed_phase_matches_pre_lift_reconciler_chain_shape() {
3910        // Parity pin: sweeps the two corners every pre-lift
3911        // consumer plausibly encountered (missing status,
3912        // populated status with a particular phase) and compares
3913        // the substrate call against a hand-authored pre-lift
3914        // chain byte-identically. A regression that reshaped ANY
3915        // of the two corners would surface here rather than as
3916        // silent operator-facing skew between the top-level
3917        // dispatcher and any of the four other reconciler
3918        // consumers on the SAME `Process`.
3919        fn pre_lift(p: &Process) -> Option<ProcessPhase> {
3920            p.status.as_ref().map(|s| s.phase)
3921        }
3922        let mut p = Process::new("api", empty_spec());
3923        p.status = None;
3924        assert_eq!(p.observed_phase(), pre_lift(&p));
3925        let p = process_with_phase(Some(ProcessPhase::Running));
3926        assert_eq!(p.observed_phase(), pre_lift(&p));
3927        let p = process_with_phase(Some(ProcessPhase::Attested));
3928        assert_eq!(p.observed_phase(), pre_lift(&p));
3929        let p = process_with_phase(Some(ProcessPhase::Failed));
3930        assert_eq!(p.observed_phase(), pre_lift(&p));
3931    }
3932
3933    #[test]
3934    fn observed_phase_default_unwrap_matches_pre_lift_pending_default() {
3935        // Callsite-shape pin: three of the FIVE pre-lift consumers
3936        // (`controller::reconcile`, `boundary::evaluate_process_phase`,
3937        // `table_controller::stable_name_group_key`) closed the
3938        // 3-line chain with `.unwrap_or(ProcessPhase::Pending)`
3939        // (identical to `.unwrap_or_default()`). This pin binds
3940        // that call-site shape: `observed_phase().unwrap_or
3941        // (Pending)` returns `Pending` on missing status and the
3942        // persisted phase otherwise. A regression that swapped
3943        // the `None` sentinel's downstream default would surface
3944        // here rather than as silent skew at three of the five
3945        // consumer sites.
3946        let mut p = Process::new("api", empty_spec());
3947        p.status = None;
3948        assert_eq!(
3949            p.observed_phase().unwrap_or(ProcessPhase::Pending),
3950            ProcessPhase::Pending
3951        );
3952        let p = process_with_phase(Some(ProcessPhase::Running));
3953        assert_eq!(
3954            p.observed_phase().unwrap_or(ProcessPhase::Pending),
3955            ProcessPhase::Running
3956        );
3957    }
3958
3959    #[test]
3960    fn observed_phase_attested_unwrap_matches_pre_lift_released_from_default() {
3961        // Callsite-shape pin: the ONE pre-lift consumer
3962        // (`phase_machine::p_current_phase_str` — the
3963        // released-from annotation composer) closed the 3-line
3964        // chain with `.unwrap_or(ProcessPhase::Attested)` rather
3965        // than the `Default` (`Pending`). This pin binds that
3966        // call-site shape: `observed_phase().unwrap_or(Attested)`
3967        // returns `Attested` on missing status and the persisted
3968        // phase otherwise. A regression that folded the
3969        // `Attested`-default consumer into the `Pending`-default
3970        // majority would break the SIGSTOP/SIGCONT release gate's
3971        // "which annotation label to emit" branch — the pin binds
3972        // the primitive at the raw `Option<ProcessPhase>` form so
3973        // this default choice stays local at the callsite.
3974        let mut p = Process::new("api", empty_spec());
3975        p.status = None;
3976        assert_eq!(
3977            p.observed_phase().unwrap_or(ProcessPhase::Attested),
3978            ProcessPhase::Attested
3979        );
3980        let p = process_with_phase(Some(ProcessPhase::Failed));
3981        assert_eq!(
3982            p.observed_phase().unwrap_or(ProcessPhase::Attested),
3983            ProcessPhase::Failed
3984        );
3985    }
3986
3987    #[test]
3988    fn observed_phase_preserves_every_process_phase_variant() {
3989        // Round-trip pin: every `ProcessPhase` variant round-
3990        // trips through the primitive unchanged. Peer to the
3991        // sibling `observed_pid_preserves_hierarchical_pid_format`
3992        // pin's dotted-segment sweep; this pin sweeps the closed
3993        // set of `ProcessPhase` variants directly so a
3994        // canonicalization pass that dropped or reshaped one
3995        // (e.g. folded `Reconverging` back into `Execing`, or
3996        // remapped `Zombie` to `Reaped`) surfaces here rather
3997        // than as silent skew at the SIGSTOP/SIGCONT release
3998        // gate's phase-name annotation branch. Covers every
3999        // variant the `ProcessPhase::DeriveClosedSet` enumerates
4000        // so a future variant addition surfaces via the closed-
4001        // set macro rather than at a silent partial sweep.
4002        for phase in [
4003            ProcessPhase::Pending,
4004            ProcessPhase::Forking,
4005            ProcessPhase::Execing,
4006            ProcessPhase::Running,
4007            ProcessPhase::Attested,
4008            ProcessPhase::Reconverging,
4009            ProcessPhase::Releasing,
4010            ProcessPhase::Exiting,
4011            ProcessPhase::Failed,
4012            ProcessPhase::Zombie,
4013            ProcessPhase::Reaped,
4014        ] {
4015            let p = process_with_phase(Some(phase));
4016            assert_eq!(
4017                p.observed_phase(),
4018                Some(phase),
4019                "phase variant {phase:?} did not round-trip"
4020            );
4021        }
4022    }
4023
4024    // ─── Process::observed_phase_or_pending substrate pins ─────────────
4025    //
4026    // Pins the copy-form status-projection primitive on the phase
4027    // axis with the `Pending` sink applied. Sibling to the raw
4028    // `observed_phase_*` pin family on the (return-form × fallback
4029    // shape) axis pair — the raw-`Option` corner stays with the
4030    // sibling family; this pin family opens the `Pending`-defaulted
4031    // corner that four of the five pre-lift `observed_phase`
4032    // consumers wrote by hand. Fail-before-pass-after granularity:
4033    // `observed_phase_or_pending` did not exist pre-lift, so any
4034    // test invoking it fails to compile pre-lift and passes
4035    // post-lift.
4036
4037    #[test]
4038    fn observed_phase_or_pending_returns_pending_when_status_is_none() {
4039        // Missing-`status` corner pin: the primitive collapses the
4040        // no-status case to `Pending` — the sink four of the five
4041        // pre-lift `observed_phase` consumers wrote by hand
4042        // (`controller::reconcile` / `boundary::
4043        // evaluate_process_phase` / `table_controller::
4044        // stable_name_group_key` / `controller_pool::reconcile_pool`)
4045        // and the sentinel `ProcessPhase::default()` returns. A
4046        // regression that folded the `None` sink to any other phase
4047        // (e.g. `Forking` — treating "not yet observed" as "already
4048        // dispatched") would silently mis-seed the top-level
4049        // dispatcher's `Pending → Forking` transition and surface as
4050        // operator-visible reconcile-cycle skew on a freshly-forked
4051        // Process rather than at this pin.
4052        let mut p = Process::new("api", empty_spec());
4053        p.status = None;
4054        assert_eq!(p.observed_phase_or_pending(), ProcessPhase::Pending);
4055    }
4056
4057    #[test]
4058    fn observed_phase_or_pending_returns_persisted_phase_when_status_is_populated() {
4059        // Populated-status corner pin: the primitive passes through
4060        // the persisted `ProcessPhase` unchanged — the sink only
4061        // fires on missing `status`, not on a populated one carrying
4062        // a `Pending`-adjacent variant. Two variants pinned to
4063        // separate the "pass through the persisted phase" arm from
4064        // the "sink fires" arm: `Running` (mid-lifecycle) and
4065        // `Attested` (post-verify) both round-trip unchanged where
4066        // a regression that always returned `Pending` (dropped the
4067        // pass-through arm entirely) would surface here rather than
4068        // as silent skew at every reconciler's per-phase branch.
4069        let p = process_with_phase(Some(ProcessPhase::Running));
4070        assert_eq!(p.observed_phase_or_pending(), ProcessPhase::Running);
4071        let p = process_with_phase(Some(ProcessPhase::Attested));
4072        assert_eq!(p.observed_phase_or_pending(), ProcessPhase::Attested);
4073    }
4074
4075    #[test]
4076    fn observed_phase_or_pending_matches_pre_lift_unwrap_or_pending_chain_shape() {
4077        // Byte-identical parity pin: the primitive's return equals
4078        // the pre-lift two-link `.observed_phase().unwrap_or
4079        // (ProcessPhase::Pending)` chain at every one of the four
4080        // corner values (missing `status` → `Pending`, populated
4081        // with `Pending` → `Pending`, populated with a mid-lifecycle
4082        // variant → pass-through, populated with a terminal variant
4083        // → pass-through). A regression that swapped the sink to
4084        // `ProcessPhase::default()` (currently equivalent to
4085        // `Pending`) would keep this pin green until the enum's
4086        // `Default` impl drifted — the explicit `Pending` spelling
4087        // in the pin binds the operator-visible label rather than
4088        // the derived `Default`, so a future rename or reordering
4089        // of `ProcessPhase` variants that shifted `Default` off
4090        // `Pending` would surface here rather than as silent skew
4091        // at the four downstream consumer sites.
4092        let pre_lift = |p: &Process| p.observed_phase().unwrap_or(ProcessPhase::Pending);
4093        let mut p = Process::new("api", empty_spec());
4094        p.status = None;
4095        assert_eq!(p.observed_phase_or_pending(), pre_lift(&p));
4096        let p = process_with_phase(Some(ProcessPhase::Pending));
4097        assert_eq!(p.observed_phase_or_pending(), pre_lift(&p));
4098        let p = process_with_phase(Some(ProcessPhase::Running));
4099        assert_eq!(p.observed_phase_or_pending(), pre_lift(&p));
4100        let p = process_with_phase(Some(ProcessPhase::Reaped));
4101        assert_eq!(p.observed_phase_or_pending(), pre_lift(&p));
4102    }
4103
4104    #[test]
4105    fn observed_phase_or_pending_is_a_pure_projection() {
4106        // Purity pin: two back-to-back calls on the same `Process`
4107        // return the same `ProcessPhase` — the primitive stamps no
4108        // side effect (no clock read, no metadata write, no
4109        // `status` mutation) despite the sibling `observed_phase`
4110        // taking `&self` too. Peer to the sibling `observed_phase`
4111        // purity pin; a regression that folded a clock read (e.g.
4112        // "if the sink fired, stamp `phase_since = Utc::now()`")
4113        // into the primitive would surface here rather than at the
4114        // consumer sites' downstream reconcile-cycle behavior.
4115        let p = process_with_phase(Some(ProcessPhase::Running));
4116        let a = p.observed_phase_or_pending();
4117        let b = p.observed_phase_or_pending();
4118        assert_eq!(a, b);
4119    }
4120
4121    #[test]
4122    fn observed_phase_or_pending_preserves_every_process_phase_variant() {
4123        // Round-trip pin: every `ProcessPhase` variant round-trips
4124        // through the primitive unchanged when the `status` slot is
4125        // populated. Peer to the sibling `observed_phase_preserves
4126        // _every_process_phase_variant` sweep; this pin sweeps the
4127        // closed set through the `Pending`-sinked accessor rather
4128        // than the raw-`Option` accessor so a canonicalization pass
4129        // that dropped or reshaped one variant (e.g. folded
4130        // `Reconverging` back into `Execing`, remapped `Zombie` to
4131        // `Reaped`) surfaces at BOTH primitives' pin sets rather
4132        // than as silent skew at a subset of the reconciler
4133        // consumers. Covers every variant the
4134        // `ProcessPhase::DeriveClosedSet` enumerates so a future
4135        // variant addition surfaces via the closed-set macro rather
4136        // than at a silent partial sweep.
4137        for phase in [
4138            ProcessPhase::Pending,
4139            ProcessPhase::Forking,
4140            ProcessPhase::Execing,
4141            ProcessPhase::Running,
4142            ProcessPhase::Attested,
4143            ProcessPhase::Reconverging,
4144            ProcessPhase::Releasing,
4145            ProcessPhase::Exiting,
4146            ProcessPhase::Failed,
4147            ProcessPhase::Zombie,
4148            ProcessPhase::Reaped,
4149        ] {
4150            let p = process_with_phase(Some(phase));
4151            assert_eq!(
4152                p.observed_phase_or_pending(),
4153                phase,
4154                "phase variant {phase:?} did not round-trip through observed_phase_or_pending"
4155            );
4156        }
4157    }
4158
4159    // ─── Process::is_being_deleted substrate pins ───────────────────────
4160    //
4161    // Pins the copy-form metadata-projection primitive on the
4162    // deletion-tombstone axis. Peer to the borrow-form + copy-form
4163    // metadata-fallback family (`namespace_or_default`,
4164    // `name_or_placeholder`, `uid_or_empty`, `coordinates_or_defaults`,
4165    // `coordinates_or_none`, `owned_coordinates_or_err`, `annotation`);
4166    // this one opens the presence-probe corner for the tombstone slot.
4167    // Fail-before-pass-after granularity: `is_being_deleted` did not
4168    // exist pre-lift, so any test invoking it fails to compile pre-
4169    // lift and passes post-lift.
4170
4171    fn tombstoned_process() -> Process {
4172        let mut p = Process::new("api-gateway", empty_spec());
4173        p.metadata.namespace = Some("prod".into());
4174        p.metadata.deletion_timestamp = Some(k8s_openapi::apimachinery::pkg::apis::meta::v1::Time(
4175            Utc::now(),
4176        ));
4177        p
4178    }
4179
4180    #[test]
4181    fn is_being_deleted_returns_false_when_deletion_timestamp_is_absent() {
4182        // Missing-tombstone corner pin: the primitive collapses the
4183        // no-tombstone case to `false` so the SIGTERM preempt at
4184        // `controller::reconcile` skips the `→ Exiting` forcing
4185        // branch and the DELETE-skip at `handle_exiting`'s child
4186        // fan-out does NOT `continue` past a child that is still
4187        // healthy. Matches the pre-lift `.is_some()` chain's `false`
4188        // byte-identically at every consumer's downstream gate.
4189        let mut p = Process::new("api", empty_spec());
4190        p.metadata.deletion_timestamp = None;
4191        assert!(!p.is_being_deleted());
4192    }
4193
4194    #[test]
4195    fn is_being_deleted_returns_true_when_deletion_timestamp_is_present() {
4196        // Present-tombstone corner pin: the primitive returns
4197        // `true` on any populated `metadata.deletionTimestamp`
4198        // slot regardless of the timestamp payload — the two
4199        // consumers only read the tombstone's PRESENCE, never
4200        // its RFC-3339 timestamp value. A regression that gated
4201        // the `true` return on the timestamp being non-epoch, or
4202        // parsed the timestamp before returning, would surface
4203        // here rather than as silent skew at the SIGTERM preempt
4204        // or child-fan-out DELETE-skip on the SAME `Process`.
4205        let p = tombstoned_process();
4206        assert!(p.is_being_deleted());
4207    }
4208
4209    #[test]
4210    fn is_being_deleted_is_a_pure_projection() {
4211        // Purity pin: two consecutive calls return byte-identical
4212        // `bool` values (no lazy materialization, no interior
4213        // mutation of `self`). Peer to the sibling
4214        // `observed_phase_is_a_pure_projection` +
4215        // `observed_pid_is_a_pure_projection` +
4216        // `observed_flux_resources_is_a_pure_projection` +
4217        // `observed_attestation_is_a_pure_projection` pins; all
4218        // five bind the pure-projection discipline on the ONE
4219        // substrate accessor per metadata / status slot.
4220        let p = tombstoned_process();
4221        let a = p.is_being_deleted();
4222        let b = p.is_being_deleted();
4223        assert_eq!(a, b);
4224        assert!(a);
4225    }
4226
4227    #[test]
4228    fn is_being_deleted_matches_pre_lift_reconciler_chain_shape() {
4229        // Parity pin: sweeps the two corners every pre-lift
4230        // consumer plausibly encountered (missing tombstone,
4231        // present tombstone) and compares the substrate call
4232        // against a hand-authored pre-lift chain byte-identically.
4233        // A regression that reshaped either corner would surface
4234        // here rather than as silent operator-facing skew between
4235        // the top-level dispatcher's SIGTERM preempt and the
4236        // SIGTERM cascade's child-fan-out DELETE-skip on the
4237        // SAME `Process` within one reconcile pass.
4238        fn pre_lift(p: &Process) -> bool {
4239            p.metadata.deletion_timestamp.is_some()
4240        }
4241        let mut p = Process::new("api", empty_spec());
4242        p.metadata.deletion_timestamp = None;
4243        assert_eq!(p.is_being_deleted(), pre_lift(&p));
4244        let p = tombstoned_process();
4245        assert_eq!(p.is_being_deleted(), pre_lift(&p));
4246    }
4247
4248    #[test]
4249    fn is_being_deleted_composes_with_process_phase_is_alive_at_reconcile_preempt() {
4250        // Call-site-shape pin: the `controller::reconcile` SIGTERM
4251        // preempt composes `is_being_deleted() && current_phase
4252        // .is_alive()` — the tombstone-presence probe AND the
4253        // alive-phase gate must BOTH hold to force `→ Exiting`.
4254        // A dead-phase (`Zombie` / `Reaped` / `Failed`) Process
4255        // that carries a tombstone still runs its normal handler,
4256        // not the preempt. This pin binds that composition shape
4257        // at the primitive so a regression that flipped either
4258        // half of the `&&` (or that broadened the tombstone probe
4259        // to include the `is_alive` half implicitly) surfaces
4260        // here rather than as silent skew at the top-level
4261        // dispatch on the SAME `Process`.
4262        let mut p = tombstoned_process();
4263        // Alive + tombstoned → preempt fires.
4264        let mut alive = ProcessStatus::default();
4265        alive.phase = ProcessPhase::Running;
4266        p.status = Some(alive);
4267        assert!(p.is_being_deleted());
4268        assert!(p.observed_phase().unwrap_or_default().is_alive());
4269        // Dead + tombstoned → preempt does NOT fire (composition
4270        // with `is_alive` returns false).
4271        let mut dead = ProcessStatus::default();
4272        dead.phase = ProcessPhase::Reaped;
4273        p.status = Some(dead);
4274        assert!(p.is_being_deleted());
4275        assert!(!p.observed_phase().unwrap_or_default().is_alive());
4276    }
4277
4278    // ─── Process::created_at substrate pins ─────────────────────────
4279    //
4280    // Pins the copy-form metadata-projection primitive on the
4281    // `metadata.creationTimestamp` axis that owns the
4282    // `.metadata.creation_timestamp.as_ref().map(|t| t.0)` chain the
4283    // three hand-authored sites (`lifetime_clock::evaluate`,
4284    // `lifetime_clock::requeue_with_ttl`,
4285    // `tatara-reconciler::table_controller`) restated by hand pre-lift.
4286    // Peer to the sibling `is_being_deleted_*` +
4287    // `observed_phase_*` pin families — all three primitives project a
4288    // wire-format `Option<T>` slot into a `Copy` inner value at ONE
4289    // owner. Fail-before-pass-after granularity: `created_at` did not
4290    // exist pre-lift, so any test invoking it fails to compile pre-lift
4291    // and passes post-lift.
4292
4293    fn creation_stamped_process(t: DateTime<Utc>) -> Process {
4294        let mut p = Process::new("age-anchor", empty_spec());
4295        p.metadata.namespace = Some("prod".into());
4296        p.metadata.creation_timestamp =
4297            Some(k8s_openapi::apimachinery::pkg::apis::meta::v1::Time(t));
4298        p
4299    }
4300
4301    #[test]
4302    fn created_at_returns_none_when_creation_timestamp_is_absent() {
4303        // Missing-slot corner pin: the primitive collapses the
4304        // no-creation-timestamp case to `None` so the TTL-expiry gate
4305        // at `lifetime_clock::evaluate` short-circuits its inner
4306        // `if let Some(...)` branch (no elapsed computation), the
4307        // requeue-budget picker returns its default sleep, and the
4308        // stable-name arbiter's `.unwrap_or_else(Utc::now)` tail
4309        // synthesizes a "just created" anchor at its own site. Matches
4310        // the pre-lift `.as_ref().map(|t| t.0)` chain's `None`
4311        // byte-identically at every consumer's downstream tail.
4312        let mut p = Process::new("api", empty_spec());
4313        p.metadata.creation_timestamp = None;
4314        assert!(p.created_at().is_none());
4315    }
4316
4317    #[test]
4318    fn created_at_returns_some_datetime_when_slot_is_populated() {
4319        // Populated-slot corner pin: with a populated
4320        // `metadata.creationTimestamp` slot, the primitive unwraps the
4321        // wire-format `Time` newtype to its inner `DateTime<Utc>` and
4322        // returns it as `Some(datetime)` — hiding the `.0` field-access
4323        // every pre-lift consumer restated to reach the underlying
4324        // instant.
4325        let anchor = Utc::now() - chrono::Duration::seconds(300);
4326        let p = creation_stamped_process(anchor);
4327        assert_eq!(p.created_at(), Some(anchor));
4328    }
4329
4330    #[test]
4331    fn created_at_is_a_pure_projection() {
4332        // Purity pin: two consecutive calls return byte-identical
4333        // `Option<DateTime<Utc>>` values (no lazy materialization, no
4334        // interior mutation of `self`). Peer to the sibling
4335        // `is_being_deleted_is_a_pure_projection` +
4336        // `observed_phase_is_a_pure_projection` pins; all three bind
4337        // the pure-projection discipline on the ONE substrate accessor
4338        // per metadata / status slot.
4339        let anchor = Utc::now();
4340        let p = creation_stamped_process(anchor);
4341        let a = p.created_at();
4342        let b = p.created_at();
4343        assert_eq!(a, b);
4344        assert_eq!(a, Some(anchor));
4345    }
4346
4347    #[test]
4348    fn created_at_matches_pre_lift_creation_timestamp_chain_shape() {
4349        // Parity pin: sweeps the two corners every pre-lift consumer
4350        // plausibly encountered (missing slot, populated slot) and
4351        // compares the substrate call against a hand-authored pre-lift
4352        // chain byte-identically. A regression that reshaped either
4353        // corner (returning `Some(Utc::now())` on the missing slot,
4354        // returning a rounded / truncated timestamp on the populated
4355        // slot) would surface here rather than as silent operator-
4356        // facing skew between the TTL-expiry gate, the requeue-budget
4357        // picker, and the stable-name claim-arbiter tie-break on the
4358        // SAME `Process` within one reconcile pass.
4359        fn pre_lift(p: &Process) -> Option<DateTime<Utc>> {
4360            p.metadata.creation_timestamp.as_ref().map(|t| t.0)
4361        }
4362        // Missing slot.
4363        let mut p = Process::new("x", empty_spec());
4364        p.metadata.creation_timestamp = None;
4365        assert_eq!(p.created_at(), pre_lift(&p));
4366        // Populated slot.
4367        let anchor = Utc::now() - chrono::Duration::seconds(42);
4368        let p = creation_stamped_process(anchor);
4369        assert_eq!(p.created_at(), pre_lift(&p));
4370    }
4371
4372    #[test]
4373    fn created_at_composes_with_signed_duration_since_at_ttl_gate() {
4374        // Call-site-shape pin: the `lifetime_clock::evaluate` TTL-
4375        // expiry gate composes `now.signed_duration_since(creation)`
4376        // where `creation` is the `DateTime<Utc>` returned by this
4377        // primitive's `Some` corner. A regression that returned a
4378        // per-callsite `Local` timezone (or that stripped the timezone
4379        // marker) would break the arithmetic silently. This pin
4380        // computes the elapsed duration byte-identically against the
4381        // pre-lift `.map(|t| t.0)` chain so a timezone drift surfaces
4382        // here rather than as silent skew at the TTL-expiry decision
4383        // on the SAME `Process` within one reconcile pass.
4384        let now = Utc::now();
4385        let anchor = now - chrono::Duration::seconds(120);
4386        let p = creation_stamped_process(anchor);
4387        let via_primitive = p.created_at().expect("populated slot");
4388        let via_pre_lift = p
4389            .metadata
4390            .creation_timestamp
4391            .as_ref()
4392            .map(|t| t.0)
4393            .expect("populated slot");
4394        assert_eq!(
4395            now.signed_duration_since(via_primitive),
4396            now.signed_duration_since(via_pre_lift)
4397        );
4398    }
4399}