Skip to main content

ferrum_interfaces/vnext/execution/
weight.rs

1use std::collections::{BTreeMap, BTreeSet};
2use std::fmt;
3use std::sync::Arc;
4
5use crate::vnext::{WeightComponentPayload, WeightComponentSource, WeightComponentSpec};
6
7use super::{
8    canonical_fingerprint, invalid_plan, is_canonical_sha256, CapabilityCatalog, CapabilityId,
9    ContractVersion, Deserialize, DeviceDescriptor, ModelFamilyId, PreparedModelFamily, Serialize,
10    VNextError, WeightId, WeightMaterializerId, WeightSchema,
11};
12
13pub const IDENTITY_WEIGHT_MATERIALIZER_ID: &str = "weight-materializer.identity";
14const IDENTITY_MATERIALIZER_VERSION: ContractVersion = ContractVersion::new(2, 0);
15pub const MAX_WEIGHT_MATERIALIZERS: usize = 64;
16
17/// Whether a physical weight transformation preserves source values.
18///
19/// Kernel availability is not authorization to change model precision.
20/// Approximate materializers may be registered for capability discovery, but
21/// require a separate numerical-quality approval path before plan selection.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
23#[serde(rename_all = "snake_case")]
24pub enum WeightMaterializationFidelity {
25    Exact,
26    Approximate,
27}
28
29#[derive(Serialize)]
30struct IdentityMaterializerFingerprint<'a> {
31    id: &'a str,
32    version: ContractVersion,
33    contract: &'a str,
34}
35
36fn identity_materializer_fingerprint() -> Result<String, VNextError> {
37    canonical_fingerprint(
38        &IdentityMaterializerFingerprint {
39            id: IDENTITY_WEIGHT_MATERIALIZER_ID,
40            version: IDENTITY_MATERIALIZER_VERSION,
41            contract: "execution-weight-plan.identity.v2",
42        },
43        "fingerprint identity weight materializer",
44    )
45}
46
47/// Serializable capability identity for one trusted weight transformation.
48///
49/// The descriptor advertises availability, but cannot construct an execution
50/// schema. Only the process-local [`WeightMaterializerRegistry`] retains the
51/// implementation object that may produce a trusted plan.
52#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
53#[serde(deny_unknown_fields)]
54pub struct WeightMaterializerDescriptor {
55    id: WeightMaterializerId,
56    version: ContractVersion,
57    implementation_fingerprint: String,
58    fidelity: WeightMaterializationFidelity,
59    required_capabilities: BTreeSet<CapabilityId>,
60}
61
62impl WeightMaterializerDescriptor {
63    pub fn new(
64        id: WeightMaterializerId,
65        version: ContractVersion,
66        implementation_fingerprint: impl Into<String>,
67        fidelity: WeightMaterializationFidelity,
68        required_capabilities: BTreeSet<CapabilityId>,
69    ) -> Result<Self, VNextError> {
70        let descriptor = Self {
71            id,
72            version,
73            implementation_fingerprint: implementation_fingerprint.into(),
74            fidelity,
75            required_capabilities,
76        };
77        descriptor.validate_structure()?;
78        Ok(descriptor)
79    }
80
81    pub(crate) fn identity() -> Result<Self, VNextError> {
82        Self::new(
83            WeightMaterializerId::new(IDENTITY_WEIGHT_MATERIALIZER_ID)?,
84            IDENTITY_MATERIALIZER_VERSION,
85            identity_materializer_fingerprint()?,
86            WeightMaterializationFidelity::Exact,
87            BTreeSet::new(),
88        )
89    }
90
91    pub fn id(&self) -> &WeightMaterializerId {
92        &self.id
93    }
94
95    pub const fn version(&self) -> ContractVersion {
96        self.version
97    }
98
99    pub fn implementation_fingerprint(&self) -> &str {
100        &self.implementation_fingerprint
101    }
102
103    pub const fn fidelity(&self) -> WeightMaterializationFidelity {
104        self.fidelity
105    }
106
107    pub fn required_capabilities(&self) -> &BTreeSet<CapabilityId> {
108        &self.required_capabilities
109    }
110
111    pub fn fingerprint(&self) -> Result<String, VNextError> {
112        canonical_fingerprint(self, "fingerprint weight materializer descriptor")
113    }
114
115    pub(crate) fn validate_for_device(&self, device: &DeviceDescriptor) -> Result<(), VNextError> {
116        self.validate_structure()?;
117        if !self.required_capabilities.is_subset(&device.capabilities) {
118            return Err(invalid_plan(format!(
119                "weight materializer `{}` requires capabilities absent from device `{}`",
120                self.id, device.id
121            )));
122        }
123        Ok(())
124    }
125
126    fn validate_structure(&self) -> Result<(), VNextError> {
127        if self.version.major == 0 || !is_canonical_sha256(&self.implementation_fingerprint) {
128            return Err(invalid_plan(format!(
129                "weight materializer descriptor `{}` has invalid version or implementation identity",
130                self.id
131            )));
132        }
133        Ok(())
134    }
135}
136
137/// Trusted authority for one physical weight transformation.
138///
139/// Implementations are invoked once while compiling an immutable plan. They
140/// must derive the complete execution schema from the prepared family and
141/// device descriptor without allocating device memory or reading request
142/// state. During static initialization the same retained implementation turns
143/// source components into the exact execution components recorded in that
144/// plan; no provider or weight source may bypass this authority.
145pub trait WeightMaterializer: Send + Sync {
146    fn descriptor(&self) -> &WeightMaterializerDescriptor;
147
148    fn execution_schema(
149        &self,
150        family: &PreparedModelFamily,
151        device: &DeviceDescriptor,
152    ) -> Result<WeightSchema, VNextError>;
153
154    /// Ordered source-component identities for every execution component.
155    ///
156    /// The default only permits a same-id mapping. Materializers that create
157    /// derived component identities or combine multiple source components must
158    /// declare that provenance explicitly.
159    fn component_sources(
160        &self,
161        family: &PreparedModelFamily,
162        execution_schema: &WeightSchema,
163    ) -> Result<BTreeMap<WeightId, Vec<WeightId>>, VNextError> {
164        identity_component_sources(family, execution_schema)
165    }
166
167    /// Materialize one execution component on the cold initialization path.
168    ///
169    /// `source_components` is resolved from the immutable plan's ordered source
170    /// map. Implementations may borrow source bytes for identity layouts or
171    /// return owned bytes for repacked/quantized layouts.
172    fn materialize_component<'source>(
173        &self,
174        source: &'source dyn WeightComponentSource,
175        source_components: &[&WeightComponentSpec],
176        execution_component: &WeightComponentSpec,
177    ) -> Result<WeightComponentPayload<'source>, VNextError>;
178
179    /// Materialize execution components that share one exact ordered source set.
180    ///
181    /// The default preserves existing one-component implementations. Expensive
182    /// transforms may override this method to decode, quantize, or repack their
183    /// common source once and return one payload per requested component in the
184    /// same order.
185    fn materialize_components<'source>(
186        &self,
187        source: &'source dyn WeightComponentSource,
188        source_components: &[&WeightComponentSpec],
189        execution_components: &[&WeightComponentSpec],
190    ) -> Result<Vec<WeightComponentPayload<'source>>, VNextError> {
191        execution_components
192            .iter()
193            .map(|component| self.materialize_component(source, source_components, component))
194            .collect()
195    }
196}
197
198struct IdentityWeightMaterializer {
199    descriptor: WeightMaterializerDescriptor,
200}
201
202impl IdentityWeightMaterializer {
203    fn new() -> Result<Self, VNextError> {
204        Ok(Self {
205            descriptor: WeightMaterializerDescriptor::identity()?,
206        })
207    }
208}
209
210impl WeightMaterializer for IdentityWeightMaterializer {
211    fn descriptor(&self) -> &WeightMaterializerDescriptor {
212        &self.descriptor
213    }
214
215    fn execution_schema(
216        &self,
217        family: &PreparedModelFamily,
218        _device: &DeviceDescriptor,
219    ) -> Result<WeightSchema, VNextError> {
220        Ok(family.weight_schema().clone())
221    }
222
223    fn materialize_component<'source>(
224        &self,
225        source: &'source dyn WeightComponentSource,
226        source_components: &[&WeightComponentSpec],
227        execution_component: &WeightComponentSpec,
228    ) -> Result<WeightComponentPayload<'source>, VNextError> {
229        let [source_component] = source_components else {
230            return Err(invalid_plan(
231                "identity weight materializer requires exactly one source component",
232            ));
233        };
234        if *source_component != execution_component {
235            return Err(invalid_plan(format!(
236                "identity weight materializer cannot transform component `{}`",
237                execution_component.id
238            )));
239        }
240        source.component(source_component)
241    }
242}
243
244fn identity_component_sources(
245    family: &PreparedModelFamily,
246    execution_schema: &WeightSchema,
247) -> Result<BTreeMap<WeightId, Vec<WeightId>>, VNextError> {
248    let source_ids = family
249        .weight_schema()
250        .components
251        .iter()
252        .map(|component| component.id.clone())
253        .collect::<BTreeSet<_>>();
254    execution_schema
255        .components
256        .iter()
257        .map(|component| {
258            if !source_ids.contains(&component.id) {
259                return Err(invalid_plan(format!(
260                    "weight materializer must declare sources for derived component `{}`",
261                    component.id
262                )));
263            }
264            Ok((component.id.clone(), vec![component.id.clone()]))
265        })
266        .collect()
267}
268
269/// Process-local registry retaining the exact implementations authorized to
270/// transform checkpoint schemas. It is deliberately neither serializable nor
271/// reconstructible from a capability catalog.
272pub struct WeightMaterializerRegistry {
273    materializers: BTreeMap<WeightMaterializerId, Arc<dyn WeightMaterializer>>,
274}
275
276impl WeightMaterializerRegistry {
277    pub fn new(materializers: Vec<Box<dyn WeightMaterializer>>) -> Result<Self, VNextError> {
278        if materializers.len() >= MAX_WEIGHT_MATERIALIZERS {
279            return Err(invalid_plan(format!(
280                "weight materializer registry exceeds {} non-identity entries",
281                MAX_WEIGHT_MATERIALIZERS - 1
282            )));
283        }
284        let identity: Arc<dyn WeightMaterializer> = Arc::new(IdentityWeightMaterializer::new()?);
285        let mut entries = BTreeMap::from([(identity.descriptor().id().clone(), identity)]);
286        for materializer in materializers {
287            materializer.descriptor().validate_structure()?;
288            let id = materializer.descriptor().id().clone();
289            if entries
290                .insert(id.clone(), Arc::from(materializer))
291                .is_some()
292            {
293                return Err(invalid_plan(format!(
294                    "duplicate weight materializer `{id}`"
295                )));
296            }
297        }
298        Ok(Self {
299            materializers: entries,
300        })
301    }
302
303    pub fn identity_only() -> Result<Self, VNextError> {
304        Self::new(Vec::new())
305    }
306
307    /// Extends a capability catalog with descriptors from these exact
308    /// process-local implementation objects.
309    pub fn augment_catalog(
310        &self,
311        catalog: CapabilityCatalog,
312    ) -> Result<CapabilityCatalog, VNextError> {
313        catalog.with_weight_materializer_descriptors(self.descriptors())
314    }
315
316    /// Invokes the selected trusted implementation and returns a witness that
317    /// cannot be forged by deserializing an [`ExecutionWeightPlan`].
318    /// Selects a materializer that is value-preserving by contract.
319    ///
320    /// Approximate transforms require a future typed quality approval carrying
321    /// checked-in numerical-tolerance evidence. Keeping that authority out of
322    /// this entrypoint prevents a build feature or backend capability from
323    /// silently changing checkpoint precision.
324    pub fn select_exact(
325        &self,
326        family: &PreparedModelFamily,
327        catalog: &CapabilityCatalog,
328        materializer_id: &WeightMaterializerId,
329    ) -> Result<TrustedExecutionWeightPlan, VNextError> {
330        let materializer = self.materializers.get(materializer_id).ok_or_else(|| {
331            invalid_plan(format!(
332                "weight materializer `{materializer_id}` is not registered"
333            ))
334        })?;
335        let descriptor = materializer.descriptor();
336        let catalog_descriptor = catalog.weight_materializer(materializer_id)?;
337        if descriptor != catalog_descriptor {
338            return Err(invalid_plan(format!(
339                "weight materializer `{materializer_id}` differs from its capability catalog descriptor"
340            )));
341        }
342        if descriptor.fidelity() != WeightMaterializationFidelity::Exact {
343            return Err(invalid_plan(format!(
344                "weight materializer `{materializer_id}` is approximate and requires explicit numerical-quality approval"
345            )));
346        }
347        descriptor.validate_for_device(catalog.device())?;
348        let mut schema = materializer.execution_schema(family, catalog.device())?;
349        schema.normalize();
350        let component_sources = materializer.component_sources(family, &schema)?;
351        let plan =
352            ExecutionWeightPlan::from_materializer(family, descriptor, schema, component_sources)?;
353        Ok(TrustedExecutionWeightPlan {
354            plan,
355            descriptor: descriptor.clone(),
356            materializer: Arc::clone(materializer),
357        })
358    }
359
360    pub fn descriptors(&self) -> BTreeMap<WeightMaterializerId, WeightMaterializerDescriptor> {
361        self.materializers
362            .iter()
363            .map(|(id, materializer)| (id.clone(), materializer.descriptor().clone()))
364            .collect()
365    }
366}
367
368/// Non-serializable proof that a process-local registry implementation
369/// produced and validated this physical execution schema.
370#[derive(Clone)]
371pub struct TrustedExecutionWeightPlan {
372    plan: ExecutionWeightPlan,
373    descriptor: WeightMaterializerDescriptor,
374    materializer: Arc<dyn WeightMaterializer>,
375}
376
377impl fmt::Debug for TrustedExecutionWeightPlan {
378    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
379        formatter
380            .debug_struct("TrustedExecutionWeightPlan")
381            .field("plan", &self.plan)
382            .field("descriptor", &self.descriptor)
383            .finish_non_exhaustive()
384    }
385}
386
387impl PartialEq for TrustedExecutionWeightPlan {
388    fn eq(&self, other: &Self) -> bool {
389        self.plan == other.plan && self.descriptor == other.descriptor
390    }
391}
392
393impl Eq for TrustedExecutionWeightPlan {}
394
395impl TrustedExecutionWeightPlan {
396    pub(crate) fn identity(family: &PreparedModelFamily) -> Result<Self, VNextError> {
397        let materializer: Arc<dyn WeightMaterializer> =
398            Arc::new(IdentityWeightMaterializer::new()?);
399        let descriptor = materializer.descriptor().clone();
400        let schema = family.weight_schema().clone();
401        let component_sources = materializer.component_sources(family, &schema)?;
402        Ok(Self {
403            plan: ExecutionWeightPlan::from_materializer(
404                family,
405                &descriptor,
406                schema,
407                component_sources,
408            )?,
409            descriptor,
410            materializer,
411        })
412    }
413
414    pub fn plan(&self) -> &ExecutionWeightPlan {
415        &self.plan
416    }
417
418    pub(crate) fn validate_against_catalog(
419        &self,
420        family: &PreparedModelFamily,
421        catalog: &CapabilityCatalog,
422    ) -> Result<(), VNextError> {
423        self.validate_runtime_authority()?;
424        let catalog_descriptor = catalog.weight_materializer(self.descriptor.id())?;
425        if &self.descriptor != catalog_descriptor {
426            return Err(invalid_plan(format!(
427                "weight materializer `{}` differs from its capability catalog descriptor",
428                self.descriptor.id()
429            )));
430        }
431        self.plan
432            .validate_against_materializer(family, &self.descriptor)
433    }
434
435    pub(crate) fn materialize_components<'source>(
436        &self,
437        family: &PreparedModelFamily,
438        source: &'source dyn WeightComponentSource,
439        execution_components: &[&WeightComponentSpec],
440    ) -> Result<Vec<WeightComponentPayload<'source>>, VNextError> {
441        self.validate_runtime_authority()?;
442        let Some(first_execution_component) = execution_components.first() else {
443            return Err(invalid_plan(
444                "weight materializer received an empty execution component group",
445            ));
446        };
447        let mut planned_components = Vec::with_capacity(execution_components.len());
448        for execution_component in execution_components {
449            let planned_component_index = self
450                .plan
451                .schema
452                .components
453                .binary_search_by(|component| component.id.cmp(&execution_component.id))
454                .map_err(|_| {
455                    invalid_plan(format!(
456                        "execution component `{}` is absent from the trusted weight plan",
457                        execution_component.id
458                    ))
459                })?;
460            let planned_component = &self.plan.schema.components[planned_component_index];
461            if planned_component != *execution_component {
462                return Err(invalid_plan(format!(
463                    "execution component `{}` differs from the trusted weight plan",
464                    execution_component.id
465                )));
466            }
467            planned_components.push(planned_component);
468        }
469        let source_ids = self
470            .plan
471            .component_sources
472            .get(&first_execution_component.id)
473            .ok_or_else(|| {
474                invalid_plan(format!(
475                    "execution component `{}` has no source mapping",
476                    first_execution_component.id
477                ))
478            })?;
479        if execution_components
480            .iter()
481            .skip(1)
482            .any(|component| self.plan.component_sources.get(&component.id) != Some(source_ids))
483        {
484            return Err(invalid_plan(
485                "grouped execution components do not share one ordered source mapping",
486            ));
487        }
488        let source_components = source_ids
489            .iter()
490            .map(|source_id| {
491                let source_component_index = family
492                    .weight_schema()
493                    .components
494                    .binary_search_by(|component| component.id.cmp(source_id))
495                    .map_err(|_| {
496                        invalid_plan(format!(
497                            "execution component `{}` references unknown source component `{source_id}`",
498                            first_execution_component.id
499                        ))
500                    })?;
501                Ok(&family.weight_schema().components[source_component_index])
502            })
503            .collect::<Result<Vec<_>, _>>()?;
504        let payloads = self.materializer.materialize_components(
505            source,
506            &source_components,
507            &planned_components,
508        )?;
509        if payloads.len() != planned_components.len() {
510            return Err(invalid_plan(format!(
511                "weight materializer `{}` returned {} payloads for {} execution components",
512                self.descriptor.id,
513                payloads.len(),
514                planned_components.len()
515            )));
516        }
517        for (payload, execution_component) in payloads.iter().zip(&planned_components) {
518            if payload.component_id() != &execution_component.id
519                || payload.external_names() != execution_component.external_names.as_slice()
520                || payload.dimensions() != execution_component.dimensions.as_slice()
521                || payload.element_type() != execution_component.physical_element_type()
522                || u64::try_from(payload.bytes().len()).ok()
523                    != Some(execution_component.physical_bytes()?)
524            {
525                return Err(invalid_plan(format!(
526                    "weight materializer `{}` returned invalid or reordered payload for execution component `{}`",
527                    self.descriptor.id, execution_component.id
528                )));
529            }
530        }
531        Ok(payloads)
532    }
533
534    fn validate_runtime_authority(&self) -> Result<(), VNextError> {
535        if self.materializer.descriptor() != &self.descriptor {
536            return Err(invalid_plan(format!(
537                "weight materializer `{}` runtime authority differs from its trusted descriptor",
538                self.descriptor.id
539            )));
540        }
541        Ok(())
542    }
543}
544
545/// Trusted physical weight contract selected for one immutable execution plan.
546///
547/// The prepared family remains the source/checkpoint contract. This plan owns
548/// the physical schema consumed by providers, static memory planning, and
549/// initialization. Keeping those contracts separate allows a backend to
550/// select a prepared layout without changing model semantics or hiding an
551/// allocation behind a provider.
552#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
553#[serde(deny_unknown_fields)]
554pub struct ExecutionWeightPlan {
555    source_schema_fingerprint: String,
556    materializer_id: WeightMaterializerId,
557    materializer_version: ContractVersion,
558    materializer_implementation_fingerprint: String,
559    component_sources: BTreeMap<WeightId, Vec<WeightId>>,
560    schema: WeightSchema,
561}
562
563impl ExecutionWeightPlan {
564    pub fn identity(family: &PreparedModelFamily) -> Result<Self, VNextError> {
565        let descriptor = WeightMaterializerDescriptor::identity()?;
566        let schema = family.weight_schema().clone();
567        let component_sources = identity_component_sources(family, &schema)?;
568        Self::from_materializer(family, &descriptor, schema, component_sources)
569    }
570
571    fn from_materializer(
572        family: &PreparedModelFamily,
573        descriptor: &WeightMaterializerDescriptor,
574        schema: WeightSchema,
575        component_sources: BTreeMap<WeightId, Vec<WeightId>>,
576    ) -> Result<Self, VNextError> {
577        let plan = Self {
578            source_schema_fingerprint: family.weight_schema().fingerprint()?,
579            materializer_id: descriptor.id().clone(),
580            materializer_version: descriptor.version(),
581            materializer_implementation_fingerprint: descriptor
582                .implementation_fingerprint()
583                .to_owned(),
584            component_sources,
585            schema,
586        };
587        plan.validate_against_materializer(family, descriptor)?;
588        Ok(plan)
589    }
590
591    pub fn source_schema_fingerprint(&self) -> &str {
592        &self.source_schema_fingerprint
593    }
594
595    pub fn materializer_id(&self) -> &WeightMaterializerId {
596        &self.materializer_id
597    }
598
599    pub const fn materializer_version(&self) -> ContractVersion {
600        self.materializer_version
601    }
602
603    pub fn materializer_implementation_fingerprint(&self) -> &str {
604        &self.materializer_implementation_fingerprint
605    }
606
607    pub fn schema(&self) -> &WeightSchema {
608        &self.schema
609    }
610
611    pub fn component_sources(&self) -> &BTreeMap<WeightId, Vec<WeightId>> {
612        &self.component_sources
613    }
614
615    pub fn fingerprint(&self) -> Result<String, VNextError> {
616        canonical_fingerprint(self, "fingerprint execution weight plan")
617    }
618
619    pub(super) fn validate_structure(&self, family_id: &ModelFamilyId) -> Result<(), VNextError> {
620        if !is_canonical_sha256(&self.source_schema_fingerprint)
621            || !is_canonical_sha256(&self.materializer_implementation_fingerprint)
622            || self.materializer_version.major == 0
623        {
624            return Err(VNextError::InvalidExecutionPlan {
625                reason: "execution weight plan provenance is invalid".to_owned(),
626            });
627        }
628        self.schema.validate(family_id)?;
629        let execution_component_ids = self
630            .schema
631            .components
632            .iter()
633            .map(|component| component.id.clone())
634            .collect::<BTreeSet<_>>();
635        let mapped_component_ids = self
636            .component_sources
637            .keys()
638            .cloned()
639            .collect::<BTreeSet<_>>();
640        if execution_component_ids != mapped_component_ids
641            || self.component_sources.values().any(|source_ids| {
642                source_ids.is_empty()
643                    || source_ids.iter().collect::<BTreeSet<_>>().len() != source_ids.len()
644            })
645        {
646            return Err(invalid_plan(
647                "execution weight component source map is incomplete or contains duplicate sources",
648            ));
649        }
650        Ok(())
651    }
652
653    pub(crate) fn validate_against_family(
654        &self,
655        family: &PreparedModelFamily,
656    ) -> Result<(), VNextError> {
657        self.validate_structure(family.family_id())?;
658        if self.source_schema_fingerprint != family.weight_schema().fingerprint()? {
659            return Err(invalid_plan(
660                "execution weight plan source schema differs from its prepared family",
661            ));
662        }
663        let source_components = family
664            .weight_schema()
665            .components
666            .iter()
667            .map(|component| (&component.id, component))
668            .collect::<BTreeMap<_, _>>();
669        let mut referenced_source_components = BTreeSet::new();
670        for (execution_component_id, source_ids) in &self.component_sources {
671            for source_id in source_ids {
672                if !source_components.contains_key(source_id) {
673                    return Err(invalid_plan(format!(
674                        "execution component `{execution_component_id}` references unknown source component `{source_id}`"
675                    )));
676                }
677                referenced_source_components.insert(source_id.clone());
678            }
679        }
680        if let Some(component) = source_components.values().find(|component| {
681            component.required && !referenced_source_components.contains(&component.id)
682        }) {
683            return Err(invalid_plan(format!(
684                "required source component `{}` is not represented in the execution weight plan",
685                component.id
686            )));
687        }
688        let source_tensors = family
689            .weight_schema()
690            .tensors
691            .iter()
692            .map(|tensor| (&tensor.id, tensor))
693            .collect::<BTreeMap<_, _>>();
694        let execution_tensors = self
695            .schema
696            .tensors
697            .iter()
698            .map(|tensor| (&tensor.id, tensor))
699            .collect::<BTreeMap<_, _>>();
700        if source_tensors.len() != execution_tensors.len()
701            || source_tensors.iter().any(|(id, source)| {
702                execution_tensors.get(id).is_none_or(|execution| {
703                    source.dimensions != execution.dimensions
704                        || source.logical_element_type != execution.logical_element_type
705                        || source.required != execution.required
706                })
707            })
708        {
709            return Err(invalid_plan(
710                "execution weight schema changes the prepared family's logical tensor contract",
711            ));
712        }
713        Ok(())
714    }
715
716    fn validate_against_materializer(
717        &self,
718        family: &PreparedModelFamily,
719        descriptor: &WeightMaterializerDescriptor,
720    ) -> Result<(), VNextError> {
721        self.validate_against_family(family)?;
722        if &self.materializer_id != descriptor.id()
723            || self.materializer_version != descriptor.version()
724            || self.materializer_implementation_fingerprint
725                != descriptor.implementation_fingerprint()
726        {
727            return Err(invalid_plan(
728                "execution weight plan differs from its trusted materializer descriptor",
729            ));
730        }
731        Ok(())
732    }
733}