use lean_ctx::core::context_overhead::ContextOverhead;
fn registered() {
super::registry::register_tool_catalog();
}
#[test]
fn card_tools_are_published_mcp_tools() {
registered();
let published: Vec<String> = lean_ctx::core::tool_catalog::tool_defs()
.into_iter()
.map(|tool| tool.name.to_string())
.collect();
let card = lean_ctx::core::a2a::agent_card::build_agent_card("p", false);
let tools = card["capabilities"]["tools"].as_array().expect("tools");
assert!(tools.len() >= 6, "core tools missing: {tools:?}");
for tool in tools {
let name = tool.as_str().expect("tool name");
assert!(
published.iter().any(|p| p == name),
"{name} is not published"
);
}
for hidden in ["ctx_agent", "ctx_handoff", "ctx_task", "ctx_share"] {
assert!(!tools.iter().any(|t| t == hidden), "{hidden} advertised");
}
let skills = card["skills"].as_array().expect("skills");
assert!(!skills.iter().any(|s| s["id"] == "multi-agent-coordination"));
}
#[test]
fn measure_reports_nonzero_components() {
registered();
let _iso = lean_ctx::core::data_dir::isolated_data_dir();
let o = ContextOverhead::measure();
assert!(o.tool_count > 0, "must expose at least one tool");
assert!(o.tool_schema_tokens > 0, "tool schemas carry tokens");
assert!(o.instruction_tokens > 0, "instructions carry tokens");
assert!(o.rules_block_tokens > 0, "rules block carries tokens");
assert_eq!(
o.total_tokens(),
o.tool_schema_tokens + o.instruction_tokens + o.rules_block_tokens
);
}
#[test]
fn governor_arm_per_turn_prefix_stays_within_budget() {
use lean_ctx::core::claude_host::GovernorArm;
const BUDGETS: &[(GovernorArm, usize)] =
&[(GovernorArm::NoMcp, 100), (GovernorArm::McpDeferred, 220)];
registered();
let _iso = lean_ctx::core::data_dir::isolated_data_dir();
let default_claude = ContextOverhead::measure_for_client("claude-code").total_tokens();
for &(arm, budget) in BUDGETS {
let o = ContextOverhead::measure_governor(arm);
assert_eq!(o.instruction_tokens, 0, "{arm:?}: no instructions");
assert!(
o.total_tokens() <= budget,
"{arm:?}: governor prefix {} tok (schemas/names {} + rules {}), budget {budget}",
o.total_tokens(),
o.tool_schema_tokens,
o.rules_block_tokens,
);
assert!(
o.total_tokens() * 10 < default_claude,
"{arm:?} ≪ default arm"
);
}
assert_eq!(
ContextOverhead::measure_governor(GovernorArm::NoMcp).tool_count,
0
);
}
#[test]
fn auto_approve_names_only_advertised_tools() {
use lean_ctx::core::editor_registry::auto_approve_tools;
registered();
let registered: std::collections::HashSet<String> = lean_ctx::tool_defs::granular_tool_defs()
.iter()
.map(|t| t.name.to_string())
.collect();
let stale: Vec<_> = auto_approve_tools()
.into_iter()
.filter(|n| *n != "ctx")
.filter(|n| {
!(registered.contains(*n)
&& lean_ctx::core::dynamic_tools::is_publicly_advertised_tool(n))
})
.collect();
assert!(stale.is_empty(), "stale autoApprove entries: {stale:?}");
for core in ["ctx_read", "ctx_shell", "ctx_search", "ctx_cost"] {
assert!(
auto_approve_tools().contains(&core),
"{core} lost auto-approval"
);
}
}
#[test]
fn mcp_tools_doc_lists_every_registered_tool() {
registered();
let md = lean_ctx::core::reference_docs::mcp_tools_markdown();
let count = lean_ctx::core::tool_catalog::tool_count();
let headings = md.matches("\n## `").count();
assert!(
headings >= count,
"expected at least one heading per tool: {headings} headings for {count} tools"
);
assert!(md.contains("## `ctx_read`"), "ctx_read must be documented");
assert!(
md.contains("## `ctx_shell`"),
"ctx_shell must be documented"
);
}
#[test]
fn capabilities_list_real_tools_and_read_modes() {
registered();
let v = lean_ctx::core::server_capabilities::capabilities_value();
assert!(
v["tools"]["total"].as_u64().unwrap_or(0) > 0,
"expected at least one tool"
);
assert!(v["read_modes"]["modes"].is_array());
}
#[test]
fn tool_health_counts_advertised_tools() {
registered();
let _iso = lean_ctx::core::data_dir::isolated_data_dir();
let tmp = tempfile::tempdir().unwrap();
let report = lean_ctx::core::tool_health::compute(tmp.path(), tmp.path());
let expected = lean_ctx::core::tool_visibility::advertised_tool_defs_default().len();
assert_eq!(report.advertised_tools, expected);
assert!(report.tool_schema_tokens > 0);
assert!(report.fixed_total_tokens >= report.tool_schema_tokens);
}
#[test]
fn minimal_profile_schema_budget() {
const MINIMAL_SCHEMA_BUDGET_TOKENS: usize = 2800;
registered();
let defs = lean_ctx::core::tool_catalog::tool_defs();
let total: usize = defs
.iter()
.filter(|t| lean_ctx::core::tool_profiles::MINIMAL_TOOLS.contains(&t.name.as_ref()))
.map(lean_ctx::core::context_overhead::tool_tokens)
.sum();
assert!(total > 0, "minimal tools must exist in the registry");
assert!(
total <= MINIMAL_SCHEMA_BUDGET_TOKENS,
"minimal-profile tool schemas = {total} tok, budget {MINIMAL_SCHEMA_BUDGET_TOKENS}"
);
}
#[test]
fn core_tool_surface_stays_within_budget() {
const PER_TOOL_BUDGET: usize = 410;
const TOTAL_BUDGET: usize = 3000;
registered();
let _guard = lean_ctx::core::data_dir::isolated_data_dir();
let core = lean_ctx::tool_defs::core_tool_names();
let defs: Vec<_> = lean_ctx::core::tool_catalog::tool_defs()
.into_iter()
.filter(|t| core.contains(&t.name.as_ref()))
.collect();
assert_eq!(defs.len(), core.len(), "every core tool must be registered");
let mut total = 0usize;
for t in &defs {
let desc = t.description.as_deref().unwrap_or("");
let schema = serde_json::to_string(&t.input_schema).unwrap_or_default();
let cost = lean_ctx::core::tokens::count_tokens(desc)
+ lean_ctx::core::tokens::count_tokens(&schema);
eprintln!("{:24} {cost:4} tok", t.name.as_ref());
assert!(
cost <= PER_TOOL_BUDGET,
"{} costs {cost} tok (budget {PER_TOOL_BUDGET}) — trim its description/schema",
t.name
);
total += cost;
}
eprintln!("CORE TOTAL: {total} tok / {} tools", defs.len());
assert!(
total <= TOTAL_BUDGET,
"core surface costs {total} tok (budget {TOTAL_BUDGET})"
);
}
#[test]
fn local_collaboration_tools_stay_callable_but_are_never_advertised() {
use lean_ctx::core::tool_profiles::ToolProfile;
use lean_ctx::core::tool_visibility::{ClientQuirks, is_tool_visible};
registered();
let defs = lean_ctx::core::tool_catalog::registered_tool_defs();
for name in lean_ctx::core::dynamic_tools::LOCAL_COLLABORATION_COMPATIBILITY_TOOLS {
assert!(
ToolProfile::Power.is_tool_enabled(name),
"{name} must remain directly compatible with Power callers"
);
assert!(
defs.iter().any(|tool| tool.name.as_ref() == *name),
"{name} must stay registered for local compatibility"
);
assert!(
!is_tool_visible(
name,
&ToolProfile::Power,
&[],
ClientQuirks::default(),
true
),
"{name} must not be advertised from tools/list"
);
}
}
#[test]
fn core_tool_names_exist_in_registry() {
registered();
let registry = lean_ctx::core::tool_catalog::registered_tool_names();
for &name in lean_ctx::tool_defs::CORE_TOOL_NAMES {
assert!(
registry.iter().any(|n| n == name),
"CORE_TOOL_NAMES references '{name}' which is not registered"
);
}
}
#[test]
fn unified_names_are_registry_tools_or_meta() {
registered();
let registry = lean_ctx::core::tool_catalog::registered_tool_names();
for t in lean_ctx::tool_defs::unified_tool_defs() {
let name = t.name.as_ref();
assert!(
name == "ctx" || registry.iter().any(|n| n == name),
"unified tool '{name}' is neither the ctx meta-tool nor a registry tool"
);
}
}
#[test]
fn readonly_tool_names_exist_in_registry() {
registered();
let registry = lean_ctx::core::tool_catalog::registered_tool_names();
for &name in lean_ctx::tool_defs::READONLY_TOOL_NAMES {
assert!(
registry.iter().any(|n| n == name),
"READONLY_TOOL_NAMES references '{name}' which is not registered"
);
}
}