1use std::sync::Arc;
18
19pub const BASIS_POINTS: u64 = 10_000;
21const SCALED_BASIS_POINTS: u64 = BASIS_POINTS * BASIS_POINTS;
22const COST_SCALE: u64 = 1_000_000;
23const COST_ROUNDING: u64 = COST_SCALE - 1;
24pub const ALL_PROVIDERS: u64 = u64::MAX;
26pub const ALL_REGIONS: u64 = u64::MAX;
28pub const MAX_PROVIDER_ID: u16 = 63;
30pub const MAX_CATALOG_MODELS: usize = u16::MAX as usize;
32
33#[repr(C)]
35#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
38pub struct KernelModel {
39 pub model_id: u32,
41 pub provider_id: u16,
43 pub quality_bps: u16,
45 pub risk_ceiling_bps: u16,
47 pub enabled: u8,
49 pub p95_latency_ms: u32,
51 pub capabilities: u64,
53 pub region_mask: u64,
55 pub input_cost_microunits_per_million_tokens: u64,
57 pub output_cost_microunits_per_million_tokens: u64,
59}
60
61#[repr(C)]
63#[derive(Clone, Copy, Debug, Eq, PartialEq)]
64#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
65#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
66pub struct KernelInput {
67 pub request_sequence: u64,
69 pub requested_model_id: u32,
71 pub input_tokens: u32,
73 pub output_tokens: u32,
75 pub business_value_microunits: i64,
77 pub budget_limit_microunits: u64,
79 pub risk_bps: u16,
81 pub confidence_bps: u16,
83 pub minimum_quality_bps: u16,
85 pub max_p95_latency_ms: u32,
87 pub required_capabilities: u64,
89 pub allowed_provider_mask: u64,
91 pub required_region_mask: u64,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
97pub enum InputError {
98 #[error("{field} must be <= {max}, got {value}")]
99 OutOfRangeBps {
100 field: &'static str,
101 value: u16,
102 max: u16,
103 },
104}
105
106impl KernelInput {
107 pub fn validate(&self) -> Result<(), InputError> {
112 if self.risk_bps > MAX_BPS {
113 return Err(InputError::OutOfRangeBps {
114 field: "risk_bps",
115 value: self.risk_bps,
116 max: MAX_BPS,
117 });
118 }
119 if self.confidence_bps > MAX_BPS {
120 return Err(InputError::OutOfRangeBps {
121 field: "confidence_bps",
122 value: self.confidence_bps,
123 max: MAX_BPS,
124 });
125 }
126 if self.minimum_quality_bps > MAX_BPS {
127 return Err(InputError::OutOfRangeBps {
128 field: "minimum_quality_bps",
129 value: self.minimum_quality_bps,
130 max: MAX_BPS,
131 });
132 }
133 Ok(())
134 }
135}
136
137#[repr(u8)]
139#[derive(Clone, Copy, Debug, Eq, PartialEq)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141pub enum KernelAction {
142 ExecuteRequested = 1,
144 Substitute = 2,
146 Reject = 3,
148}
149
150impl std::fmt::Display for KernelAction {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 match self {
153 Self::ExecuteRequested => write!(f, "execute_requested"),
154 Self::Substitute => write!(f, "substitute"),
155 Self::Reject => write!(f, "reject"),
156 }
157 }
158}
159
160#[repr(u16)]
162#[derive(Clone, Copy, Debug, Eq, PartialEq)]
163#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
164pub enum KernelReason {
165 RequestedModelMaximizesUtility = 1,
167 AlternativeMaximizesUtility = 2,
169 RiskHardLimit = 100,
171 ConfidenceHardLimit = 101,
173 NoEnabledModel = 102,
175 QualityConstraint = 103,
177 LatencyConstraint = 104,
179 CapabilityConstraint = 105,
181 ProviderConstraint = 106,
183 RegionConstraint = 107,
185 BudgetConstraint = 108,
187 NonPositiveUtility = 109,
189 RiskCeilingConstraint = 110,
191}
192
193impl std::fmt::Display for KernelReason {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195 match self {
196 Self::RequestedModelMaximizesUtility => write!(f, "requested_model_maximizes_utility"),
197 Self::AlternativeMaximizesUtility => write!(f, "alternative_maximizes_utility"),
198 Self::RiskHardLimit => write!(f, "risk_hard_limit"),
199 Self::ConfidenceHardLimit => write!(f, "confidence_hard_limit"),
200 Self::NoEnabledModel => write!(f, "no_enabled_model"),
201 Self::QualityConstraint => write!(f, "quality_constraint"),
202 Self::LatencyConstraint => write!(f, "latency_constraint"),
203 Self::CapabilityConstraint => write!(f, "capability_constraint"),
204 Self::ProviderConstraint => write!(f, "provider_constraint"),
205 Self::RegionConstraint => write!(f, "region_constraint"),
206 Self::BudgetConstraint => write!(f, "budget_constraint"),
207 Self::NonPositiveUtility => write!(f, "non_positive_utility"),
208 Self::RiskCeilingConstraint => write!(f, "risk_ceiling_constraint"),
209 }
210 }
211}
212
213#[repr(C)]
215#[derive(Clone, Copy, Debug, Eq, PartialEq)]
216#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
217#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
218pub struct KernelDecision {
219 pub request_sequence: u64,
221 pub action: KernelAction,
223 pub reason: KernelReason,
225 pub selected_model_id: u32,
227 pub selected_model_index: u16,
229 pub estimated_cost_microunits: u64,
231 pub expected_utility_microunits: i64,
233 pub counterfactual_model_id: u32,
235 pub counterfactual_utility_microunits: i64,
237 pub evaluated_models: u16,
239 pub eligible_models: u16,
241 pub policy_epoch: u64,
243 pub catalog_epoch: u64,
245}
246
247impl KernelDecision {
248 #[must_use]
250 pub const fn is_executable(&self) -> bool {
251 matches!(
252 self.action,
253 KernelAction::ExecuteRequested | KernelAction::Substitute
254 )
255 }
256
257 #[must_use]
259 pub const fn is_requested_execution(&self) -> bool {
260 matches!(self.action, KernelAction::ExecuteRequested)
261 }
262
263 #[must_use]
265 pub const fn is_substitution(&self) -> bool {
266 matches!(self.action, KernelAction::Substitute)
267 }
268
269 #[must_use]
271 pub const fn is_rejected(&self) -> bool {
272 matches!(self.action, KernelAction::Reject)
273 }
274}
275
276#[derive(Clone, Debug)]
284pub struct PolicySnapshot {
285 pub policy_epoch: u64,
286 pub catalog_epoch: u64,
287 pub hard_risk_limit_bps: u16,
288 pub minimum_confidence_bps: u16,
289 pub risk_penalty_multiplier_bps: u16,
290 pub latency_penalty_microunits_per_ms: u64,
297 max_quality_bps: u16,
298 max_p95_latency_ms: u32,
299 max_input_cost: u64,
300 max_output_cost: u64,
301 models: Arc<[KernelModel]>,
302}
303
304#[derive(Clone, Copy)]
305struct Candidate {
306 model_id: u32,
307 model_index: u16,
308 quality_bps: u16,
309 cost: u64,
310 utility: i64,
311}
312
313#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
315#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
316pub struct RejectionHistogram {
317 pub disabled: u16,
319 pub quality: u16,
321 pub risk_ceiling: u16,
323 pub latency: u16,
325 pub capability: u16,
327 pub provider: u16,
329 pub region: u16,
331 pub budget: u16,
333 pub utility: u16,
335}
336
337#[derive(Clone, Copy, Debug, PartialEq, Eq)]
339#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
340pub struct DecisionTrace {
341 pub rejections: RejectionHistogram,
342 pub evaluated_models: u16,
343 pub eligible_models: u16,
344}
345
346pub const MAX_BPS: u16 = 10_000;
348
349pub const MAX_RISK_PENALTY_MULTIPLIER_BPS: u16 = 50_000;
351
352#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
354pub enum PolicyError {
355 #[error("model catalog is empty")]
356 EmptyCatalog,
357 #[error("duplicate model_id {model_id}")]
358 DuplicateModelId { model_id: u32 },
359 #[error("model_id {model_id} has provider_id {provider_id} > MAX_PROVIDER_ID")]
360 InvalidProviderId { model_id: u32, provider_id: u16 },
361 #[error("no enabled models in catalog")]
362 NoEnabledModels,
363 #[error("{field} must be <= {max}, got {value}")]
364 OutOfRangeBps {
365 field: &'static str,
366 value: u16,
367 max: u16,
368 },
369}
370
371#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
373pub enum TrustPolicyError {
374 #[error("policy validation failed: {0}")]
375 Policy(#[from] PolicyError),
376 #[error("model catalog has {len} entries; maximum is {max}")]
377 CatalogTooLarge { len: usize, max: usize },
378 #[error("model_id 0 is reserved for decisions with no selected model")]
379 ReservedModelId,
380 #[error("model_id {model_id} has non-canonical enabled flag {value}; expected 0 or 1")]
381 InvalidEnabledFlag { model_id: u32, value: u8 },
382}
383
384type RejectionCounts = RejectionHistogram;
385
386impl PolicySnapshot {
387 pub fn new_unchecked(
398 policy_epoch: u64,
399 catalog_epoch: u64,
400 hard_risk_limit_bps: u16,
401 minimum_confidence_bps: u16,
402 risk_penalty_multiplier_bps: u16,
403 latency_penalty_microunits_per_ms: u64,
404 models: Vec<KernelModel>,
405 ) -> Self {
406 let max_quality_bps = models
407 .iter()
408 .map(|model| model.quality_bps)
409 .max()
410 .unwrap_or_default();
411 let max_p95_latency_ms = models
412 .iter()
413 .map(|model| model.p95_latency_ms)
414 .max()
415 .unwrap_or_default();
416 let max_input_cost = models
417 .iter()
418 .map(|model| model.input_cost_microunits_per_million_tokens)
419 .max()
420 .unwrap_or_default();
421 let max_output_cost = models
422 .iter()
423 .map(|model| model.output_cost_microunits_per_million_tokens)
424 .max()
425 .unwrap_or_default();
426 Self {
427 policy_epoch,
428 catalog_epoch,
429 hard_risk_limit_bps,
430 minimum_confidence_bps,
431 risk_penalty_multiplier_bps,
432 latency_penalty_microunits_per_ms,
433 max_quality_bps,
434 max_p95_latency_ms,
435 max_input_cost,
436 max_output_cost,
437 models: Arc::from(models),
438 }
439 }
440
441 #[deprecated(
443 since = "0.3.9",
444 note = "use PolicySnapshot::try_new for validated snapshots or new_unchecked for tests"
445 )]
446 pub fn new(
447 policy_epoch: u64,
448 catalog_epoch: u64,
449 hard_risk_limit_bps: u16,
450 minimum_confidence_bps: u16,
451 risk_penalty_multiplier_bps: u16,
452 latency_penalty_microunits_per_ms: u64,
453 models: Vec<KernelModel>,
454 ) -> Self {
455 Self::new_unchecked(
456 policy_epoch,
457 catalog_epoch,
458 hard_risk_limit_bps,
459 minimum_confidence_bps,
460 risk_penalty_multiplier_bps,
461 latency_penalty_microunits_per_ms,
462 models,
463 )
464 }
465
466 pub fn models(&self) -> &[KernelModel] {
468 &self.models
469 }
470
471 pub fn validate(&self) -> Result<(), PolicyError> {
473 if self.hard_risk_limit_bps > MAX_BPS {
474 return Err(PolicyError::OutOfRangeBps {
475 field: "hard_risk_limit_bps",
476 value: self.hard_risk_limit_bps,
477 max: MAX_BPS,
478 });
479 }
480 if self.minimum_confidence_bps > MAX_BPS {
481 return Err(PolicyError::OutOfRangeBps {
482 field: "minimum_confidence_bps",
483 value: self.minimum_confidence_bps,
484 max: MAX_BPS,
485 });
486 }
487 if self.risk_penalty_multiplier_bps > MAX_RISK_PENALTY_MULTIPLIER_BPS {
488 return Err(PolicyError::OutOfRangeBps {
489 field: "risk_penalty_multiplier_bps",
490 value: self.risk_penalty_multiplier_bps,
491 max: MAX_RISK_PENALTY_MULTIPLIER_BPS,
492 });
493 }
494 if self.models.is_empty() {
495 return Err(PolicyError::EmptyCatalog);
496 }
497 let mut seen = std::collections::HashSet::new();
498 let mut any_enabled = false;
499 for model in self.models.iter() {
500 if !seen.insert(model.model_id) {
501 return Err(PolicyError::DuplicateModelId {
502 model_id: model.model_id,
503 });
504 }
505 if model.provider_id > MAX_PROVIDER_ID {
506 return Err(PolicyError::InvalidProviderId {
507 model_id: model.model_id,
508 provider_id: model.provider_id,
509 });
510 }
511 if model.quality_bps > MAX_BPS {
512 return Err(PolicyError::OutOfRangeBps {
513 field: "model.quality_bps",
514 value: model.quality_bps,
515 max: MAX_BPS,
516 });
517 }
518 if model.risk_ceiling_bps > MAX_BPS {
519 return Err(PolicyError::OutOfRangeBps {
520 field: "model.risk_ceiling_bps",
521 value: model.risk_ceiling_bps,
522 max: MAX_BPS,
523 });
524 }
525 if model.enabled != 0 {
526 any_enabled = true;
527 }
528 }
529 if !any_enabled {
530 return Err(PolicyError::NoEnabledModels);
531 }
532 Ok(())
533 }
534
535 pub fn try_new(
540 policy_epoch: u64,
541 catalog_epoch: u64,
542 hard_risk_limit_bps: u16,
543 minimum_confidence_bps: u16,
544 risk_penalty_multiplier_bps: u16,
545 latency_penalty_microunits_per_ms: u64,
546 models: Vec<KernelModel>,
547 ) -> Result<Self, PolicyError> {
548 let snapshot = Self::new_unchecked(
549 policy_epoch,
550 catalog_epoch,
551 hard_risk_limit_bps,
552 minimum_confidence_bps,
553 risk_penalty_multiplier_bps,
554 latency_penalty_microunits_per_ms,
555 models,
556 );
557 snapshot.validate()?;
558 Ok(snapshot)
559 }
560
561 pub fn try_new_trusted(
568 policy_epoch: u64,
569 catalog_epoch: u64,
570 hard_risk_limit_bps: u16,
571 minimum_confidence_bps: u16,
572 risk_penalty_multiplier_bps: u16,
573 latency_penalty_microunits_per_ms: u64,
574 mut models: Vec<KernelModel>,
575 ) -> Result<Self, TrustPolicyError> {
576 if models.len() > MAX_CATALOG_MODELS {
577 return Err(TrustPolicyError::CatalogTooLarge {
578 len: models.len(),
579 max: MAX_CATALOG_MODELS,
580 });
581 }
582 if models.iter().any(|model| model.model_id == 0) {
583 return Err(TrustPolicyError::ReservedModelId);
584 }
585 if let Some(model) = models.iter().find(|model| model.enabled > 1) {
586 return Err(TrustPolicyError::InvalidEnabledFlag {
587 model_id: model.model_id,
588 value: model.enabled,
589 });
590 }
591 models.sort_by_key(|model| model.model_id);
592 let snapshot = Self::new_unchecked(
593 policy_epoch,
594 catalog_epoch,
595 hard_risk_limit_bps,
596 minimum_confidence_bps,
597 risk_penalty_multiplier_bps,
598 latency_penalty_microunits_per_ms,
599 models,
600 );
601 snapshot.validate()?;
602 Ok(snapshot)
603 }
604
605 pub fn prescribe_batch(&self, inputs: &[KernelInput]) -> Vec<KernelDecision> {
607 inputs.iter().map(|&input| self.prescribe(input)).collect()
608 }
609
610 pub fn prescribe_batch_checked(
613 &self,
614 inputs: &[KernelInput],
615 ) -> Result<Vec<KernelDecision>, InputError> {
616 for input in inputs {
617 input.validate()?;
618 }
619 Ok(self.prescribe_batch(inputs))
620 }
621
622 pub fn prescribe_with_trace(&self, input: KernelInput) -> (KernelDecision, DecisionTrace) {
624 let (decision, rejections) = self.prescribe_inner(input);
625 let trace = DecisionTrace {
626 rejections,
627 evaluated_models: decision.evaluated_models,
628 eligible_models: decision.eligible_models,
629 };
630 (decision, trace)
631 }
632
633 pub fn prescribe_with_trace_checked(
635 &self,
636 input: KernelInput,
637 ) -> Result<(KernelDecision, DecisionTrace), InputError> {
638 input.validate()?;
639 Ok(self.prescribe_with_trace(input))
640 }
641
642 #[must_use]
653 pub fn prescribe(&self, input: KernelInput) -> KernelDecision {
654 self.prescribe_inner(input).0
655 }
656
657 pub fn prescribe_checked(&self, input: KernelInput) -> Result<KernelDecision, InputError> {
663 input.validate()?;
664 Ok(self.prescribe(input))
665 }
666
667 #[must_use]
672 pub fn utility_for_model(&self, input: KernelInput, model_id: u32) -> Option<i64> {
673 if input.risk_bps >= self.hard_risk_limit_bps {
674 return None;
675 }
676 if input.confidence_bps < self.minimum_confidence_bps {
677 return None;
678 }
679 let model = self.models.iter().find(|m| m.model_id == model_id)?;
680
681 if model.enabled == 0 {
682 return None;
683 }
684 if model.quality_bps < input.minimum_quality_bps {
685 return None;
686 }
687 if input.max_p95_latency_ms > 0 && model.p95_latency_ms > input.max_p95_latency_ms {
688 return None;
689 }
690 if model.capabilities & input.required_capabilities != input.required_capabilities {
691 return None;
692 }
693 if model.provider_id > MAX_PROVIDER_ID {
694 return None;
695 }
696 if input.allowed_provider_mask != ALL_PROVIDERS
697 && input.allowed_provider_mask & (1_u64 << model.provider_id) == 0
698 {
699 return None;
700 }
701 if input.required_region_mask != 0 && model.region_mask & input.required_region_mask == 0 {
702 return None;
703 }
704 if input.risk_bps > model.risk_ceiling_bps {
705 return None;
706 }
707
708 let all_costs_fit = self.all_costs_fit_u64(input.input_tokens, input.output_tokens);
709 let cost = if all_costs_fit {
710 model_cost_fast(model, input.input_tokens, input.output_tokens)
711 } else {
712 model_cost_reference(model, input.input_tokens, input.output_tokens)
713 };
714 if cost > input.budget_limit_microunits {
715 return None;
716 }
717
718 let value = input.business_value_microunits.max(0) as u64;
719 let confidence_bps = u64::from(input.confidence_bps);
720 let quality_prefix = value.checked_mul(confidence_bps).filter(|prefix| {
721 prefix
722 .checked_mul(u64::from(self.max_quality_bps))
723 .is_some()
724 });
725 let risk_penalty = scaled_term_exact(
726 value,
727 u64::from(input.risk_bps),
728 u64::from(self.risk_penalty_multiplier_bps),
729 );
730 let all_latencies_fit = u64::from(self.max_p95_latency_ms)
731 .checked_mul(self.latency_penalty_microunits_per_ms)
732 .is_some();
733 let quality_adjusted = quality_prefix.map_or_else(
734 || scaled_term_reference(value, confidence_bps, u64::from(model.quality_bps)),
735 |prefix| {
736 i128::from(prefix.wrapping_mul(u64::from(model.quality_bps)) / SCALED_BASIS_POINTS)
737 },
738 );
739 let latency_penalty = if all_latencies_fit {
740 i128::from(
741 u64::from(model.p95_latency_ms)
742 .wrapping_mul(self.latency_penalty_microunits_per_ms),
743 )
744 } else {
745 i128::from(model.p95_latency_ms) * i128::from(self.latency_penalty_microunits_per_ms)
746 };
747 let utility =
748 clamp_i128_to_i64(quality_adjusted - risk_penalty - i128::from(cost) - latency_penalty);
749 if utility <= 0 {
750 return None;
751 }
752 Some(utility)
753 }
754
755 fn prescribe_inner(&self, input: KernelInput) -> (KernelDecision, RejectionHistogram) {
756 if input.risk_bps >= self.hard_risk_limit_bps {
757 return self.reject(input, KernelReason::RiskHardLimit, 0, 0);
758 }
759 if input.confidence_bps < self.minimum_confidence_bps {
760 return self.reject(input, KernelReason::ConfidenceHardLimit, 0, 0);
761 }
762
763 let mut best: Option<Candidate> = None;
764 let mut second: Option<Candidate> = None;
765 let mut eligible_models = 0_u16;
766 let mut rejected = RejectionCounts::default();
767
768 let value = input.business_value_microunits.max(0) as u64;
769 let confidence_bps = u64::from(input.confidence_bps);
770 let quality_prefix = value.checked_mul(confidence_bps).filter(|prefix| {
771 prefix
772 .checked_mul(u64::from(self.max_quality_bps))
773 .is_some()
774 });
775 let risk_penalty = scaled_term_exact(
776 value,
777 u64::from(input.risk_bps),
778 u64::from(self.risk_penalty_multiplier_bps),
779 );
780 let all_costs_fit = self.all_costs_fit_u64(input.input_tokens, input.output_tokens);
781 let all_latencies_fit = u64::from(self.max_p95_latency_ms)
782 .checked_mul(self.latency_penalty_microunits_per_ms)
783 .is_some();
784
785 let check_provider = input.allowed_provider_mask != ALL_PROVIDERS;
786 let check_region = input.required_region_mask != 0;
787 let check_latency = input.max_p95_latency_ms > 0;
788 let latency_pen_per_ms = self.latency_penalty_microunits_per_ms;
789
790 for (index, model) in self.models.iter().enumerate() {
791 if model.enabled == 0 {
793 rejected.disabled += 1;
794 continue;
795 }
796 if model.quality_bps < input.minimum_quality_bps {
797 rejected.quality += 1;
798 continue;
799 }
800 if check_latency && model.p95_latency_ms > input.max_p95_latency_ms {
801 rejected.latency += 1;
802 continue;
803 }
804 if model.capabilities & input.required_capabilities != input.required_capabilities {
805 rejected.capability += 1;
806 continue;
807 }
808 if model.provider_id > MAX_PROVIDER_ID {
811 rejected.provider += 1;
812 continue;
813 }
814 if check_provider && input.allowed_provider_mask & (1_u64 << model.provider_id) == 0 {
815 rejected.provider += 1;
816 continue;
817 }
818 if check_region && model.region_mask & input.required_region_mask == 0 {
819 rejected.region += 1;
820 continue;
821 }
822 if input.risk_bps > model.risk_ceiling_bps {
823 rejected.risk_ceiling += 1;
824 continue;
825 }
826
827 let cost = if all_costs_fit {
828 model_cost_fast(model, input.input_tokens, input.output_tokens)
829 } else {
830 model_cost_reference(model, input.input_tokens, input.output_tokens)
831 };
832 if cost > input.budget_limit_microunits {
833 rejected.budget += 1;
834 continue;
835 }
836
837 let quality_adjusted = quality_prefix.map_or_else(
838 || scaled_term_reference(value, confidence_bps, u64::from(model.quality_bps)),
839 |prefix| {
840 i128::from(
842 prefix.wrapping_mul(u64::from(model.quality_bps)) / SCALED_BASIS_POINTS,
843 )
844 },
845 );
846 let latency_penalty = if all_latencies_fit {
847 i128::from(u64::from(model.p95_latency_ms).wrapping_mul(latency_pen_per_ms))
848 } else {
849 i128::from(model.p95_latency_ms) * i128::from(latency_pen_per_ms)
850 };
851 let utility = clamp_i128_to_i64(
852 quality_adjusted - risk_penalty - i128::from(cost) - latency_penalty,
853 );
854
855 if utility <= 0 {
856 rejected.utility += 1;
857 continue;
858 }
859 eligible_models = eligible_models.saturating_add(1);
860
861 let candidate = Candidate {
862 model_id: model.model_id,
863 model_index: u16::try_from(index).unwrap_or(u16::MAX),
864 quality_bps: model.quality_bps,
865 cost,
866 utility,
867 };
868 match best {
869 None => best = Some(candidate),
870 Some(current) if candidate_better(candidate, current) => {
871 second = best;
872 best = Some(candidate);
873 }
874 _ => {
875 if second.is_none_or(|s| candidate_better(candidate, s)) {
876 second = Some(candidate);
877 }
878 }
879 }
880 }
881
882 let evaluated_models = u16::try_from(self.models.len()).unwrap_or(u16::MAX);
883 let Some(best) = best else {
884 return self.reject(
885 input,
886 dominant_rejection_reason(&rejected),
887 evaluated_models,
888 eligible_models,
889 );
890 };
891 let action = if best.model_id == input.requested_model_id {
892 KernelAction::ExecuteRequested
893 } else {
894 KernelAction::Substitute
895 };
896 (
897 KernelDecision {
898 request_sequence: input.request_sequence,
899 action,
900 reason: if action == KernelAction::ExecuteRequested {
901 KernelReason::RequestedModelMaximizesUtility
902 } else {
903 KernelReason::AlternativeMaximizesUtility
904 },
905 selected_model_id: best.model_id,
906 selected_model_index: best.model_index,
907 estimated_cost_microunits: best.cost,
908 expected_utility_microunits: best.utility,
909 counterfactual_model_id: second.map_or(0, |candidate| candidate.model_id),
910 counterfactual_utility_microunits: second.map_or(0, |candidate| candidate.utility),
911 evaluated_models,
912 eligible_models,
913 policy_epoch: self.policy_epoch,
914 catalog_epoch: self.catalog_epoch,
915 },
916 rejected,
917 )
918 }
919
920 #[inline]
921 fn all_costs_fit_u64(&self, input_tokens: u32, output_tokens: u32) -> bool {
922 let input = u64::from(input_tokens)
923 .checked_mul(self.max_input_cost)
924 .and_then(|value| value.checked_add(COST_ROUNDING));
925 let output = u64::from(output_tokens)
926 .checked_mul(self.max_output_cost)
927 .and_then(|value| value.checked_add(COST_ROUNDING));
928 input
929 .zip(output)
930 .is_some_and(|(input, output)| input.checked_add(output).is_some())
931 }
932
933 fn reject(
937 &self,
938 input: KernelInput,
939 reason: KernelReason,
940 evaluated_models: u16,
941 eligible_models: u16,
942 ) -> (KernelDecision, RejectionHistogram) {
943 (
944 KernelDecision {
945 request_sequence: input.request_sequence,
946 action: KernelAction::Reject,
947 reason,
948 selected_model_id: 0,
949 selected_model_index: u16::MAX,
950 estimated_cost_microunits: 0,
951 expected_utility_microunits: 0,
952 counterfactual_model_id: 0,
953 counterfactual_utility_microunits: 0,
954 evaluated_models,
955 eligible_models,
956 policy_epoch: self.policy_epoch,
957 catalog_epoch: self.catalog_epoch,
958 },
959 RejectionHistogram::default(),
960 )
961 }
962}
963
964#[inline(always)]
965fn model_cost_fast(model: &KernelModel, input_tokens: u32, output_tokens: u32) -> u64 {
966 let input = u64::from(input_tokens)
967 .wrapping_mul(model.input_cost_microunits_per_million_tokens)
968 .wrapping_add(COST_ROUNDING)
969 / COST_SCALE;
970 let output = u64::from(output_tokens)
971 .wrapping_mul(model.output_cost_microunits_per_million_tokens)
972 .wrapping_add(COST_ROUNDING)
973 / COST_SCALE;
974 input.wrapping_add(output)
975}
976
977fn model_cost_reference(model: &KernelModel, input_tokens: u32, output_tokens: u32) -> u64 {
978 let input = u128::from(input_tokens)
979 .saturating_mul(u128::from(model.input_cost_microunits_per_million_tokens))
980 .saturating_add(u128::from(COST_ROUNDING))
981 / u128::from(COST_SCALE);
982 let output = u128::from(output_tokens)
983 .saturating_mul(u128::from(model.output_cost_microunits_per_million_tokens))
984 .saturating_add(u128::from(COST_ROUNDING))
985 / u128::from(COST_SCALE);
986 u64::try_from(input.saturating_add(output)).unwrap_or(u64::MAX)
987}
988
989#[inline]
990fn scaled_term_exact(value: u64, first_bps: u64, second_bps: u64) -> i128 {
991 value
992 .checked_mul(first_bps)
993 .and_then(|value| value.checked_mul(second_bps))
994 .map_or_else(
995 || scaled_term_reference(value, first_bps, second_bps),
996 |numerator| i128::from(numerator / SCALED_BASIS_POINTS),
997 )
998}
999
1000#[inline]
1001fn scaled_term_reference(value: u64, first_bps: u64, second_bps: u64) -> i128 {
1002 i128::from(value) * i128::from(first_bps) * i128::from(second_bps)
1003 / i128::from(SCALED_BASIS_POINTS)
1004}
1005
1006#[inline(always)]
1008fn candidate_better(left: Candidate, right: Candidate) -> bool {
1009 left.utility > right.utility
1010 || (left.utility == right.utility && left.cost < right.cost)
1011 || (left.utility == right.utility
1012 && left.cost == right.cost
1013 && left.quality_bps > right.quality_bps)
1014 || (left.utility == right.utility
1015 && left.cost == right.cost
1016 && left.quality_bps == right.quality_bps
1017 && left.model_id < right.model_id)
1018}
1019
1020fn dominant_rejection_reason(counts: &RejectionCounts) -> KernelReason {
1021 let candidates = [
1022 (counts.capability, KernelReason::CapabilityConstraint),
1023 (counts.region, KernelReason::RegionConstraint),
1024 (counts.provider, KernelReason::ProviderConstraint),
1025 (counts.quality, KernelReason::QualityConstraint),
1026 (counts.risk_ceiling, KernelReason::RiskCeilingConstraint),
1027 (counts.latency, KernelReason::LatencyConstraint),
1028 (counts.budget, KernelReason::BudgetConstraint),
1029 (counts.utility, KernelReason::NonPositiveUtility),
1030 (counts.disabled, KernelReason::NoEnabledModel),
1031 ];
1032 candidates
1033 .into_iter()
1034 .max_by_key(|(count, _)| *count)
1035 .filter(|(count, _)| *count > 0)
1036 .map_or(KernelReason::NoEnabledModel, |(_, reason)| reason)
1037}
1038
1039fn clamp_i128_to_i64(value: i128) -> i64 {
1040 value.clamp(i128::from(i64::MIN), i128::from(i64::MAX)) as i64
1041}
1042
1043#[cfg(test)]
1044mod tests {
1045 use std::{hint::black_box, time::Instant};
1046
1047 use proptest::prelude::*;
1048
1049 use super::*;
1050
1051 const TOOLS: u64 = 1 << 0;
1052 const REGION_EU: u64 = 1 << 0;
1053
1054 fn snapshot() -> PolicySnapshot {
1055 PolicySnapshot::new_unchecked(
1056 7,
1057 11,
1058 9_600,
1059 5_500,
1060 10_000,
1061 2,
1062 vec![
1063 KernelModel {
1064 model_id: 10,
1065 provider_id: 0,
1066 quality_bps: 7_500,
1067 risk_ceiling_bps: 9_500,
1068 enabled: 1,
1069 p95_latency_ms: 180,
1070 capabilities: TOOLS,
1071 region_mask: REGION_EU,
1072 input_cost_microunits_per_million_tokens: 150_000,
1073 output_cost_microunits_per_million_tokens: 600_000,
1074 },
1075 KernelModel {
1076 model_id: 20,
1077 provider_id: 1,
1078 quality_bps: 9_500,
1079 risk_ceiling_bps: 9_500,
1080 enabled: 1,
1081 p95_latency_ms: 450,
1082 capabilities: TOOLS,
1083 region_mask: REGION_EU,
1084 input_cost_microunits_per_million_tokens: 2_500_000,
1085 output_cost_microunits_per_million_tokens: 10_000_000,
1086 },
1087 ],
1088 )
1089 }
1090
1091 fn input() -> KernelInput {
1092 KernelInput {
1093 request_sequence: 1,
1094 requested_model_id: 20,
1095 input_tokens: 2_000,
1096 output_tokens: 500,
1097 business_value_microunits: 100_000_000,
1098 budget_limit_microunits: 20_000_000,
1099 risk_bps: 1_000,
1100 confidence_bps: 9_000,
1101 minimum_quality_bps: 7_000,
1102 max_p95_latency_ms: 1_000,
1103 required_capabilities: TOOLS,
1104 allowed_provider_mask: ALL_PROVIDERS,
1105 required_region_mask: REGION_EU,
1106 }
1107 }
1108
1109 fn prescribe_reference(snapshot: &PolicySnapshot, input: KernelInput) -> KernelDecision {
1110 if input.risk_bps >= snapshot.hard_risk_limit_bps {
1111 return snapshot.reject(input, KernelReason::RiskHardLimit, 0, 0).0;
1112 }
1113 if input.confidence_bps < snapshot.minimum_confidence_bps {
1114 return snapshot
1115 .reject(input, KernelReason::ConfidenceHardLimit, 0, 0)
1116 .0;
1117 }
1118
1119 let mut best: Option<Candidate> = None;
1120 let mut second: Option<Candidate> = None;
1121 let mut eligible_models = 0_u16;
1122 let mut rejected = RejectionCounts::default();
1123 let value = input.business_value_microunits.max(0) as u64;
1124 let risk_penalty = scaled_term_reference(
1125 value,
1126 u64::from(input.risk_bps),
1127 u64::from(snapshot.risk_penalty_multiplier_bps),
1128 );
1129
1130 for (index, model) in snapshot.models.iter().enumerate() {
1131 if model.enabled == 0 {
1132 rejected.disabled += 1;
1133 continue;
1134 }
1135 if model.quality_bps < input.minimum_quality_bps {
1136 rejected.quality += 1;
1137 continue;
1138 }
1139 if input.max_p95_latency_ms > 0 && model.p95_latency_ms > input.max_p95_latency_ms {
1140 rejected.latency += 1;
1141 continue;
1142 }
1143 if model.capabilities & input.required_capabilities != input.required_capabilities {
1144 rejected.capability += 1;
1145 continue;
1146 }
1147 if model.provider_id > MAX_PROVIDER_ID {
1148 rejected.provider += 1;
1149 continue;
1150 }
1151 if input.allowed_provider_mask != ALL_PROVIDERS
1152 && input.allowed_provider_mask & (1_u64 << model.provider_id) == 0
1153 {
1154 rejected.provider += 1;
1155 continue;
1156 }
1157 if input.required_region_mask != 0
1158 && model.region_mask & input.required_region_mask == 0
1159 {
1160 rejected.region += 1;
1161 continue;
1162 }
1163 if input.risk_bps > model.risk_ceiling_bps {
1164 rejected.risk_ceiling += 1;
1165 continue;
1166 }
1167
1168 let cost = model_cost_reference(model, input.input_tokens, input.output_tokens);
1169 if cost > input.budget_limit_microunits {
1170 rejected.budget += 1;
1171 continue;
1172 }
1173 let quality_adjusted = scaled_term_reference(
1174 value,
1175 u64::from(input.confidence_bps),
1176 u64::from(model.quality_bps),
1177 );
1178 let latency_penalty = i128::from(model.p95_latency_ms)
1179 * i128::from(snapshot.latency_penalty_microunits_per_ms);
1180 let utility = clamp_i128_to_i64(
1181 quality_adjusted - risk_penalty - i128::from(cost) - latency_penalty,
1182 );
1183 if utility <= 0 {
1184 rejected.utility += 1;
1185 continue;
1186 }
1187 eligible_models = eligible_models.saturating_add(1);
1188 let candidate = Candidate {
1189 model_id: model.model_id,
1190 model_index: u16::try_from(index).unwrap_or(u16::MAX),
1191 quality_bps: model.quality_bps,
1192 cost,
1193 utility,
1194 };
1195 if best.is_none_or(|current| candidate_better(candidate, current)) {
1196 second = best;
1197 best = Some(candidate);
1198 } else if second.is_none_or(|current| candidate_better(candidate, current)) {
1199 second = Some(candidate);
1200 }
1201 }
1202
1203 let evaluated_models = u16::try_from(snapshot.models.len()).unwrap_or(u16::MAX);
1204 let Some(best) = best else {
1205 return snapshot
1206 .reject(
1207 input,
1208 dominant_rejection_reason(&rejected),
1209 evaluated_models,
1210 eligible_models,
1211 )
1212 .0;
1213 };
1214 let action = if best.model_id == input.requested_model_id {
1215 KernelAction::ExecuteRequested
1216 } else {
1217 KernelAction::Substitute
1218 };
1219 KernelDecision {
1220 request_sequence: input.request_sequence,
1221 action,
1222 reason: if action == KernelAction::ExecuteRequested {
1223 KernelReason::RequestedModelMaximizesUtility
1224 } else {
1225 KernelReason::AlternativeMaximizesUtility
1226 },
1227 selected_model_id: best.model_id,
1228 selected_model_index: best.model_index,
1229 estimated_cost_microunits: best.cost,
1230 expected_utility_microunits: best.utility,
1231 counterfactual_model_id: second.map_or(0, |candidate| candidate.model_id),
1232 counterfactual_utility_microunits: second.map_or(0, |candidate| candidate.utility),
1233 evaluated_models,
1234 eligible_models,
1235 policy_epoch: snapshot.policy_epoch,
1236 catalog_epoch: snapshot.catalog_epoch,
1237 }
1238 }
1239
1240 #[test]
1241 fn prescribes_maximum_utility_not_minimum_price() {
1242 let decision = snapshot().prescribe(input());
1243 assert_eq!(decision.action, KernelAction::ExecuteRequested);
1244 assert_eq!(decision.selected_model_id, 20);
1245 assert_eq!(decision.counterfactual_model_id, 10);
1246 assert!(decision.expected_utility_microunits > decision.counterfactual_utility_microunits);
1247 }
1248
1249 #[test]
1250 fn hard_budget_can_prescribe_substitution() {
1251 let mut request = input();
1252 request.budget_limit_microunits = 1_000;
1253 let decision = snapshot().prescribe(request);
1254 assert_eq!(decision.action, KernelAction::Substitute);
1255 assert_eq!(decision.selected_model_id, 10);
1256 }
1257
1258 #[test]
1259 fn decision_action_helpers_match_action() {
1260 let requested = snapshot().prescribe(input());
1261 assert!(requested.is_executable());
1262 assert!(requested.is_requested_execution());
1263 assert!(!requested.is_substitution());
1264 assert!(!requested.is_rejected());
1265
1266 let mut substitute_input = input();
1267 substitute_input.budget_limit_microunits = 1_000;
1268 let substitute = snapshot().prescribe(substitute_input);
1269 assert!(substitute.is_executable());
1270 assert!(!substitute.is_requested_execution());
1271 assert!(substitute.is_substitution());
1272 assert!(!substitute.is_rejected());
1273
1274 let mut rejected_input = input();
1275 rejected_input.risk_bps = 9_900;
1276 let rejected = snapshot().prescribe(rejected_input);
1277 assert!(!rejected.is_executable());
1278 assert!(!rejected.is_requested_execution());
1279 assert!(!rejected.is_substitution());
1280 assert!(rejected.is_rejected());
1281 }
1282
1283 fn base_model(model_id: u32, enabled: u8) -> KernelModel {
1284 KernelModel {
1285 model_id,
1286 provider_id: 0,
1287 quality_bps: 8_000,
1288 risk_ceiling_bps: 9_500,
1289 enabled,
1290 p95_latency_ms: 200,
1291 capabilities: 0,
1292 region_mask: ALL_REGIONS,
1293 input_cost_microunits_per_million_tokens: 100,
1294 output_cost_microunits_per_million_tokens: 400,
1295 }
1296 }
1297
1298 #[test]
1299 fn input_validate_rejects_out_of_range_bps() {
1300 let mut request = input();
1301 request.confidence_bps = 10_001;
1302 assert_eq!(
1303 request.validate(),
1304 Err(InputError::OutOfRangeBps {
1305 field: "confidence_bps",
1306 value: 10_001,
1307 max: MAX_BPS,
1308 })
1309 );
1310 }
1311
1312 #[test]
1313 fn input_validate_accepts_boundary_bps() {
1314 let mut request = input();
1315 request.risk_bps = MAX_BPS;
1316 request.confidence_bps = MAX_BPS;
1317 request.minimum_quality_bps = MAX_BPS;
1318 assert!(request.validate().is_ok());
1319 }
1320
1321 #[test]
1322 fn checked_prescribe_rejects_invalid_input_before_evaluation() {
1323 let snapshot = snapshot();
1324 let mut request = input();
1325 request.confidence_bps = MAX_BPS + 1;
1326 assert!(matches!(
1327 snapshot.prescribe_checked(request),
1328 Err(InputError::OutOfRangeBps {
1329 field: "confidence_bps",
1330 ..
1331 })
1332 ));
1333 assert!(snapshot.prescribe_with_trace_checked(request).is_err());
1334 assert!(snapshot
1335 .prescribe_batch_checked(&[input(), request])
1336 .is_err());
1337 }
1338
1339 #[test]
1340 fn policy_error_empty_catalog() {
1341 let snap = PolicySnapshot::new_unchecked(1, 1, 9_600, 5_500, 3_500, 0, vec![]);
1342 assert_eq!(snap.validate(), Err(PolicyError::EmptyCatalog));
1343 assert!(matches!(
1344 PolicySnapshot::try_new(1, 1, 9_600, 5_500, 3_500, 0, vec![]),
1345 Err(PolicyError::EmptyCatalog)
1346 ));
1347 }
1348
1349 #[test]
1350 fn policy_error_duplicate_model_id() {
1351 let snap = PolicySnapshot::new_unchecked(
1352 1,
1353 1,
1354 9_600,
1355 5_500,
1356 3_500,
1357 0,
1358 vec![base_model(1, 1), base_model(1, 1)],
1359 );
1360 assert_eq!(
1361 snap.validate(),
1362 Err(PolicyError::DuplicateModelId { model_id: 1 })
1363 );
1364 }
1365
1366 #[test]
1367 fn model_id_zero_is_reserved_for_rejection() {
1368 assert!(matches!(
1369 PolicySnapshot::try_new_trusted(1, 1, 9_600, 5_500, 3_500, 0, vec![base_model(0, 1)]),
1370 Err(TrustPolicyError::ReservedModelId)
1371 ));
1372 }
1373
1374 #[test]
1375 fn catalog_larger_than_decision_counters_is_rejected() {
1376 let models = (1..=u32::from(u16::MAX) + 1)
1377 .map(|model_id| base_model(model_id, 1))
1378 .collect();
1379 assert!(matches!(
1380 PolicySnapshot::try_new_trusted(1, 1, 9_600, 5_500, 3_500, 0, models),
1381 Err(TrustPolicyError::CatalogTooLarge { .. })
1382 ));
1383 }
1384
1385 #[test]
1386 fn policy_error_invalid_provider_id() {
1387 let mut model = base_model(1, 1);
1388 model.provider_id = MAX_PROVIDER_ID + 1;
1389 let snap = PolicySnapshot::new_unchecked(1, 1, 9_600, 5_500, 3_500, 0, vec![model]);
1390 assert_eq!(
1391 snap.validate(),
1392 Err(PolicyError::InvalidProviderId {
1393 model_id: 1,
1394 provider_id: MAX_PROVIDER_ID + 1,
1395 })
1396 );
1397 }
1398
1399 #[test]
1400 fn policy_error_no_enabled_models() {
1401 let snap = PolicySnapshot::new_unchecked(
1402 1,
1403 1,
1404 9_600,
1405 5_500,
1406 3_500,
1407 0,
1408 vec![base_model(1, 0), base_model(2, 0)],
1409 );
1410 assert_eq!(snap.validate(), Err(PolicyError::NoEnabledModels));
1411 }
1412
1413 #[test]
1414 fn policy_error_out_of_range_bps() {
1415 let models = vec![base_model(1, 1)];
1416 assert!(matches!(
1417 PolicySnapshot::try_new(1, 1, 10_001, 5_500, 3_500, 0, models.clone()),
1418 Err(PolicyError::OutOfRangeBps { .. })
1419 ));
1420 assert!(matches!(
1421 PolicySnapshot::try_new(1, 1, 9_600, 10_001, 3_500, 0, models.clone()),
1422 Err(PolicyError::OutOfRangeBps { .. })
1423 ));
1424 assert!(matches!(
1425 PolicySnapshot::try_new(1, 1, 9_600, 5_500, 50_001, 0, models.clone()),
1426 Err(PolicyError::OutOfRangeBps { .. })
1427 ));
1428 let mut bad_quality = base_model(2, 1);
1429 bad_quality.quality_bps = 10_001;
1430 assert!(matches!(
1431 PolicySnapshot::try_new(1, 1, 9_600, 5_500, 3_500, 0, vec![bad_quality]),
1432 Err(PolicyError::OutOfRangeBps { .. })
1433 ));
1434 }
1435
1436 #[test]
1437 fn utility_for_model_matches_eligible_catalog_entry() {
1438 let snap = snapshot();
1439 let input = input();
1440 let utility = snap.utility_for_model(input, 20);
1441 assert!(utility.is_some());
1442 assert_eq!(
1443 utility,
1444 Some(snap.prescribe(input).expected_utility_microunits)
1445 );
1446 }
1447
1448 #[test]
1449 fn utility_for_model_none_for_missing_id() {
1450 let snap = snapshot();
1451 assert!(snap.utility_for_model(input(), 999).is_none());
1452 }
1453
1454 #[test]
1455 fn prescribe_batch_matches_individual() {
1456 let snap = snapshot();
1457 let inputs = [
1458 input(),
1459 KernelInput {
1460 request_sequence: 2,
1461 requested_model_id: 10,
1462 input_tokens: 500,
1463 output_tokens: 100,
1464 business_value_microunits: 50_000_000,
1465 budget_limit_microunits: 5_000_000,
1466 risk_bps: 500,
1467 confidence_bps: 9_500,
1468 minimum_quality_bps: 7_000,
1469 max_p95_latency_ms: 500,
1470 required_capabilities: TOOLS,
1471 allowed_provider_mask: ALL_PROVIDERS,
1472 required_region_mask: REGION_EU,
1473 },
1474 ];
1475 let batch = snap.prescribe_batch(&inputs);
1476 assert_eq!(batch.len(), inputs.len());
1477 for (i, &inp) in inputs.iter().enumerate() {
1478 assert_eq!(batch[i], snap.prescribe(inp));
1479 }
1480 }
1481
1482 #[test]
1483 fn hard_constraints_fail_closed() {
1484 let mut request = input();
1485 request.risk_bps = 9_900;
1486 let decision = snapshot().prescribe(request);
1487 assert_eq!(decision.action, KernelAction::Reject);
1488 assert_eq!(decision.reason, KernelReason::RiskHardLimit);
1489
1490 request.risk_bps = 1_000;
1491 request.required_capabilities = 1 << 9;
1492 let decision = snapshot().prescribe(request);
1493 assert_eq!(decision.action, KernelAction::Reject);
1494 assert_eq!(decision.reason, KernelReason::CapabilityConstraint);
1495 }
1496
1497 #[test]
1498 fn extreme_inputs_saturate_without_panicking() {
1499 let mut request = input();
1500 request.input_tokens = u32::MAX;
1501 request.output_tokens = u32::MAX;
1502 request.business_value_microunits = i64::MAX;
1503 request.budget_limit_microunits = u64::MAX;
1504 let decision = snapshot().prescribe(request);
1505 assert_eq!(decision.request_sequence, request.request_sequence);
1506 }
1507
1508 #[test]
1509 fn exact_fast_path_preserves_single_rounding_step() {
1510 assert_eq!(scaled_term_reference(2, 5_001, 9_999), 1);
1511 assert_eq!(scaled_term_exact(2, 5_001, 9_999), 1);
1512 }
1513
1514 proptest! {
1515 #[test]
1516 fn optimized_scaled_term_matches_i128_reference(
1517 value in any::<u64>(),
1518 first_bps in any::<u16>(),
1519 second_bps in any::<u16>(),
1520 ) {
1521 prop_assert_eq!(
1522 scaled_term_exact(value, u64::from(first_bps), u64::from(second_bps)),
1523 scaled_term_reference(value, u64::from(first_bps), u64::from(second_bps)),
1524 );
1525 }
1526
1527 #[test]
1528 fn optimized_cost_matches_u128_reference_when_guard_admits(
1529 input_tokens in any::<u32>(),
1530 output_tokens in any::<u32>(),
1531 input_price in any::<u64>(),
1532 output_price in any::<u64>(),
1533 ) {
1534 let model = KernelModel {
1535 model_id: 1,
1536 provider_id: 0,
1537 quality_bps: 10_000,
1538 risk_ceiling_bps: u16::MAX,
1539 enabled: 1,
1540 p95_latency_ms: 1,
1541 capabilities: 0,
1542 region_mask: ALL_REGIONS,
1543 input_cost_microunits_per_million_tokens: input_price,
1544 output_cost_microunits_per_million_tokens: output_price,
1545 };
1546 let snapshot = PolicySnapshot::new_unchecked(1, 1, u16::MAX, 0, 0, 0, vec![model]);
1547 if snapshot.all_costs_fit_u64(input_tokens, output_tokens) {
1548 prop_assert_eq!(
1549 model_cost_fast(&model, input_tokens, output_tokens),
1550 model_cost_reference(&model, input_tokens, output_tokens),
1551 );
1552 }
1553 }
1554
1555 #[test]
1556 fn optimized_kernel_matches_reference_decision(
1557 input_tokens in any::<u32>(),
1558 output_tokens in any::<u32>(),
1559 value in any::<i64>(),
1560 budget in any::<u64>(),
1561 risk in any::<u16>(),
1562 confidence in any::<u16>(),
1563 minimum_quality in any::<u16>(),
1564 maximum_latency in any::<u32>(),
1565 provider_mask in any::<u64>(),
1566 region_mask in any::<u64>(),
1567 ) {
1568 let mut request = input();
1569 request.input_tokens = input_tokens;
1570 request.output_tokens = output_tokens;
1571 request.business_value_microunits = value;
1572 request.budget_limit_microunits = budget;
1573 request.risk_bps = risk;
1574 request.confidence_bps = confidence;
1575 request.minimum_quality_bps = minimum_quality;
1576 request.max_p95_latency_ms = maximum_latency;
1577 request.allowed_provider_mask = provider_mask;
1578 request.required_region_mask = region_mask;
1579 let snapshot = snapshot();
1580 prop_assert_eq!(snapshot.prescribe(request), prescribe_reference(&snapshot, request));
1581 }
1582
1583 #[test]
1584 fn arbitrary_inputs_never_bypass_provider_fence(
1585 input_tokens in any::<u32>(),
1586 output_tokens in any::<u32>(),
1587 value in any::<i64>(),
1588 budget in any::<u64>(),
1589 risk in any::<u16>(),
1590 confidence in any::<u16>(),
1591 ) {
1592 let mut request = input();
1593 request.input_tokens = input_tokens;
1594 request.output_tokens = output_tokens;
1595 request.business_value_microunits = value;
1596 request.budget_limit_microunits = budget;
1597 request.risk_bps = risk;
1598 request.confidence_bps = confidence;
1599 request.allowed_provider_mask = 0;
1600 let decision = snapshot().prescribe(request);
1601 prop_assert_eq!(decision.action, KernelAction::Reject);
1602 }
1603 }
1604
1605 #[test]
1606 fn provider_id_above_64_rejected_even_with_all_providers() {
1607 let models = vec![KernelModel {
1608 model_id: 1,
1609 provider_id: 65,
1610 quality_bps: 9500,
1611 risk_ceiling_bps: 10000,
1612 enabled: 1,
1613 p95_latency_ms: 500,
1614 capabilities: 0,
1615 region_mask: ALL_REGIONS,
1616 input_cost_microunits_per_million_tokens: 100,
1617 output_cost_microunits_per_million_tokens: 400,
1618 }];
1619 let snapshot = PolicySnapshot::new_unchecked(1, 1, 9600, 5500, 3500, 0, models);
1620 let mut request = input();
1621 request.allowed_provider_mask = ALL_PROVIDERS;
1622 let decision = snapshot.prescribe(request);
1623 assert_eq!(
1624 decision.action,
1625 KernelAction::Reject,
1626 "provider_id >= 64 must be rejected even when mask is ALL_PROVIDERS"
1627 );
1628 }
1629
1630 #[test]
1631 fn provider_id_below_64_accepted_with_all_providers() {
1632 let mut request = input();
1633 request.allowed_provider_mask = ALL_PROVIDERS;
1634 let decision = snapshot().prescribe(request);
1635 assert_ne!(
1636 decision.action,
1637 KernelAction::Reject,
1638 "provider_id < 64 with ALL_PROVIDERS should not be rejected by provider fence"
1639 );
1640 }
1641
1642 #[test]
1643 #[ignore = "release-only kernel guard"]
1644 fn prescriptive_kernel_latency_guard() {
1645 let snapshot = snapshot();
1646 let base = input();
1647 let iterations = 1_000_000_u64;
1648 let started = Instant::now();
1649 for sequence in 0..iterations {
1650 let mut request = base;
1651 request.request_sequence = sequence;
1652 request.input_tokens = 1_000 + (sequence % 1_024) as u32;
1653 black_box(snapshot.prescribe(black_box(request)));
1654 }
1655 let average_ns = started.elapsed().as_nanos() / u128::from(iterations);
1656 assert!(
1657 average_ns < 2_000,
1658 "prescriptive kernel exceeded 2us average guard: {average_ns}ns"
1659 );
1660 }
1661}