Skip to main content

ferrum_interfaces/vnext/
numerical_resolution.rs

1//! External evidence for the numerical choice made during static composition.
2
3use serde::{Deserialize, Serialize};
4
5use super::{
6    canonical_runtime_policy_fingerprint, CapabilityCatalog, ContractVersion, ExecutionPlan,
7    KvStorageFormat, ModelFamilyDefinition, NumericalExecutionPolicy, NumericalProfileId,
8    PreparedModelFamily, ResolvedRuntimePolicy, VNextError,
9};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "snake_case")]
13pub enum NumericalProfileRejectionStage {
14    FamilyPreparation,
15    WeightMaterializer,
16    ProgramCompilation,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(deny_unknown_fields)]
21pub struct NumericalProfileRejection {
22    pub profile_id: NumericalProfileId,
23    pub stage: NumericalProfileRejectionStage,
24    pub reason: String,
25}
26
27/// Created by the composition owner from the retained static plan. It cannot be
28/// deserialized as trusted evidence. Revalidation requires the independently
29/// supplied selection, including the original request and rejected candidates.
30#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
31#[serde(transparent)]
32pub struct NumericalProfileResolution {
33    parts: NumericalProfileResolutionWire,
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37#[serde(deny_unknown_fields)]
38pub(crate) struct NumericalProfileResolutionWire {
39    requested: NumericalExecutionPolicy,
40    requested_kv_storage: KvStorageFormat,
41    selected_kv_storage: Option<KvStorageFormat>,
42    selected_profile: NumericalProfileId,
43    selected_version: ContractVersion,
44    profile_fingerprint: String,
45    qualification_version: ContractVersion,
46    definition_fingerprint: String,
47    prepared_family_fingerprint: String,
48    capability_catalog_fingerprint: String,
49    runtime_policy_fingerprint: String,
50    execution_plan_hash: String,
51    rejected: Vec<NumericalProfileRejection>,
52}
53
54fn invalid(reason: impl Into<String>) -> VNextError {
55    VNextError::InvalidExecutionPlan {
56        reason: format!("numerical resolution: {}", reason.into()),
57    }
58}
59
60impl NumericalProfileResolution {
61    /// The caller supplies failures observed while trying the declared prefix
62    /// of candidates with the same registries. Successful compilation remains
63    /// bound to this exact family, catalog and runtime policy. This constructor
64    /// does not qualify new numerical profiles for Auto.
65    #[allow(clippy::too_many_arguments)]
66    pub fn from_static_plan(
67        requested: NumericalExecutionPolicy,
68        requested_kv_storage: KvStorageFormat,
69        definition: &ModelFamilyDefinition,
70        family: &PreparedModelFamily,
71        capabilities: &CapabilityCatalog,
72        runtime: &ResolvedRuntimePolicy,
73        plan: &ExecutionPlan,
74        rejected: Vec<NumericalProfileRejection>,
75    ) -> Result<Self, VNextError> {
76        let profiles = definition.numerical_profiles();
77        let selected = family.numerical_profile();
78        if definition.family_id() != family.family_id()
79            || definition.canonical_config() != family.canonical_config()
80            || profiles.resolve(&selected.id)? != selected
81        {
82            return Err(invalid("selected family differs from its typed definition"));
83        }
84        let candidates = profiles.candidates(&requested, requested_kv_storage)?;
85        let selected_position = candidates
86            .iter()
87            .position(|profile| profile.id == selected.id)
88            .ok_or_else(|| invalid("selected profile is not a candidate for the request"))?;
89        if rejected.len() != selected_position
90            || rejected
91                .iter()
92                .zip(&candidates)
93                .any(|(rejection, profile)| {
94                    rejection.profile_id != profile.id || rejection.reason.trim().is_empty()
95                })
96        {
97            return Err(invalid(
98                "rejections must explain exactly the declared candidates before the selected profile",
99            ));
100        }
101        let prepared_family_fingerprint = family.fingerprint()?;
102        let capability_catalog_fingerprint = capabilities.fingerprint()?;
103        let runtime_policy_fingerprint = canonical_runtime_policy_fingerprint(runtime)?;
104        let payload = plan.payload();
105        if payload.prepared_family_fingerprint() != prepared_family_fingerprint
106            || payload.program_fingerprint() != family.program().fingerprint()?
107            || payload.capability_catalog_fingerprint() != capability_catalog_fingerprint
108            || payload.policy_fingerprint() != runtime_policy_fingerprint
109        {
110            return Err(invalid(
111                "static plan belongs to another family, catalog or runtime policy",
112            ));
113        }
114        Ok(Self {
115            parts: NumericalProfileResolutionWire {
116                requested,
117                requested_kv_storage,
118                selected_kv_storage: selected.kv_storage_format()?,
119                selected_profile: selected.id.clone(),
120                selected_version: selected.version,
121                profile_fingerprint: selected.fingerprint()?,
122                qualification_version: profiles.version(),
123                definition_fingerprint: definition.fingerprint()?,
124                prepared_family_fingerprint,
125                capability_catalog_fingerprint,
126                runtime_policy_fingerprint,
127                execution_plan_hash: plan.plan_hash().as_str().to_owned(),
128                rejected,
129            },
130        })
131    }
132
133    pub fn requested(&self) -> &NumericalExecutionPolicy {
134        &self.parts.requested
135    }
136
137    pub fn requested_kv_storage(&self) -> KvStorageFormat {
138        self.parts.requested_kv_storage
139    }
140
141    pub fn selected_kv_storage(&self) -> Option<KvStorageFormat> {
142        self.parts.selected_kv_storage
143    }
144
145    pub fn selected_profile(&self) -> &NumericalProfileId {
146        &self.parts.selected_profile
147    }
148
149    pub fn rejected(&self) -> &[NumericalProfileRejection] {
150        &self.parts.rejected
151    }
152
153    pub(crate) fn matches_wire(&self, wire: &NumericalProfileResolutionWire) -> bool {
154        &self.parts == wire
155    }
156
157    pub(crate) fn validate_for(
158        &self,
159        definition: &ModelFamilyDefinition,
160        family: &PreparedModelFamily,
161        capabilities: &CapabilityCatalog,
162        runtime: &ResolvedRuntimePolicy,
163        plan: &ExecutionPlan,
164    ) -> Result<(), VNextError> {
165        let rebuilt = Self::from_static_plan(
166            self.parts.requested.clone(),
167            self.parts.requested_kv_storage,
168            definition,
169            family,
170            capabilities,
171            runtime,
172            plan,
173            self.parts.rejected.clone(),
174        )?;
175        if &rebuilt != self {
176            return Err(invalid(
177                "selection evidence differs from typed reconstruction",
178            ));
179        }
180        Ok(())
181    }
182}