use serde::{Deserialize, Serialize};
use super::candidates::CandidateProfile;
pub const AGGREGATE_BUDGET_MIB: f64 = 1024.0;
pub const EMBED_WORKER_HOST_BUDGET_MIB: f64 = 350.0;
pub const DAEMON_BASE_BUDGET_MIB: f64 = 100.0;
pub const MCP_SHIMS_BUDGET_MIB: f64 = 45.0;
pub const PROJECT_METADATA_BUDGET_MIB: f64 = 150.0;
pub const MMAP_WORKING_SET_BUDGET_MIB: f64 = 150.0;
pub const INDEX_TRANSIENT_STEADY_MIB: f64 = 25.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BudgetScenario {
CpuOnly,
Gpu,
}
impl BudgetScenario {
pub fn as_str(&self) -> &'static str {
match self {
Self::CpuOnly => "cpu_only",
Self::Gpu => "gpu",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BudgetFitResult {
pub candidate_id: String,
pub scenario: BudgetScenario,
pub embed_worker_host_rss_mib: f64,
pub embed_worker_gpu_vram_mib: f64,
pub reranker_cost_mib: f64,
pub fits_embed_worker_host: bool,
pub fits_aggregate: bool,
pub aggregate_total_mib: f64,
pub notes: String,
}
impl BudgetFitResult {
pub fn total_embed_cost_mib(&self) -> f64 {
self.embed_worker_host_rss_mib + self.embed_worker_gpu_vram_mib + self.reranker_cost_mib
}
pub fn fits_all(&self) -> bool {
self.fits_embed_worker_host && self.fits_aggregate
}
}
pub fn compute_budget_fit(
profile: &CandidateProfile,
scenario: BudgetScenario,
reranker_cost_mib: f64,
) -> BudgetFitResult {
let (host_rss, gpu_vram) = match scenario {
BudgetScenario::CpuOnly => {
let model_in_host = profile.model_size_mib;
let runtime_overhead = profile.host_rss_mib; (model_in_host + runtime_overhead, 0.0)
}
BudgetScenario::Gpu => {
(profile.host_rss_mib, profile.gpu_vram_mib)
}
};
let fits_embed_worker = host_rss + reranker_cost_mib <= EMBED_WORKER_HOST_BUDGET_MIB;
let aggregate = DAEMON_BASE_BUDGET_MIB
+ MCP_SHIMS_BUDGET_MIB
+ PROJECT_METADATA_BUDGET_MIB
+ MMAP_WORKING_SET_BUDGET_MIB
+ INDEX_TRANSIENT_STEADY_MIB
+ host_rss
+ gpu_vram
+ reranker_cost_mib;
let fits_aggregate = aggregate <= AGGREGATE_BUDGET_MIB;
let notes = if fits_embed_worker && fits_aggregate {
format!(
"Fits §7 budget: embed worker host {:.0} MiB <= {:.0} MiB, aggregate {:.0} MiB <= {:.0} MiB",
host_rss + reranker_cost_mib,
EMBED_WORKER_HOST_BUDGET_MIB,
aggregate,
AGGREGATE_BUDGET_MIB,
)
} else if !fits_embed_worker {
format!(
"CONFLICT: embed worker host {:.0} MiB exceeds {:.0} MiB allocation",
host_rss + reranker_cost_mib,
EMBED_WORKER_HOST_BUDGET_MIB,
)
} else {
format!(
"CONFLICT: aggregate {:.0} MiB exceeds {:.0} MiB target",
aggregate, AGGREGATE_BUDGET_MIB,
)
};
BudgetFitResult {
candidate_id: profile.id.clone(),
scenario,
embed_worker_host_rss_mib: host_rss,
embed_worker_gpu_vram_mib: gpu_vram,
reranker_cost_mib,
fits_embed_worker_host: fits_embed_worker,
fits_aggregate,
aggregate_total_mib: aggregate,
notes,
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BudgetAnalysis {
pub results: Vec<BudgetFitResult>,
pub any_fits: bool,
pub best_candidate_id: Option<String>,
pub embed_worker_host_budget_mib: f64,
pub aggregate_budget_mib: f64,
pub conflict_reported: bool,
}
pub fn analyze_budget(catalog: &[CandidateProfile], reranker_cost_mib: f64) -> BudgetAnalysis {
let scenarios = [BudgetScenario::CpuOnly, BudgetScenario::Gpu];
let mut results: Vec<BudgetFitResult> = Vec::new();
let mut best: Option<(String, f64)> = None;
for profile in catalog {
for scenario in &scenarios {
let fit = compute_budget_fit(profile, *scenario, reranker_cost_mib);
if fit.fits_all() {
let total = fit.total_embed_cost_mib();
if best.as_ref().is_none_or(|(_, b)| total < *b) {
best = Some((profile.id.clone(), total));
}
}
results.push(fit);
}
}
let any_fits = best.is_some();
BudgetAnalysis {
results,
any_fits,
best_candidate_id: best.map(|(id, _)| id),
embed_worker_host_budget_mib: EMBED_WORKER_HOST_BUDGET_MIB,
aggregate_budget_mib: AGGREGATE_BUDGET_MIB,
conflict_reported: !any_fits,
}
}
pub fn generate_budget_markdown(analysis: &BudgetAnalysis) -> String {
let mut md = String::new();
md.push_str("# WS11 Task 6: Section 7 Budget Ledger Analysis\n\n");
md.push_str("**Date:** 2026-08-04\n");
md.push_str("**Spec ref:** §7 (budget conflict), §2.1 #6/#7 (anti-cheat: GPU counted)\n\n");
md.push_str("## Methodology\n\n");
md.push_str(
"The §7 budget ledger allocates 350 MiB of host RSS to the embed worker (steady).\n\
GPU VRAM is counted separately. On CPU-only deployments, model weights live in\n\
host RSS; on GPU deployments, weights live in VRAM.\n\n",
);
md.push_str("## Section 7 Budget Ledger\n\n");
md.push_str("| Component | Steady Target (MiB) |\n");
md.push_str("|-----------|-------------------:|\n");
md.push_str(&format!(
"| MCP shims (3 clients) | {:.0} |\n",
MCP_SHIMS_BUDGET_MIB
));
md.push_str(&format!(
"| leindexd base/runtime | {:.0} |\n",
DAEMON_BASE_BUDGET_MIB
));
md.push_str(&format!(
"| Project metadata (2 projects) | {:.0} |\n",
PROJECT_METADATA_BUDGET_MIB
));
md.push_str(&format!(
"| Resident mmap working set | {:.0} |\n",
MMAP_WORKING_SET_BUDGET_MIB
));
md.push_str(&format!(
"| Index transient buffers | {:.0} |\n",
INDEX_TRANSIENT_STEADY_MIB
));
md.push_str(&format!(
"| **Embed worker host memory** | **{:.0}** |\n",
EMBED_WORKER_HOST_BUDGET_MIB
));
md.push_str(&format!(
"| **Total** | **<= {:.0}** |\n\n",
AGGREGATE_BUDGET_MIB
));
md.push_str("## Per-Candidate Budget Fit\n\n");
md.push_str(
"| Candidate | Scenario | Embed Host RSS | GPU VRAM | Reranker | Fits Host | Fits Aggregate |\n",
);
md.push_str("|-----------|----------|---------------:|---------:|---------:|-----------|---------------|\n");
for result in &analysis.results {
md.push_str(&format!(
"| {} | {} | {:.0} | {:.0} | {:.0} | {} | {} |\n",
result.candidate_id,
result.scenario.as_str(),
result.embed_worker_host_rss_mib,
result.embed_worker_gpu_vram_mib,
result.reranker_cost_mib,
if result.fits_embed_worker_host {
"YES"
} else {
"NO"
},
if result.fits_aggregate { "YES" } else { "NO" },
));
}
md.push_str("\n## Decision\n\n");
if let Some(ref id) = analysis.best_candidate_id {
md.push_str(&format!(
"**Budget fit confirmed** for candidate `{}`. The validated profile fits the §7 budget.\n",
id
));
} else {
md.push_str(
"**CONFLICT REPORT:** No candidate fits the §7 budget at acceptable quality.\n\
Per anti-cheat section 2.1 #4, #13, the conflict is reported — not manufactured.\n\
Escalation: revise the §7 target or accept a documented quality delta.\n",
);
}
md.push_str(&format!(
"\n**Conflict reported (VAL-EVAL-010):** {}\n",
if analysis.conflict_reported {
"YES"
} else {
"NO — budget fit confirmed"
}
));
md
}
#[cfg(test)]
mod tests {
use super::*;
use crate::eval::candidates::build_candidate_catalog;
#[test]
fn test_embed_worker_budget_constant() {
assert_eq!(EMBED_WORKER_HOST_BUDGET_MIB, 350.0);
}
#[test]
fn test_aggregate_budget_constant() {
assert_eq!(AGGREGATE_BUDGET_MIB, 1024.0);
}
#[test]
fn test_budget_fit_cpu_only_coderank_no_reranker() {
let catalog = build_candidate_catalog();
let coderank = catalog
.iter()
.find(|c| c.id == "coderank-embed-137m")
.expect("coderank candidate");
let result = compute_budget_fit(coderank, BudgetScenario::CpuOnly, 0.0);
assert!(
result.embed_worker_host_rss_mib > 0.0,
"Host RSS must be positive"
);
}
#[test]
fn test_budget_fit_cpu_only_coderank_int8_no_reranker() {
let catalog = build_candidate_catalog();
let coderank = catalog
.iter()
.find(|c| c.id == "coderank-embed-137m")
.expect("coderank candidate");
let mut int8_profile = coderank.clone();
int8_profile.model_size_mib = coderank.model_size_mib / 2.0;
int8_profile.id = "coderank-embed-137m-int8".to_string();
let result = compute_budget_fit(&int8_profile, BudgetScenario::CpuOnly, 0.0);
assert!(
result.fits_embed_worker_host,
"CodeRankEmbed INT8 should fit embed worker budget on CPU: got host RSS {:.0} MiB",
result.embed_worker_host_rss_mib
);
assert!(
result.fits_aggregate,
"CodeRankEmbed INT8 should fit aggregate budget on CPU"
);
}
#[test]
fn test_budget_fit_gpu_coderank_no_reranker() {
let catalog = build_candidate_catalog();
let coderank = catalog
.iter()
.find(|c| c.id == "coderank-embed-137m")
.expect("coderank candidate");
let result = compute_budget_fit(coderank, BudgetScenario::Gpu, 0.0);
assert_eq!(result.embed_worker_host_rss_mib, 120.0);
assert_eq!(result.embed_worker_gpu_vram_mib, 270.0);
assert!(
result.fits_embed_worker_host,
"CodeRankEmbed on GPU should fit embed worker host budget"
);
}
#[test]
fn test_budget_fit_fp16_qwen3_exceeds_budget() {
let catalog = build_candidate_catalog();
let qwen3 = catalog
.iter()
.find(|c| c.id == "qwen3-fp16")
.expect("qwen3 baseline");
let result_cpu = compute_budget_fit(qwen3, BudgetScenario::CpuOnly, 0.0);
let result_gpu = compute_budget_fit(qwen3, BudgetScenario::Gpu, 0.0);
assert!(
!result_cpu.fits_embed_worker_host,
"FP16 Qwen3 on CPU should exceed budget"
);
assert!(
!result_gpu.fits_aggregate,
"FP16 Qwen3 should not fit aggregate budget even on GPU"
);
}
#[test]
fn test_budget_fit_with_reranker_exceeds() {
let catalog = build_candidate_catalog();
let coderank = catalog
.iter()
.find(|c| c.id == "coderank-embed-137m")
.expect("coderank candidate");
let result = compute_budget_fit(coderank, BudgetScenario::CpuOnly, 1190.0);
assert!(
!result.fits_all(),
"CodeRankEmbed + reranker should NOT fit budget"
);
}
#[test]
fn test_analyze_budget_finds_fitting_candidate() {
let catalog = build_candidate_catalog();
let analysis = analyze_budget(&catalog, 0.0);
assert!(
analysis.any_fits,
"At least one candidate should fit: {}",
analysis
.results
.iter()
.filter(|r| r.fits_all())
.map(|r| r.candidate_id.as_str())
.collect::<Vec<_>>()
.join(", ")
);
}
#[test]
fn test_analyze_budget_conflict_when_no_reranker_relief() {
let catalog = build_candidate_catalog();
let analysis = analyze_budget(&catalog, 1190.0);
assert!(
analysis.results.iter().all(|r| !r.fits_all()),
"With 1190 MiB reranker, no candidate should fit budget"
);
}
#[test]
fn test_budget_markdown_contains_section7_ledger() {
let catalog = build_candidate_catalog();
let analysis = analyze_budget(&catalog, 0.0);
let md = generate_budget_markdown(&analysis);
assert!(md.contains("Section 7 Budget Ledger"));
assert!(md.contains("Embed worker host memory"));
assert!(md.contains("350"));
assert!(md.contains("1024"));
}
#[test]
fn test_budget_markdown_reports_conflict_when_applicable() {
let catalog = build_candidate_catalog();
let analysis = analyze_budget(&catalog, 1190.0);
let md = generate_budget_markdown(&analysis);
assert!(md.contains("CONFLICT"));
assert!(md.contains("VAL-EVAL-010"));
}
#[test]
fn test_budget_scenario_cpu_only_vram_zero() {
let catalog = build_candidate_catalog();
let coderank = catalog
.iter()
.find(|c| c.id == "coderank-embed-137m")
.unwrap();
let result = compute_budget_fit(coderank, BudgetScenario::CpuOnly, 0.0);
assert_eq!(
result.embed_worker_gpu_vram_mib, 0.0,
"GPU VRAM must be 0 on CPU-only"
);
}
}