Skip to main content

eredu_runtime/
realtime_model.rs

1//! Family-blind construction of a selected layered realtime model.
2
3use std::{collections::BTreeMap, marker::PhantomData};
4
5use eredu_checkpoint::recipe::{DerivedWeightRecipe, RecipeMetadata};
6use eredu_nn::{NeuralBackend, Tensor};
7
8use crate::{
9    LayerWeightResidency, LayeredArchitecture, LayerwisePolicy, LayerwiseRuntime, ParameterBackend,
10    ParameterGroupOwner, RealtimeWeightComponentRequirement, RealtimeWeightComponentRole,
11    RealtimeWeightLoweringRequirement, RuntimeState, SelectedRealtimeRealization,
12    SubmissionBackend, WeightBinding, WeightBindingPlan,
13};
14
15/// Architecture-issued identities that bind concrete modules to one selection.
16#[derive(Debug, Clone, Eq, PartialEq)]
17pub struct RealtimeArchitectureConstructionIdentity {
18    architecture: crate::RealtimeIdentity,
19    speech_schedule: crate::RealtimeIdentity,
20    state_layout: crate::RealtimeIdentity,
21}
22
23impl RealtimeArchitectureConstructionIdentity {
24    /// Creates one exact construction witness.
25    pub fn new(
26        architecture: crate::RealtimeIdentity,
27        speech_schedule: crate::RealtimeIdentity,
28        state_layout: crate::RealtimeIdentity,
29    ) -> Self {
30        Self {
31            architecture,
32            speech_schedule,
33            state_layout,
34        }
35    }
36}
37
38/// Supplies stable semantic identities for a concrete neutral architecture.
39pub trait RealtimeArchitectureIdentity {
40    /// Returns the identities derived from the architecture's normalized policy.
41    fn realtime_construction_identity(
42        &self,
43    ) -> Result<RealtimeArchitectureConstructionIdentity, String>;
44}
45
46/// Concrete state paired with the exact realization its mechanism implemented.
47pub struct RealizedRealtimeState<S> {
48    state: S,
49    realization: crate::SelectedRealtimeStateRealization,
50}
51
52impl<S> RealizedRealtimeState<S> {
53    /// Attaches an exact state realization report to concrete storage.
54    pub fn new(state: S, realization: crate::SelectedRealtimeStateRealization) -> Self {
55        Self { state, realization }
56    }
57
58    /// Consumes concrete state and its exact realization report.
59    pub fn into_parts(self) -> (S, crate::SelectedRealtimeStateRealization) {
60        (self.state, self.realization)
61    }
62}
63
64/// Concrete layer storage paired with the exact residency it implemented.
65pub struct RealizedRealtimePolicy<P> {
66    policy: P,
67    residency: LayerWeightResidency,
68}
69
70impl<P> RealizedRealtimePolicy<P> {
71    /// Attaches the implemented residency report to a concrete policy.
72    pub fn new(policy: P, residency: LayerWeightResidency) -> Self {
73        Self { policy, residency }
74    }
75
76    /// Consumes concrete storage and its exact residency report.
77    pub fn into_parts(self) -> (P, LayerWeightResidency) {
78        (self.policy, self.residency)
79    }
80}
81
82/// One selected component paired with its exact architecture recipe payload.
83#[derive(Debug, Clone, Eq, PartialEq)]
84pub struct RealtimeMaterializationComponent {
85    requirement: RealtimeWeightComponentRequirement,
86    source_provenance: Vec<eredu_checkpoint::store::TensorSourceProvenance>,
87}
88
89impl RealtimeMaterializationComponent {
90    /// Pairs an exact selected component with its admission-time physical sources.
91    pub fn new(
92        requirement: RealtimeWeightComponentRequirement,
93        source_provenance: impl IntoIterator<Item = eredu_checkpoint::store::TensorSourceProvenance>,
94    ) -> Result<Self, RealtimeModelContractError> {
95        let source_provenance = source_provenance.into_iter().collect::<Vec<_>>();
96        if requirement.source_occurrences().len() != source_provenance.len()
97            || requirement
98                .source_occurrences()
99                .iter()
100                .zip(&source_provenance)
101                .any(|(expected, actual)| expected.as_str() != actual.catalog_key)
102        {
103            return Err(RealtimeModelContractError::SourceProvenanceMismatch {
104                target: requirement.target().as_str().to_owned(),
105            });
106        }
107        Ok(Self {
108            requirement,
109            source_provenance,
110        })
111    }
112
113    /// Returns the exact selected component requirement.
114    pub const fn requirement(&self) -> &RealtimeWeightComponentRequirement {
115        &self.requirement
116    }
117
118    /// Returns the architecture recipe for a source-backed component.
119    pub const fn recipe(&self) -> Option<&DerivedWeightRecipe> {
120        self.requirement.recipe()
121    }
122
123    /// Returns admission-time recipe output metadata.
124    pub const fn recipe_output(&self) -> Option<&RecipeMetadata> {
125        self.requirement.recipe_output()
126    }
127
128    /// Returns exact physical source provenance in recipe traversal order.
129    pub fn source_provenance(&self) -> &[eredu_checkpoint::store::TensorSourceProvenance] {
130        &self.source_provenance
131    }
132}
133
134/// Exact materialization work for one selected logical parameter target.
135#[derive(Debug, Clone, Eq, PartialEq)]
136pub struct RealtimeMaterializationTask {
137    lowering: RealtimeWeightLoweringRequirement,
138    owner: ParameterGroupOwner,
139    components: Vec<RealtimeMaterializationComponent>,
140}
141
142impl RealtimeMaterializationTask {
143    /// Creates a task whose recipe payload exactly covers the selected components.
144    pub fn new(
145        lowering: RealtimeWeightLoweringRequirement,
146        owner: ParameterGroupOwner,
147        components: impl IntoIterator<Item = RealtimeMaterializationComponent>,
148    ) -> Result<Self, RealtimeModelContractError> {
149        let components = components.into_iter().collect::<Vec<_>>();
150        let expected = lowering.components();
151        if components.len() != expected.len()
152            || components
153                .iter()
154                .zip(expected)
155                .any(|(actual, expected)| actual.requirement() != expected)
156        {
157            return Err(RealtimeModelContractError::ComponentCoverageMismatch {
158                target: lowering.target().as_str().to_owned(),
159            });
160        }
161        let primary = components
162            .iter()
163            .find(|component| {
164                component.requirement().role() == RealtimeWeightComponentRole::Primary
165            })
166            .expect("selected lowering validation guarantees one primary component");
167        if primary
168            .recipe_output()
169            .is_some_and(|output| output.shape != lowering.descriptor().physical_shape())
170        {
171            return Err(RealtimeModelContractError::RecipeGeometryMismatch {
172                target: lowering.target().as_str().to_owned(),
173            });
174        }
175        if let (Some(output), eredu_checkpoint::SourceTensorEncoding::Safetensors(stored)) =
176            (primary.recipe_output(), lowering.descriptor().source())
177        {
178            if output.dtype != eredu_checkpoint::recipe::RecipeDtype::from(stored.clone()) {
179                return Err(RealtimeModelContractError::RecipeEncodingMismatch {
180                    target: lowering.target().as_str().to_owned(),
181                });
182            }
183        }
184        Ok(Self {
185            lowering,
186            owner,
187            components,
188        })
189    }
190
191    /// Returns the selected lowering and target identity.
192    pub const fn lowering(&self) -> &RealtimeWeightLoweringRequirement {
193        &self.lowering
194    }
195
196    /// Returns the exact static or execution-unit owner.
197    pub const fn owner(&self) -> &ParameterGroupOwner {
198        &self.owner
199    }
200
201    /// Returns ordered primary and companion recipe payloads.
202    pub fn components(&self) -> &[RealtimeMaterializationComponent] {
203        &self.components
204    }
205}
206
207/// Canonical owner-partitioned bindings derived from exact realtime tasks.
208#[derive(Debug, Clone)]
209pub struct RealtimeTaskBindingPlan {
210    pinned: Vec<WeightBinding>,
211    units: BTreeMap<ParameterGroupOwner, Vec<WeightBinding>>,
212}
213
214impl RealtimeTaskBindingPlan {
215    /// Consumes the pinned and execution-unit binding partitions.
216    pub fn into_parts(
217        self,
218    ) -> (
219        Vec<WeightBinding>,
220        BTreeMap<ParameterGroupOwner, Vec<WeightBinding>>,
221    ) {
222        (self.pinned, self.units)
223    }
224}
225
226/// Validates every exact realtime task and backend recipe capability without payload access.
227///
228/// This gate is valid against the original checkpoint even when later transform
229/// work publishes authoritative packed outputs.
230pub fn preflight_realtime_materialization_tasks<B: ParameterBackend>(
231    tasks: &[RealtimeMaterializationTask],
232    source: &dyn eredu_checkpoint::store::CheckpointSource,
233) -> Result<(), RealtimeModelContractError> {
234    for task in tasks {
235        let transformed = matches!(
236            task.lowering().kind(),
237            crate::WeightLoweringKind::Transform | crate::WeightLoweringKind::DerivedTransform
238        );
239        let targets = task
240            .components()
241            .iter()
242            .map(|component| component.requirement().target().as_str())
243            .collect::<std::collections::BTreeSet<_>>();
244        for component in task.components() {
245            for admitted in component.source_provenance() {
246                let actual = source
247                    .source_provenance(&admitted.catalog_key)
248                    .map_err(|error| RealtimeModelContractError::BindingPlan {
249                        detail: error.to_string(),
250                    })?;
251                if &actual != admitted {
252                    return Err(RealtimeModelContractError::BindingPlan {
253                        detail: format!(
254                            "realtime component {:?} differs from admitted source provenance",
255                            component.requirement().target().as_str()
256                        ),
257                    });
258                }
259            }
260            if let Some(owner) = component.requirement().recipe_owner() {
261                if owner != component.requirement().target() && !targets.contains(owner.as_str()) {
262                    return Err(RealtimeModelContractError::BindingPlan {
263                        detail: format!("realtime alias owner {:?} is absent", owner.as_str()),
264                    });
265                }
266            }
267            if let Some(recipe) = component.recipe() {
268                let actual = recipe.infer(source).map_err(|error| {
269                    RealtimeModelContractError::BindingPlan {
270                        detail: error.to_string(),
271                    }
272                })?;
273                if component.recipe_output() != Some(&actual) {
274                    return Err(RealtimeModelContractError::BindingPlan {
275                        detail: format!(
276                            "realtime component {:?} recipe output drifted",
277                            component.requirement().target().as_str()
278                        ),
279                    });
280                }
281                B::preflight_recipe(recipe, source).map_err(|error| {
282                    RealtimeModelContractError::BindingPlan {
283                        detail: error.to_string(),
284                    }
285                })?;
286            } else if component.requirement().recipe_owner().is_none() && !transformed {
287                return Err(RealtimeModelContractError::BindingPlan {
288                    detail: format!(
289                        "realtime component {:?} has neither recipe nor alias owner",
290                        component.requirement().target().as_str()
291                    ),
292                });
293            }
294        }
295    }
296    Ok(())
297}
298
299/// Derives the singular canonical binding partitions from exact realtime tasks.
300pub fn realtime_task_binding_plan(
301    tasks: &[RealtimeMaterializationTask],
302    source: &dyn eredu_checkpoint::store::CheckpointSource,
303) -> Result<RealtimeTaskBindingPlan, RealtimeModelContractError> {
304    let mut pinned = Vec::new();
305    let mut units = BTreeMap::<ParameterGroupOwner, Vec<WeightBinding>>::new();
306    for task in tasks {
307        let destination = match task.owner() {
308            ParameterGroupOwner::StaticRole(_) | ParameterGroupOwner::StaticAnyOf(_) => &mut pinned,
309            ParameterGroupOwner::ExecutionUnit { .. } => {
310                units.entry(task.owner().clone()).or_default()
311            }
312        };
313        let transformed = matches!(
314            task.lowering().kind(),
315            crate::WeightLoweringKind::Transform | crate::WeightLoweringKind::DerivedTransform
316        );
317        for component in task.components() {
318            let requirement = component.requirement();
319            let target = requirement.target().as_str();
320            let binding = if transformed {
321                if !source.is_authoritative_materialized_key(target) {
322                    return Err(RealtimeModelContractError::BindingPlan {
323                        detail: format!(
324                            "transformed realtime output {target:?} is not authoritative"
325                        ),
326                    });
327                }
328                let metadata = source.source_metadata(target).map_err(|error| {
329                    RealtimeModelContractError::BindingPlan {
330                        detail: error.to_string(),
331                    }
332                })?;
333                WeightBinding::new(
334                    target,
335                    target,
336                    eredu_checkpoint::store::TensorSelection::Full,
337                    metadata.encoded_byte_len,
338                )
339            } else {
340                let output = component.recipe_output().ok_or_else(|| {
341                    RealtimeModelContractError::BindingPlan {
342                        detail: format!("realtime recipe component {target:?} has no output"),
343                    }
344                })?;
345                match requirement.recipe_owner() {
346                    Some(owner) if owner != requirement.target() => {
347                        WeightBinding::alias(target, owner.as_str(), output.byte_len())
348                    }
349                    _ => WeightBinding::from_recipe(
350                        target,
351                        component.recipe().cloned().ok_or_else(|| {
352                            RealtimeModelContractError::BindingPlan {
353                                detail: format!("realtime component {target:?} has no recipe"),
354                            }
355                        })?,
356                        output.byte_len(),
357                    ),
358                }
359            }
360            .map_err(|error| RealtimeModelContractError::BindingPlan {
361                detail: error.to_string(),
362            })?
363            .with_logical_target(task.lowering().target().as_str())
364            .map_err(|error| RealtimeModelContractError::BindingPlan {
365                detail: error.to_string(),
366            })?;
367            destination.push(binding);
368        }
369    }
370    WeightBindingPlan::new(&pinned).map_err(|error| RealtimeModelContractError::BindingPlan {
371        detail: error.to_string(),
372    })?;
373    for bindings in units.values() {
374        WeightBindingPlan::new(bindings).map_err(|error| {
375            RealtimeModelContractError::BindingPlan {
376                detail: error.to_string(),
377            }
378        })?;
379    }
380    Ok(RealtimeTaskBindingPlan { pinned, units })
381}
382
383/// Selected realization paired with complete architecture recipe payloads.
384#[derive(Debug)]
385pub struct PreparedRealtimeModelContract {
386    selected: SelectedRealtimeRealization,
387    tasks: Vec<RealtimeMaterializationTask>,
388}
389
390impl PreparedRealtimeModelContract {
391    /// Validates that one exact task exists for every selected target.
392    pub fn new(
393        selected: SelectedRealtimeRealization,
394        tasks: impl IntoIterator<Item = RealtimeMaterializationTask>,
395    ) -> Result<Self, RealtimeModelContractError> {
396        let tasks = tasks.into_iter().collect::<Vec<_>>();
397        if tasks.len() != selected.weight_lowerings().len() {
398            return Err(RealtimeModelContractError::TaskCoverageMismatch);
399        }
400        for (task, selected_lowering) in tasks.iter().zip(selected.weight_lowerings()) {
401            if selected_lowering != &task.lowering {
402                return Err(RealtimeModelContractError::TaskSelectionMismatch {
403                    target: task.lowering.target().as_str().to_owned(),
404                });
405            }
406            let expected_owner = selected
407                .execution_parameters()
408                .groups()
409                .iter()
410                .find_map(|group| {
411                    group
412                        .group()
413                        .members()
414                        .iter()
415                        .any(|member| member.target() == task.lowering.target().as_str())
416                        .then(|| group.owner())
417                })
418                .ok_or_else(|| RealtimeModelContractError::TaskOwnerUnavailable {
419                    target: task.lowering.target().as_str().to_owned(),
420                })?;
421            if expected_owner != &task.owner {
422                return Err(RealtimeModelContractError::TaskOwnerMismatch {
423                    target: task.lowering.target().as_str().to_owned(),
424                });
425            }
426        }
427        Ok(Self { selected, tasks })
428    }
429
430    /// Returns the authoritative selected realization.
431    pub const fn selected(&self) -> &SelectedRealtimeRealization {
432        &self.selected
433    }
434
435    /// Returns exact materialization work in architecture order.
436    pub fn tasks(&self) -> &[RealtimeMaterializationTask] {
437        &self.tasks
438    }
439
440    /// Consumes the contract into selection and exact work.
441    pub fn into_parts(
442        self,
443    ) -> (
444        SelectedRealtimeRealization,
445        Vec<RealtimeMaterializationTask>,
446    ) {
447        (self.selected, self.tasks)
448    }
449}
450
451/// Generic mechanisms used only to materialize and store a selected model.
452pub trait RealtimeModelConstructionMechanisms<A, B>
453where
454    B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
455    A: LayeredArchitecture<B, Self::State>,
456    Self::State: RuntimeState<B>,
457    Self::ResidentPolicy: LayerwisePolicy<B, A::Unit, Error = Self::PolicyError>,
458    Self::BoundedPolicy: LayerwisePolicy<B, A::Unit, Error = Self::PolicyError>,
459{
460    /// Concrete architecture state realization.
461    type State: RuntimeState<B>;
462    /// Shared resident/bounded policy failure.
463    type PolicyError;
464    /// Fully resident unit storage.
465    type ResidentPolicy: LayerwisePolicy<B, A::Unit, Error = Self::PolicyError>;
466    /// Host-windowed or disk-streamed unit storage.
467    type BoundedPolicy: LayerwisePolicy<B, A::Unit, Error = Self::PolicyError>;
468    /// Mechanism failure.
469    type Error;
470
471    /// Materializes and binds every resident static/unit component exactly once.
472    #[allow(clippy::too_many_arguments)]
473    fn prepare_resident_materialization(
474        &mut self,
475        architecture: &mut A,
476        units: &mut [A::Unit],
477        source_architecture: Option<&mut A>,
478        source_units: Option<&mut [A::Unit]>,
479        tasks: &[RealtimeMaterializationTask],
480        selected: &SelectedRealtimeRealization,
481        context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
482    ) -> Result<(), Self::Error>;
483
484    /// Builds fully resident storage around populated units.
485    fn resident_policy(
486        &mut self,
487        architecture: &mut A,
488        units: Vec<A::Unit>,
489        selected: &SelectedRealtimeRealization,
490        context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
491    ) -> Result<RealizedRealtimePolicy<Self::ResidentPolicy>, Self::Error>;
492
493    /// Builds selected bounded storage without eagerly constructing every unit.
494    #[allow(clippy::too_many_arguments)]
495    fn bounded_policy(
496        &mut self,
497        architecture: &mut A,
498        source_architecture: Option<&mut A>,
499        tasks: &[RealtimeMaterializationTask],
500        selected: &SelectedRealtimeRealization,
501        context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
502    ) -> Result<RealizedRealtimePolicy<Self::BoundedPolicy>, Self::Error>;
503
504    /// Realizes exact selected state components and placements.
505    fn realize_state(
506        &mut self,
507        selected: &crate::SelectedRealtimeStateRealization,
508        context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
509    ) -> Result<RealizedRealtimeState<Self::State>, Self::Error>;
510}
511
512/// Resident or bounded runtime chosen by the authoritative realization.
513pub enum RealtimeLayerwiseRuntime<A, B, S, R, P>
514where
515    B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
516    S: RuntimeState<B>,
517    A: LayeredArchitecture<B, S>,
518    R: LayerwisePolicy<B, A::Unit>,
519    P: LayerwisePolicy<B, A::Unit>,
520{
521    /// Fully resident execution.
522    Resident(LayerwiseRuntime<A, B, S, R>),
523    /// Host-windowed or disk-streamed execution.
524    Bounded(LayerwiseRuntime<A, B, S, P>),
525}
526
527/// Constructed static execution and mechanisms, detached from mutable model state.
528pub struct ConstructedRealtimeExecution<A, B, M>
529where
530    B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
531    M: RealtimeModelConstructionMechanisms<A, B>,
532    A: LayeredArchitecture<B, M::State>,
533{
534    selected: SelectedRealtimeRealization,
535    execution: RealtimeLayerwiseRuntime<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy>,
536    mechanisms: M,
537    backend: PhantomData<fn() -> B>,
538}
539
540impl<A, B, M> ConstructedRealtimeExecution<A, B, M>
541where
542    B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
543    M: RealtimeModelConstructionMechanisms<A, B>,
544    A: LayeredArchitecture<B, M::State>,
545{
546    /// Returns the immutable selected realization.
547    pub const fn selected(&self) -> &SelectedRealtimeRealization {
548        &self.selected
549    }
550
551    /// Returns the selected resident or bounded runtime.
552    pub const fn execution(
553        &self,
554    ) -> &RealtimeLayerwiseRuntime<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy> {
555        &self.execution
556    }
557
558    /// Mutably borrows the selected resident or bounded runtime.
559    pub fn execution_mut(
560        &mut self,
561    ) -> &mut RealtimeLayerwiseRuntime<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy> {
562        &mut self.execution
563    }
564
565    /// Returns generic construction mechanisms for reports or later composition.
566    pub const fn mechanisms(&self) -> &M {
567        &self.mechanisms
568    }
569
570    /// Mutably borrows generic construction mechanisms.
571    pub fn mechanisms_mut(&mut self) -> &mut M {
572        &mut self.mechanisms
573    }
574
575    /// Decomposes selected construction for installation in the exact
576    /// topology-specific neutral execution runtime.
577    #[allow(clippy::type_complexity)]
578    pub fn into_parts(
579        self,
580    ) -> (
581        SelectedRealtimeRealization,
582        RealtimeLayerwiseRuntime<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy>,
583        M,
584    ) {
585        (self.selected, self.execution, self.mechanisms)
586    }
587}
588
589/// Fully constructed execution paired with its initial mutable model state.
590pub struct ConstructedRealtimeModel<A, B, M>
591where
592    B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
593    M: RealtimeModelConstructionMechanisms<A, B>,
594    A: LayeredArchitecture<B, M::State>,
595{
596    execution: ConstructedRealtimeExecution<A, B, M>,
597    state: M::State,
598}
599
600impl<A, B, M> ConstructedRealtimeModel<A, B, M>
601where
602    B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
603    M: RealtimeModelConstructionMechanisms<A, B>,
604    A: LayeredArchitecture<B, M::State>,
605{
606    /// Returns the immutable selected realization.
607    pub const fn selected(&self) -> &SelectedRealtimeRealization {
608        self.execution.selected()
609    }
610
611    /// Returns the selected resident or bounded runtime.
612    pub const fn execution(
613        &self,
614    ) -> &RealtimeLayerwiseRuntime<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy> {
615        self.execution.execution()
616    }
617
618    /// Mutably borrows the selected resident or bounded runtime.
619    pub fn execution_mut(
620        &mut self,
621    ) -> &mut RealtimeLayerwiseRuntime<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy> {
622        self.execution.execution_mut()
623    }
624
625    /// Returns realized architecture state.
626    pub const fn state(&self) -> &M::State {
627        &self.state
628    }
629
630    /// Mutably borrows realized architecture state.
631    pub fn state_mut(&mut self) -> &mut M::State {
632        &mut self.state
633    }
634
635    /// Mutably borrows execution and state together for one atomic model pass.
636    #[allow(clippy::type_complexity)]
637    pub fn execution_and_state_mut(
638        &mut self,
639    ) -> (
640        &mut RealtimeLayerwiseRuntime<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy>,
641        &mut M::State,
642    ) {
643        (self.execution.execution_mut(), &mut self.state)
644    }
645
646    /// Mutably borrows detached execution and state as separate typed values.
647    #[allow(clippy::type_complexity)]
648    pub fn constructed_execution_and_state_mut(
649        &mut self,
650    ) -> (&mut ConstructedRealtimeExecution<A, B, M>, &mut M::State) {
651        (&mut self.execution, &mut self.state)
652    }
653
654    /// Returns generic construction mechanisms for reports or later composition.
655    pub const fn mechanisms(&self) -> &M {
656        self.execution.mechanisms()
657    }
658
659    /// Mutably borrows generic mechanisms.
660    pub fn mechanisms_mut(&mut self) -> &mut M {
661        self.execution.mechanisms_mut()
662    }
663
664    /// Consumes the combined model into static execution and mutable state.
665    pub fn into_execution_and_state(self) -> (ConstructedRealtimeExecution<A, B, M>, M::State) {
666        (self.execution, self.state)
667    }
668}
669
670/// Constructs static modules, selected units, storage, and exact state once.
671#[allow(clippy::type_complexity)]
672pub fn construct_realtime_model<A, B, M>(
673    mut architecture: A,
674    mut source_architecture: Option<A>,
675    prepared: PreparedRealtimeModelContract,
676    mut mechanisms: M,
677    context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
678) -> Result<
679    ConstructedRealtimeModel<A, B, M>,
680    RealtimeModelConstructionError<A::Error, M::PolicyError, M::Error>,
681>
682where
683    B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
684    M: RealtimeModelConstructionMechanisms<A, B>,
685    A: LayeredArchitecture<B, M::State> + RealtimeArchitectureIdentity,
686    A::Error: std::fmt::Display,
687    M::PolicyError: std::fmt::Display,
688    M::Error: std::fmt::Display,
689{
690    let (selected, tasks) = prepared.into_parts();
691    let requires_source_architecture = selected.weight_lowerings().iter().any(|lowering| {
692        matches!(
693            lowering.kind(),
694            crate::WeightLoweringKind::Transform | crate::WeightLoweringKind::DerivedTransform
695        )
696    });
697    if requires_source_architecture != source_architecture.is_some() {
698        return Err(RealtimeModelConstructionError::Contract(
699            "selected realtime lowering and source-format architecture presence differ".into(),
700        ));
701    }
702    validate_architecture::<A, B, M::State>(&architecture, &selected, false, context)
703        .map_err(widen_error)?;
704    if let Some(source) = source_architecture.as_ref() {
705        validate_architecture::<A, B, M::State>(source, &selected, true, context)
706            .map_err(widen_error)?;
707    }
708    let (state, state_realization) = mechanisms
709        .realize_state(selected.state(), context)
710        .map_err(RealtimeModelConstructionError::Mechanism)?
711        .into_parts();
712    if &state_realization != selected.state() || state.layout() != selected.state().layout() {
713        return Err(RealtimeModelConstructionError::Contract(
714            "realized realtime state differs from selection".into(),
715        ));
716    }
717    let execution = match selected.residency() {
718        LayerWeightResidency::FullyResident => {
719            let mut units = construct_units::<A, B, M::State>(&architecture, &selected, context)
720                .map_err(widen_error)?;
721            let mut source_units = source_architecture
722                .as_ref()
723                .map(|source| construct_units::<A, B, M::State>(source, &selected, context))
724                .transpose()
725                .map_err(widen_error)?;
726            mechanisms
727                .prepare_resident_materialization(
728                    &mut architecture,
729                    &mut units,
730                    source_architecture.as_mut(),
731                    source_units.as_deref_mut(),
732                    &tasks,
733                    &selected,
734                    context,
735                )
736                .map_err(RealtimeModelConstructionError::Mechanism)?;
737            let (policy, residency) = mechanisms
738                .resident_policy(&mut architecture, units, &selected, context)
739                .map_err(RealtimeModelConstructionError::Mechanism)?
740                .into_parts();
741            if residency != selected.residency() {
742                return Err(RealtimeModelConstructionError::Contract(
743                    "realized realtime weight residency differs from selection".into(),
744                ));
745            }
746            RealtimeLayerwiseRuntime::Resident(LayerwiseRuntime::new(architecture, policy))
747        }
748        LayerWeightResidency::LayerwiseHost(_) | LayerWeightResidency::DenseDiskStream(_) => {
749            let (policy, residency) = mechanisms
750                .bounded_policy(
751                    &mut architecture,
752                    source_architecture.as_mut(),
753                    &tasks,
754                    &selected,
755                    context,
756                )
757                .map_err(RealtimeModelConstructionError::Mechanism)?
758                .into_parts();
759            if residency != selected.residency() {
760                return Err(RealtimeModelConstructionError::Contract(
761                    "realized realtime weight residency differs from selection".into(),
762                ));
763            }
764            RealtimeLayerwiseRuntime::Bounded(LayerwiseRuntime::new(architecture, policy))
765        }
766    };
767    Ok(ConstructedRealtimeModel {
768        execution: ConstructedRealtimeExecution {
769            selected,
770            execution,
771            mechanisms,
772            backend: PhantomData,
773        },
774        state,
775    })
776}
777
778fn widen_error<A, P, M>(
779    error: RealtimeModelConstructionError<A, std::convert::Infallible, std::convert::Infallible>,
780) -> RealtimeModelConstructionError<A, P, M>
781where
782    A: std::fmt::Display,
783    P: std::fmt::Display,
784    M: std::fmt::Display,
785{
786    match error {
787        RealtimeModelConstructionError::Architecture(error) => {
788            RealtimeModelConstructionError::Architecture(error)
789        }
790        RealtimeModelConstructionError::Contract(error) => {
791            RealtimeModelConstructionError::Contract(error)
792        }
793        RealtimeModelConstructionError::Mechanism(error) => match error {},
794        RealtimeModelConstructionError::Policy(error) => match error {},
795    }
796}
797
798fn construct_units<A, B, S>(
799    architecture: &A,
800    selected: &SelectedRealtimeRealization,
801    context: &<B::Tensor as Tensor>::Context,
802) -> Result<
803    Vec<A::Unit>,
804    RealtimeModelConstructionError<A::Error, std::convert::Infallible, std::convert::Infallible>,
805>
806where
807    B: NeuralBackend,
808    S: RuntimeState<B>,
809    A: LayeredArchitecture<B, S>,
810    A::Error: std::fmt::Display,
811{
812    (0..selected.execution_units().len())
813        .map(|ordinal| {
814            let address = selected
815                .execution_units()
816                .address(ordinal)
817                .expect("selected execution ordinal has an address");
818            architecture
819                .build_unit(address.group(), address.index(), context)
820                .map_err(RealtimeModelConstructionError::Architecture)
821        })
822        .collect()
823}
824
825fn validate_architecture<A, B, S>(
826    architecture: &A,
827    selected: &SelectedRealtimeRealization,
828    source: bool,
829    context: &<B::Tensor as Tensor>::Context,
830) -> Result<
831    (),
832    RealtimeModelConstructionError<A::Error, std::convert::Infallible, std::convert::Infallible>,
833>
834where
835    B: NeuralBackend,
836    S: RuntimeState<B>,
837    A: LayeredArchitecture<B, S> + RealtimeArchitectureIdentity,
838    A::Error: std::fmt::Display,
839{
840    if !source {
841        let actual = architecture
842            .realtime_construction_identity()
843            .map_err(RealtimeModelConstructionError::Contract)?;
844        let requirements = selected.requirements();
845        let expected = RealtimeArchitectureConstructionIdentity::new(
846            requirements.architecture().clone(),
847            requirements.speech_schedule_identity().clone(),
848            requirements.state_layout_identity().clone(),
849        );
850        if actual != expected {
851            return Err(RealtimeModelConstructionError::Contract(
852                "constructed realtime architecture identities differ from selection".into(),
853            ));
854        }
855    }
856    if architecture
857        .execution_graph()
858        .map_err(RealtimeModelConstructionError::Architecture)?
859        != *selected.execution_graph()
860    {
861        return Err(RealtimeModelConstructionError::Contract(
862            "constructed realtime execution graph differs from selection".into(),
863        ));
864    }
865    for group in 0..selected.execution_graph().groups().len() {
866        let actual = architecture
867            .group_unit_count(group)
868            .map_err(RealtimeModelConstructionError::Architecture)?;
869        let expected = selected
870            .execution_units()
871            .group_range(group)
872            .expect("selected layout contains every graph group")
873            .len();
874        if actual != expected {
875            return Err(RealtimeModelConstructionError::Contract(format!(
876                "constructed realtime group {group} unit count differs from selection"
877            )));
878        }
879    }
880    let actual = architecture
881        .parameter_description(context)
882        .map_err(RealtimeModelConstructionError::Architecture)?;
883    let expected = if source {
884        selected.source_parameters()
885    } else {
886        selected.execution_parameters()
887    };
888    if &actual != expected {
889        return Err(RealtimeModelConstructionError::Contract(
890            "constructed realtime parameter topology differs from selection".into(),
891        ));
892    }
893    if !source
894        && architecture
895            .state_layout()
896            .map_err(RealtimeModelConstructionError::Architecture)?
897            != *selected.state().layout()
898    {
899        return Err(RealtimeModelConstructionError::Contract(
900            "constructed realtime state layout differs from selection".into(),
901        ));
902    }
903    Ok(())
904}
905
906/// Invalid selected recipe or task handoff.
907#[derive(Debug, Clone, Eq, PartialEq, thiserror::Error)]
908#[non_exhaustive]
909pub enum RealtimeModelContractError {
910    /// A component's retained physical sources differ from its selected recipe traversal.
911    #[error("realtime source provenance differs for target {target}")]
912    SourceProvenanceMismatch {
913        /// Affected selected component target.
914        target: String,
915    },
916    /// A source-backed companion's inferred geometry differs from selection.
917    #[error("realtime recipe geometry differs for target {target}")]
918    RecipeGeometryMismatch {
919        /// Affected selected component target.
920        target: String,
921    },
922    /// Primary recipe scalar encoding differs from its selected source descriptor.
923    #[error("realtime recipe encoding differs for target {target}")]
924    RecipeEncodingMismatch {
925        /// Affected selected component target.
926        target: String,
927    },
928    /// Concrete component payload does not exactly cover the lowering.
929    #[error("realtime component payload differs for target {target}")]
930    ComponentCoverageMismatch {
931        /// Affected selected lowering target.
932        target: String,
933    },
934    /// Task targets do not exactly cover selection.
935    #[error("realtime materialization tasks do not exactly cover selected targets")]
936    TaskCoverageMismatch,
937    /// A task contains a lowering that differs from selection.
938    #[error("realtime materialization task differs from selection for target {target}")]
939    TaskSelectionMismatch {
940        /// Affected selected lowering target.
941        target: String,
942    },
943    /// A selected target has no declared execution parameter owner.
944    #[error("realtime materialization target {target} has no execution owner")]
945    TaskOwnerUnavailable {
946        /// Affected selected lowering target.
947        target: String,
948    },
949    /// A task owner differs from the exact selected execution owner.
950    #[error("realtime materialization owner differs from selection for target {target}")]
951    TaskOwnerMismatch {
952        /// Affected selected lowering target.
953        target: String,
954    },
955    /// Canonical task-to-binding derivation or metadata preflight failed.
956    #[error("realtime binding plan is invalid: {detail}")]
957    BindingPlan {
958        /// Exact metadata-only causal failure.
959        detail: String,
960    },
961}
962
963/// Failure while constructing one selected layered realtime model.
964#[derive(Debug, thiserror::Error)]
965pub enum RealtimeModelConstructionError<A, P, M>
966where
967    A: std::fmt::Display,
968    P: std::fmt::Display,
969    M: std::fmt::Display,
970{
971    /// Neutral architecture construction failed.
972    #[error("realtime architecture construction failed: {0}")]
973    Architecture(A),
974    /// Selected and constructed neutral contracts differ.
975    #[error("invalid realtime model construction: {0}")]
976    Contract(String),
977    /// Generic materialization, state, or storage mechanism failed.
978    #[error("realtime model mechanism failed: {0}")]
979    Mechanism(M),
980    /// Resident/bounded policy failure reserved for execution-time composition.
981    #[error("realtime residency policy failed: {0}")]
982    Policy(P),
983}