Skip to main content

compile

Function compile 

Source
pub fn compile(
    ctx: &Context,
    input: CompileInput,
) -> Result<CompiledContext, CapabilityError>
Expand description

Compile a context. The one entry point; every projection calls this.

The whole call runs over values the process already holds — the index and the composed graph derived from it — so it reads no file and walks no tree, which is what lets it sit inside a handler rather than at load time.

It fails only on a request that cannot mean anything: a budget of zero, a relevance floor outside 0..=1, a path that is not repository-relative, or a named seed this repository does not hold. Everything else is an answer. In particular a request that names nothing is valid and does not produce an empty context — the governance applies to every session whether or not it was asked for.

The budget is a ceiling on what the compiler chooses, not on what it must keep: seeds, the policy and the scope are never dropped, so an answer can come back over budget and says so rather than omitting the thing it was compiled about.

use majordomus_cli::capability::CapabilityError;
use majordomus_cli::devcontext::{compile, CompileInput, Tier};
use majordomus_cli::synthetic::SyntheticRepository;

let repo = SyntheticRepository::small().unwrap();
let ctx = repo.context().unwrap();

// the governance arrives without being asked for, and cannot be dropped
let c = compile(&ctx, CompileInput::default()).unwrap();
let required: Vec<&str> = c
    .selected
    .iter()
    .filter(|e| e.required)
    .map(|e| e.kind.as_str())
    .collect();
assert!(required.contains(&"policy"), "what every session is held to: {required:?}");
assert!(c.selected.iter().all(|e| e.tier >= Tier::Task));

// a tiny ceiling still keeps what may not be dropped, and says it went over
let squeezed = compile(
    &ctx,
    CompileInput { budget_tokens: Some(1), ..Default::default() },
)
.unwrap();
assert!(squeezed.selected.iter().any(|e| e.required));
assert!(squeezed.budget.over_budget);
assert_eq!(squeezed.budget.limit_tokens, 1);

// and the refusals are requests that could not mean anything
assert!(matches!(
    compile(&ctx, CompileInput { budget_tokens: Some(0), ..Default::default() }),
    Err(CapabilityError::InvalidInput(_)),
));
assert!(matches!(
    compile(&ctx, CompileInput { floor: Some(1.5), ..Default::default() }),
    Err(CapabilityError::InvalidInput(_)),
));
assert!(matches!(
    compile(&ctx, CompileInput { paths: vec!["/etc".into()], ..Default::default() }),
    Err(CapabilityError::InvalidInput(_)),
));
assert!(matches!(
    compile(&ctx, CompileInput { issue: Some("I9999".into()), ..Default::default() }),
    Err(CapabilityError::NotFound(_)),
));