use crate::surface::{build_surface, build_surface_cached, SurfaceMode, SurfacePolicy, SurfaceRequest};
use crate::ContextCompiler;
use scc_core::kinds;
use scc_core::{estimate_tokens, ContextArtifact, ContextBudget, ContextLedger};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
pub const RENDERER_VERSION: &str = env!("CARGO_PKG_VERSION");
pub struct StartupContext {
pub atlas: String,
pub atlas_budget_used: usize,
pub skeleton: String,
pub surface: String,
pub important: String,
pub surface_render: scc_core::SurfaceRenderResult,
pub coverage: Vec<String>,
pub omissions: Vec<String>,
pub artifact: ContextArtifact,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct GlobalRankCache {
pub epoch: String,
pub policy: String,
pub salt: String,
pub global_vector: Vec<f64>,
pub node_symbol_map: BTreeMap<String, f64>,
pub candidates_epoch: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub candidate_ids: Vec<String>,
#[serde(default)]
pub hits: u64,
}
pub fn allocate_startup_budget(
compiler: &ContextCompiler,
target_tokens: Option<usize>,
) -> ContextBudget {
let total = target_tokens.unwrap_or(compiler.settings.startup_tokens);
let view = &compiler.view;
let entity_count = view.entities().count();
let component_count = view.components().len();
let flow_count = view.flows().len();
let surface_candidates = view.entities_of_kind(scc_core::kinds::SYMBOL).len();
scc_core::ContextBudget::adaptive(total, entity_count, component_count, flow_count, surface_candidates)
}
fn coverage_lines(
compiler: &ContextCompiler,
render_ids: usize,
candidates: usize,
render_tokens: usize,
surface_budget: usize,
) -> Vec<String> {
let mut coverage = Vec::new();
for w in compiler_warnings(compiler) {
coverage.push(w);
}
let mut stale: Vec<String> = compiler.stale_paths.clone();
stale.sort();
stale.dedup();
const MAX_STALE_LINES: usize = 10;
for p in stale.iter().take(MAX_STALE_LINES) {
coverage.push(format!("stale: {p}"));
}
if stale.len() > MAX_STALE_LINES {
coverage.push(format!(
"stale: โฆand {} more changed file(s) not yet re-indexed",
stale.len() - MAX_STALE_LINES
));
}
coverage.push(format!(
"surface map: {} of {} entries rendered, {} tokens (budget {})",
render_ids,
candidates,
render_tokens,
surface_budget
));
coverage
}
fn omission_lines(
render_omissions: &[scc_core::SurfaceOmission],
omitted_len: usize,
atlas_dropped: &[String],
atlas_hard_truncated: bool,
atlas_exceeded: bool,
) -> Vec<String> {
let mut omissions = Vec::new();
for o in render_omissions {
omissions.push(format!("surface: {} ({})", o.kind, o.reason));
}
if omitted_len > 0 {
omissions.push(format!(
"surface: {} lower-ranked definitions omitted",
omitted_len
));
}
for d in atlas_dropped {
omissions.push(format!("atlas section dropped: {d}"));
}
if atlas_hard_truncated {
omissions.push("atlas hard-truncated mid-section".into());
}
if atlas_exceeded {
omissions.push("atlas exceeded soft budget: kept complete, over budget".into());
}
if omissions.is_empty() {
omissions.push("none".into());
}
omissions
}
pub fn build_startup(
compiler: &ContextCompiler,
budget: &ContextBudget,
renderer_version: &str,
) -> StartupContext {
let epoch = compiler
.store
.cache_epoch()
.unwrap_or_else(|_| "no-epoch".into());
let atlas_pack = compiler.system_atlas(Some(budget.atlas));
let atlas = atlas_pack.content.clone();
let paths: Vec<String> = compiler
.store
.all_files()
.unwrap_or_default()
.into_iter()
.map(|(p, _, _, _, _)| p)
.collect();
let mut skeleton =
crate::skeleton::build_skeleton(&paths, crate::skeleton::skeleton_budget(budget.total)).text;
let mut rank_cache = load_global_rank_cache(compiler);
let cache_hit = rank_cache.is_some();
let render = build_surface_cached(
compiler,
SurfaceRequest {
mode: SurfaceMode::Global,
budget: budget.surface,
explain: false,
policy: SurfacePolicy::defaults(budget.surface),
semantic: None,
},
&mut rank_cache,
);
let startup_hard_max = budget.total.saturating_add((budget.total / 5).max(500));
let mut render = render;
let mut atlas_pack = atlas_pack;
let mut atlas = atlas;
let mut atlas_budget = budget.atlas;
let mut coverage = coverage_lines(
compiler,
render.rendered_ids.len(),
render.rendered_ids.len() + render.omitted_ids.len(),
render.token_count,
budget.surface,
);
const BLOCK_HEADER_OVERHEAD: usize = 40; let mut iterations = 0;
loop {
let omissions_probe = omission_lines(
&render.omissions,
render.omitted_ids.len(),
&atlas_pack.dropped_sections,
atlas_pack.hard_truncated,
atlas_pack.exceeded_soft_budget,
);
let fused = assemble_body(&atlas, &skeleton, &render.text, "", &coverage, &omissions_probe);
if BLOCK_HEADER_OVERHEAD + estimate_tokens(&fused) <= startup_hard_max {
break;
}
iterations += 1;
if iterations > 64 {
break;
}
let overhead = estimate_tokens(&assemble_body(&atlas, &skeleton, "", "", &coverage, &omissions_probe));
let room = startup_hard_max.saturating_sub(overhead);
if room >= 64 {
let policy = SurfacePolicy {
quotas: true,
mmr: true,
coverage: true,
hard_max: room,
};
render = build_surface_cached(
compiler,
SurfaceRequest {
mode: SurfaceMode::Global,
budget: room,
explain: false,
policy,
semantic: None,
},
&mut rank_cache,
);
coverage = coverage_lines(
compiler,
render.rendered_ids.len(),
render.rendered_ids.len() + render.omitted_ids.len(),
render.token_count,
room,
);
} else {
let smaller = atlas_budget.saturating_mul(3) / 4;
if smaller == atlas_budget {
break; }
atlas_budget = smaller;
atlas_pack = compiler.system_atlas(Some(atlas_budget));
atlas = atlas_pack.content.clone();
}
}
if let Some(c) = &mut rank_cache {
if cache_hit {
c.hits += 1;
}
store_global_rank_cache(compiler, c);
}
let mut surface = render.text.clone();
let mut atlas_budget_used = atlas_budget;
let emergency_omissions: Option<Vec<String>>;
{
let omissions_probe0 = omission_lines(
&render.omissions,
render.omitted_ids.len(),
&atlas_pack.dropped_sections,
atlas_pack.hard_truncated,
atlas_pack.exceeded_soft_budget,
);
if BLOCK_HEADER_OVERHEAD
+ estimate_tokens(&assemble_body(
&atlas,
&skeleton,
&surface,
"",
&coverage,
&omissions_probe0,
))
<= startup_hard_max
{
emergency_omissions = None;
} else {
atlas_budget_used = 256;
atlas_pack = compiler.system_atlas(Some(atlas_budget_used));
atlas = atlas_pack.content.clone();
render.rendered_ids.clear();
render.omitted_ids.clear();
render.omissions.clear();
render.text = String::new();
render.token_count = 0;
surface = String::new();
coverage = compiler_warnings(compiler);
if compiler.stale_paths.is_empty() {
coverage.push("model: current".into());
} else {
coverage.push(format!(
"model stale: {} changed file(s) not yet re-indexed (paths omitted over hard max)",
compiler.stale_paths.len()
));
}
coverage.push("surface map: omitted over hard max (0 rendered)".into());
let mut skel_budget = crate::skeleton::skeleton_budget(budget.total);
loop {
let probe = crate::skeleton::build_skeleton(&paths, skel_budget);
let omissions_probe = {
let mut o = omission_lines(
&[],
0,
&atlas_pack.dropped_sections,
atlas_pack.hard_truncated,
atlas_pack.exceeded_soft_budget,
);
o.push(
"startup emergency compression: atlas essentials + skeleton only (surface omitted over hard max)".into(),
);
o };
let fused = assemble_body(&atlas, &probe.text, "", "", &coverage, &omissions_probe);
if BLOCK_HEADER_OVERHEAD + estimate_tokens(&fused) <= startup_hard_max
|| skel_budget == 0
{
skeleton = probe.text;
emergency_omissions = Some(omissions_probe);
break;
}
skel_budget /= 2;
}
}
}
let important_n = (startup_hard_max / 500).clamp(1, 15);
let mut important = if render.rendered_ids.is_empty() {
"## SYSTEM-CRITICAL SYMBOLS\n(surface omitted over hard max)\n".to_string()
} else {
let top = crate::surface::important_symbols(
compiler,
crate::surface::SurfaceMode::Global,
important_n,
);
crate::surface::render_important(&top, false)
};
{
let probe_om = omission_lines(
&render.omissions,
render.omitted_ids.len(),
&atlas_pack.dropped_sections,
atlas_pack.hard_truncated,
atlas_pack.exceeded_soft_budget,
);
let fused = assemble_body(&atlas, &skeleton, &render.text, &important, &coverage, &probe_om);
if BLOCK_HEADER_OVERHEAD + estimate_tokens(&fused) > startup_hard_max && !render.rendered_ids.is_empty() {
let over = BLOCK_HEADER_OVERHEAD + estimate_tokens(&fused) - startup_hard_max;
let room = render
.token_count
.saturating_sub(over)
.saturating_sub(estimate_tokens(&important));
if room >= 64 {
let policy = SurfacePolicy {
quotas: true,
mmr: true,
coverage: true,
hard_max: room,
};
render = build_surface_cached(
compiler,
SurfaceRequest {
mode: SurfaceMode::Global,
budget: room,
explain: false,
policy,
semantic: None,
},
&mut rank_cache,
);
coverage = coverage_lines(
compiler,
render.rendered_ids.len(),
render.rendered_ids.len() + render.omitted_ids.len(),
render.token_count,
room,
);
important = if render.rendered_ids.is_empty() {
"## SYSTEM-CRITICAL SYMBOLS\n(surface omitted over hard max)\n".to_string()
} else {
let top = crate::surface::important_symbols(
compiler,
crate::surface::SurfaceMode::Global,
important_n,
);
crate::surface::render_important(&top, false)
};
let probe_om2 = omission_lines(
&render.omissions,
render.omitted_ids.len(),
&atlas_pack.dropped_sections,
atlas_pack.hard_truncated,
atlas_pack.exceeded_soft_budget,
);
let fused2 = assemble_body(&atlas, &skeleton, &render.text, &important, &coverage, &probe_om2);
if BLOCK_HEADER_OVERHEAD + estimate_tokens(&fused2) > startup_hard_max {
important = "## SYSTEM-CRITICAL SYMBOLS\n(omitted over hard max)\n".to_string();
}
}
} else {
important = "## SYSTEM-CRITICAL SYMBOLS\n(omitted over hard max)\n".to_string();
}
}
let omissions = emergency_omissions.unwrap_or_else(|| {
omission_lines(
&render.omissions,
render.omitted_ids.len(),
&atlas_pack.dropped_sections,
atlas_pack.hard_truncated,
atlas_pack.exceeded_soft_budget,
)
});
let trust_policy = trust_policy_str(compiler.view.policy());
let mut h = blake3::Hasher::new();
h.update(b"startup-artifact-v1");
h.update(epoch.as_bytes());
h.update(renderer_version.as_bytes());
h.update(trust_policy.as_bytes());
h.update(budget.total.to_string().as_bytes());
h.update(budget.atlas.to_string().as_bytes());
h.update(budget.surface.to_string().as_bytes());
h.update(budget.task_delta.to_string().as_bytes());
h.update(budget.structural_source.to_string().as_bytes());
let sha256 = h.finalize().to_hex().to_string();
let body = assemble_body(&atlas, &skeleton, &surface, &important, &coverage, &omissions);
let mut ch = blake3::Hasher::new();
ch.update(b"startup-content-v1");
ch.update(epoch.as_bytes());
ch.update(renderer_version.as_bytes());
ch.update(trust_policy.as_bytes());
ch.update(budget.total.to_string().as_bytes());
ch.update(budget.atlas.to_string().as_bytes());
ch.update(budget.surface.to_string().as_bytes());
ch.update(budget.task_delta.to_string().as_bytes());
ch.update(budget.structural_source.to_string().as_bytes());
ch.update(body.as_bytes());
let content_hash = ch.finalize().to_hex().to_string();
let mut artifact = ContextArtifact {
kind: "startup".into(),
epoch,
renderer_version: renderer_version.to_string(),
trust_policy,
budget: budget.clone(),
sha256,
content_hash,
text: String::new(),
};
artifact.text = assemble_block(&atlas, &skeleton, &surface, &important, &coverage, &omissions, &artifact);
StartupContext {
atlas,
atlas_budget_used,
skeleton,
surface,
important,
surface_render: render,
coverage,
omissions,
artifact,
}
}
fn global_rank_key(epoch: &str, policy: &str, salt: &str) -> String {
let mut h = blake3::Hasher::new();
h.update(b"rank:global:v1");
h.update(epoch.as_bytes());
h.update(b"\0");
h.update(policy.as_bytes());
h.update(b"\0");
h.update(salt.as_bytes());
format!("rank:global:{}", &h.finalize().to_hex()[..20])
}
pub fn load_global_rank_cache(compiler: &ContextCompiler) -> Option<GlobalRankCache> {
let epoch = compiler.store.cache_epoch().ok()?;
let policy = trust_policy_str(compiler.view.policy());
let salt = &compiler.settings.rank_salt;
let key = global_rank_key(&epoch, &policy, salt);
let cached = compiler.store.cache_get(&key, &epoch).ok().flatten()?;
let c: GlobalRankCache = serde_json::from_str(&cached).ok()?;
if c.epoch != epoch || c.policy != policy || c.salt != *salt {
return None;
}
Some(c)
}
pub fn store_global_rank_cache(compiler: &ContextCompiler, cache: &GlobalRankCache) {
let epoch = compiler
.store
.cache_epoch()
.unwrap_or_else(|_| "no-epoch".into());
let policy = trust_policy_str(compiler.view.policy());
let salt = &compiler.settings.rank_salt;
let key = global_rank_key(&epoch, &policy, salt);
if let Ok(json) = serde_json::to_string(cache) {
let _ = compiler.store.cache_put(&key, &json, &epoch);
}
}
fn symbol_id_of(entry_id: &str) -> String {
entry_id
.rsplit_once("#overload")
.map(|(logical, _)| logical)
.unwrap_or(entry_id)
.to_string()
}
pub fn render_startup(s: &StartupContext) -> String {
assemble_block(&s.atlas, &s.skeleton, &s.surface, &s.important, &s.coverage, &s.omissions, &s.artifact)
}
fn assemble_body(atlas: &str, skeleton: &str, surface: &str, important: &str, coverage: &[String], omissions: &[String]) -> String {
let mut out = String::new();
out.push_str("# SCC SYSTEM CONTEXT\n");
out.push_str("## SYSTEM ATLAS\n");
out.push_str(atlas.trim_end());
out.push_str("\n\n## REPOSITORY SKELETON\n");
out.push_str(skeleton.trim_end());
out.push_str("\n\n## SYSTEM SURFACE MAP\n");
out.push_str(surface.trim_end());
out.push_str("\n\n");
out.push_str(important.trim_end());
out.push_str("\n\n## MODEL COVERAGE\n");
if coverage.is_empty() {
out.push_str("(no warnings)\n");
} else {
for c in coverage {
out.push_str(c);
out.push('\n');
}
}
out.push_str("\n## OMISSIONS\n");
for o in omissions {
out.push_str(o);
out.push('\n');
}
out
}
fn assemble_block(
atlas: &str,
skeleton: &str,
surface: &str,
important: &str,
coverage: &[String],
omissions: &[String],
artifact: &ContextArtifact,
) -> String {
let mut out = String::new();
out.push_str("# SCC SYSTEM CONTEXT\n");
out.push_str(&format!(
"<!-- artifact sha256:{} content_hash:{} epoch:{} renderer:{} -->\n\n",
artifact.sha256, artifact.content_hash, artifact.epoch, artifact.renderer_version
));
out.push_str(&assemble_body(atlas, skeleton, surface, important, coverage, omissions));
out
}
fn compiler_warnings(compiler: &ContextCompiler) -> Vec<String> {
let mut w = Vec::new();
if compiler.store.snapshot_status().ok().flatten().is_none() {
w.push("Repository is not indexed โ run `scc index`.".into());
}
if !compiler.stale_paths.is_empty() {
w.push(format!(
"Model is stale: {} changed file(s) not yet re-indexed.",
compiler.stale_paths.len()
));
}
if let Ok(findings) = compiler.store.drift_findings(true) {
for (_, kind, sev, msg, _) in findings {
if sev == "high" || sev == "critical" {
w.push(format!("Drift [{kind}]: {msg}"));
}
}
}
w.truncate(6);
w
}
pub(crate) fn trust_policy_str(p: &scc_graph::TrustPolicy) -> String {
format!(
"extracted={} resolved={} observed={} declared={} inferred={} floor={}",
p.allow_extracted,
p.allow_resolved,
p.allow_observed,
p.allow_declared,
p.allow_inferred,
p.min_inferred_confidence
)
}
pub fn visible_ids_from_startup(
compiler: &ContextCompiler,
startup: &StartupContext,
) -> (BTreeSet<String>, BTreeSet<String>, BTreeSet<String>, BTreeSet<String>) {
let mut symbols = BTreeSet::new();
let mut files = BTreeSet::new();
let mut components = BTreeSet::new();
let mut flows = BTreeSet::new();
let atlas_pack = compiler.system_atlas(Some(startup.atlas_budget_used));
let view = &compiler.view;
let rendered_symbols: BTreeSet<String> = startup
.surface_render
.rendered_ids
.iter()
.map(|id| symbol_id_of(id))
.collect();
let mut comp_of: BTreeMap<String, String> = BTreeMap::new();
for c in view.components() {
for r in sorted_rels(view.out_pred(&c.id, scc_core::predicates::CONTAINS)) {
for sr in sorted_rels(view.out_pred(&r.object, scc_core::predicates::CONTAINS)) {
if rendered_symbols.contains(&sr.object) {
comp_of
.entry(sr.object.clone())
.or_insert_with(|| c.name.clone());
}
}
}
}
for id in &startup.surface_render.rendered_ids {
let symbol_id = symbol_id_of(id);
symbols.insert(symbol_id.clone());
let ent = view.entity(id).or_else(|| view.entity(&symbol_id));
if let Some(e) = ent {
if let Some(f) = e.attributes.get("file").and_then(|v| v.as_str()) {
files.insert(f.to_string());
}
}
if let Some(c) = comp_of.get(&symbol_id) {
components.insert(c.clone());
}
}
for id in &atlas_pack.entity_ids {
if let Some(e) = compiler.view.entity(id) {
match e.kind.as_str() {
kinds::SYMBOL => {
symbols.insert(id.clone());
}
kinds::FILE => {
files.insert(e.name.clone());
}
kinds::COMPONENT => {
components.insert(id.clone());
}
kinds::FLOW => {
flows.insert(id.clone());
}
_ => {}
}
}
}
(symbols, files, components, flows)
}
fn sorted_rels(rels: Vec<&scc_core::Relationship>) -> Vec<&scc_core::Relationship> {
let mut v = rels;
v.sort_by(|a, b| {
a.id.cmp(&b.id)
.then_with(|| a.subject.cmp(&b.subject))
.then_with(|| a.object.cmp(&b.object))
});
v
}
pub fn task_delta_with_ids(
compiler: &ContextCompiler,
goal: &str,
visible: &ContextLedger,
budget_tokens: usize,
semantic: Option<&dyn crate::rank::SemanticScorer>,
) -> (String, Vec<String>) {
let render = build_surface(
compiler,
SurfaceRequest {
mode: SurfaceMode::Task {
goal,
visible: Some(visible),
},
budget: budget_tokens,
explain: false,
policy: SurfacePolicy::defaults(budget_tokens),
semantic,
},
);
let critical = crate::surface::important_symbols(
compiler,
SurfaceMode::Task { goal, visible: Some(visible) },
8,
);
let mut out = String::new();
out.push_str("# SCC TASK DELTA\n");
out.push_str(&format!("TASK-FOCUS: {goal}\n"));
out.push_str(crate::surface::render_important(&critical, true).as_str());
out.push_str("Relevant APIs not already visible:\n");
let body = render
.text
.strip_prefix("SCC SYSTEM SURFACE MAP\n\n")
.unwrap_or(&render.text);
out.push_str(body.trim_end());
out.push('\n');
(out, render.rendered_ids)
}
pub fn task_surface(
compiler: &ContextCompiler,
goal: &str,
budget_tokens: usize,
explain: bool,
semantic: Option<&dyn crate::rank::SemanticScorer>,
) -> String {
task_surface_with_ids(compiler, goal, budget_tokens, explain, semantic).0
}
pub fn task_surface_with_ids(
compiler: &ContextCompiler,
goal: &str,
budget_tokens: usize,
explain: bool,
semantic: Option<&dyn crate::rank::SemanticScorer>,
) -> (String, Vec<String>) {
let render = build_surface(
compiler,
SurfaceRequest {
mode: SurfaceMode::Task {
goal,
visible: None,
},
budget: budget_tokens,
explain,
policy: SurfacePolicy::defaults(budget_tokens),
semantic,
},
);
let mut out = String::new();
out.push_str(&format!("# SYSTEM SURFACE MAP (task-personalized: {goal})\n"));
let body = render
.text
.strip_prefix("SCC SYSTEM SURFACE MAP\n\n")
.unwrap_or(&render.text);
out.push_str(body.trim_end());
out.push('\n');
(out, render.rendered_ids)
}
#[cfg(test)]
mod tests {
use super::*;
fn fixture_compiler() -> (tempfile::TempDir, crate::ContextCompiler<'static>) {
let dir = tempfile::TempDir::new().unwrap();
let root = dir.path().join("repo");
std::fs::create_dir_all(&root).unwrap();
let store = Box::leak(Box::new(
scc_store::Store::open(&dir.path().join("scc.db"), &root).unwrap(),
));
let graph = Box::leak(Box::new(scc_graph::RealityGraph::load(store).unwrap()));
let settings = crate::ContextSettings::default();
let comp = crate::ContextCompiler::new(store, graph, settings, Vec::new());
(dir, comp)
}
#[test]
fn render_startup_emits_spec_headers() {
let sc = StartupContext {
atlas: "ATLAS-BODY".into(),
atlas_budget_used: 6000,
skeleton: "SKELETON-BODY".into(),
surface: "SURFACE-BODY".into(),
important: "IMPORTANT-BODY".into(),
surface_render: scc_core::SurfaceRenderResult {
text: "SURFACE-BODY".into(),
rendered_ids: vec![],
rendered_entries: vec![],
omitted_ids: vec![],
omissions: vec![],
token_count: 0,
critical_drops: vec![],
},
coverage: vec!["stale: a.py".into()],
omissions: vec!["none".into()],
artifact: ContextArtifact {
kind: "startup".into(),
epoch: "epoch:test".into(),
renderer_version: "test".into(),
trust_policy: "floor=0.85".into(),
budget: ContextBudget::default(),
sha256: "abc".into(),
content_hash: "def".into(),
text: String::new(),
},
};
let out = render_startup(&sc);
assert!(out.contains("# SCC SYSTEM CONTEXT"));
assert!(out.contains("## SYSTEM ATLAS"));
assert!(out.contains("## REPOSITORY SKELETON"));
assert!(out.contains("## SYSTEM SURFACE MAP"));
assert!(out.contains("ATLAS-BODY"));
assert!(out.contains("SURFACE-BODY"));
assert!(out.contains("SKELETON-BODY"));
assert!(out.contains("## SYSTEM-CRITICAL SYMBOLS") || out.contains("IMPORTANT-BODY"));
let (ia, ik, is) = (
out.find("## SYSTEM ATLAS").unwrap(),
out.find("## REPOSITORY SKELETON").unwrap(),
out.find("## SYSTEM SURFACE MAP").unwrap(),
);
assert!(ia < ik && ik < is, "skeleton grounds before architecture");
assert!(out.contains("stale: a.py"));
}
#[test]
fn artifact_text_equals_rendered_block() {
let (_dir, comp) = fixture_compiler();
let budget = ContextBudget::default();
let sc = build_startup(&comp, &budget, "test-renderer");
assert_eq!(sc.artifact.text, render_startup(&sc));
assert_eq!(sc.artifact.sha256.len(), 64);
assert_eq!(sc.artifact.content_hash.len(), 64);
assert_ne!(sc.artifact.content_hash, sc.artifact.sha256);
assert!(render_startup(&sc).contains("content_hash:"));
assert_eq!(sc.artifact.epoch, comp.store.cache_epoch().unwrap_or_default());
}
#[test]
fn global_rank_cache_roundtrips_through_the_store() {
let (_dir, comp) = fixture_compiler();
assert!(load_global_rank_cache(&comp).is_none());
let cache = GlobalRankCache {
epoch: comp.store.cache_epoch().unwrap_or_else(|_| "no-epoch".into()),
policy: trust_policy_str(comp.view.policy()),
salt: comp.settings.rank_salt.clone(),
global_vector: vec![0.1, 0.2, 0.3],
node_symbol_map: BTreeMap::from([("repo://r/symbol/a.py/serve".into(), 0.42)]),
candidates_epoch: comp.store.cache_epoch().unwrap_or_default(),
candidate_ids: vec!["repo://r/symbol/a.py/serve".into()],
hits: 1,
};
store_global_rank_cache(&comp, &cache);
let loaded = load_global_rank_cache(&comp).expect("cache entry present after store");
assert_eq!(loaded, cache);
assert_eq!(loaded.hits, 1);
assert_eq!(
loaded.node_symbol_map.get("repo://r/symbol/a.py/serve"),
Some(&0.42)
);
assert_eq!(loaded.candidates_epoch, loaded.epoch);
}
#[test]
fn visible_ids_consume_the_same_render_the_artifact_printed() {
let (_dir, comp) = fixture_compiler();
let budget = ContextBudget::default();
let sc = build_startup(&comp, &budget, "test-renderer");
assert!(sc.artifact.text.contains(&sc.surface));
let (syms, _files, _comps, _flows) = visible_ids_from_startup(&comp, &sc);
for id in &sc.surface_render.rendered_ids {
let symbol_id = symbol_id_of(id);
assert!(
syms.contains(&symbol_id),
"rendered entry {id} must be marked visible (symbol {symbol_id})"
);
}
}
}