use std::io::Write;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Instant;
use anyhow::{Context, Result};
use newt_core::caveats::{Caveats, CountBound, Scope};
use newt_core::model_card::ChatCompletionsCapability;
use newt_core::role_profile::Cognition;
use newt_core::{
BackendKind, Config, OpenAiApi, RuntimeSettingsSnapshot, TurnDriver, TurnDriverConfig,
TurnStatus,
};
use crate::headless_contract;
pub struct HeadlessArgs {
pub cwd: PathBuf,
pub instruction_file: PathBuf,
pub profile: Option<PathBuf>,
pub non_interactive: bool,
pub unsafe_host_exec: bool,
pub confined: bool,
pub events: Option<PathBuf>,
pub smart_harness: bool,
pub frame_dir: Option<PathBuf>,
pub hermetic_explicit: bool,
pub launch: newt_launch::LaunchConfig,
pub max_rounds: Option<usize>,
pub context_window: Option<u32>,
pub model_digest: Option<String>,
pub scratchpad_state: Option<PathBuf>,
pub require_feature: Vec<headless_contract::Feature>,
pub output_allowance: Option<u32>,
pub run_allowance: Option<u32>,
}
fn workspace_root_system_message(workspace: &str) -> newt_core::MemMessage {
newt_core::MemMessage::system(format!("Workspace root: {workspace}"))
}
fn seed_scratchpad(json: &str) -> Result<(Arc<newt_core::SessionScratchpadStore>, String)> {
use newt_core::ScratchpadStore;
let entries: std::collections::BTreeMap<String, String> = serde_json::from_str(json)
.context("--scratchpad-state must be a JSON object of string values")?;
anyhow::ensure!(
entries.keys().all(|k| !k.trim().is_empty()),
"--scratchpad-state keys must be non-empty"
);
let store = Arc::new(newt_core::SessionScratchpadStore::default());
for (key, value) in entries {
store.set(&key, value);
}
let canonical = content_addressable::canonical::to_canonical_dagcbor(&store.entries())?;
let seed = content_addressable::ContentId::from_canonical_bytes(&canonical).to_string();
Ok((store, seed))
}
fn smart_launch(
launch: &newt_launch::LaunchConfig,
enabled: bool,
hermetic_explicit: bool,
) -> newt_launch::LaunchConfig {
if enabled && !hermetic_explicit && !launch.continuity.is_resumable() {
newt_launch::LaunchConfig {
continuity: newt_launch::Continuity::Resume { from: None },
}
} else {
launch.clone()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum HeadlessLane {
Confined,
Yolo,
}
fn resolve_lane(
confined_flag: bool,
ocap_env: Option<&str>,
unsafe_host_exec: bool,
) -> HeadlessLane {
let confined = confined_flag || ocap_env.is_some_and(|v| v.trim().eq_ignore_ascii_case("on"));
if confined {
HeadlessLane::Confined
} else if unsafe_host_exec {
HeadlessLane::Yolo
} else {
HeadlessLane::Confined
}
}
fn resolve_model_digest(flag: Option<&str>, env: Option<&str>) -> Option<String> {
[flag, env]
.into_iter()
.flatten()
.map(str::trim)
.find(|d| !d.is_empty())
.map(str::to_string)
}
fn apply_context_config(driver: &mut TurnDriverConfig, context: Option<&newt_core::ContextConfig>) {
let Some(context) = context else {
return;
};
driver.compaction_trigger_policy = context.compaction_trigger_policy;
driver.input_ceiling_pct =
newt_core::config::normalize_input_ceiling_pct(context.input_ceiling_pct);
driver.low_budget_pct = context.low_budget_pct;
driver.estimation = context.estimation;
driver.summary_input_cap_floor_chars = context.summary_input_cap_floor_chars;
driver.context_manager = context.manager;
}
fn apply_context_window(driver: &mut TurnDriverConfig, context_window: u32) {
let input_budget =
newt_core::config::input_percentage_ceiling(context_window, driver.input_ceiling_pct);
driver.safe_context = Some(input_budget);
driver.max_ok_input = Some(input_budget);
driver.num_ctx = Some(context_window);
}
fn resolve_runtime_posture(cfg: &Config, family: Option<&str>) -> RuntimeSettingsSnapshot {
newt_core::initiative::set_active_model_family(family.map(str::to_string));
RuntimeSettingsSnapshot::resolve(cfg, None, None)
}
fn headless_tool_round_limit(
configured: usize,
explicit_tenacity: Option<newt_core::Tenacity>,
explicit_rounds: Option<usize>,
) -> usize {
newt_core::tenacity::resolve_tool_round_limit(configured, explicit_tenacity, explicit_rounds)
.rounds
}
fn headless_principal(
serving: Option<newt_core::Serving>,
model: &str,
) -> newt_core::model_card::ServingPrincipal<'_> {
use newt_core::model_card::ServingPrincipal as P;
match serving {
Some(newt_core::Serving::Instance) => P::Instance,
Some(newt_core::Serving::Multiplexer) => P::MultiplexerModel(model),
None => P::SelectedModel(model),
}
}
fn projected_cognition(
cognition: Option<Cognition>,
kind: BackendKind,
api: OpenAiApi,
chat_capability: ChatCompletionsCapability,
) -> Option<Cognition> {
newt_core::agentic::projected_cognition(cognition, kind, api, chat_capability)
}
pub async fn run(args: HeadlessArgs) -> Result<i32> {
let scratchpad = match &args.scratchpad_state {
Some(path) => Some(seed_scratchpad(
&std::fs::read_to_string(path)
.with_context(|| format!("reading --scratchpad-state {}", path.display()))?,
)?),
None => None,
};
let cfg = match &args.profile {
Some(path) => {
resolve_profile(path)?
}
None => crate::migration_notices::read(|report| {
newt_core::Config::resolve_runtime_unpublished(report)
})
.context("resolving config")?,
};
let _non_interactive = args.non_interactive;
let ocap_env = std::env::var("NEWT_BENCH_OCAP").ok();
let unsafe_host = args.unsafe_host_exec
|| std::env::var("NEWT_UNSAFE_HOST_EXEC")
.ok()
.is_some_and(|v| {
matches!(
v.trim().to_ascii_lowercase().as_str(),
"1" | "true" | "on" | "yes"
)
});
let lane = resolve_lane(args.confined, ocap_env.as_deref(), unsafe_host);
match lane {
HeadlessLane::Confined => {
unsafe {
std::env::remove_var("NEWT_DISABLE_OCAP");
std::env::remove_var("NEWT_FULL_ACCESS");
std::env::set_var("NEWT_SHELL_ENGINE", "brush");
}
}
HeadlessLane::Yolo => {
unsafe {
std::env::set_var("NEWT_FULL_ACCESS", "1");
std::env::set_var("NEWT_DISABLE_OCAP", "1");
}
}
}
newt_core::launch_authority::freeze(newt_core::launch_authority::LaunchAuthority::from_env());
let picked = pick_backend(&cfg)?;
let backend = picked.backend;
let url = backend.endpoint.clone();
let model = backend
.effective_model()
.context("backend has no model (set model = in the [[backends]] entry)")?
.to_string();
let kind = backend.kind.unwrap_or(BackendKind::Openai);
let api_key = backend.resolve_api_key();
let api = backend.api.unwrap_or_default();
let pinned = newt_core::Config::pinned_config_path();
let card_source = args.profile.as_deref().or(pinned.as_deref());
let caps = newt_core::model_card::ResolvedCapabilities::resolve(
backend,
&picked.receipt.binding,
card_source,
)
.map_err(|e| anyhow::anyhow!(e))?;
let principal = headless_principal(backend.serving, &model);
let destination = newt_core::BackendDestination::of(backend);
let decision = caps.for_route(&destination, principal);
if let Some(notice) = newt_tui::applicability_prose(decision.applicability()) {
eprintln!("newt: {notice}");
}
let chat_capability = decision.chat_completions();
cfg.publish_runtime_settings();
newt_tui::apply_openai_api_env(api);
let runtime = resolve_runtime_posture(&cfg, caps.family_for_route(&destination, principal));
headless_contract::admit_required(&args.require_feature, |feature| match feature {
headless_contract::Feature::Scratchpad => scratchpad.is_some(),
headless_contract::Feature::Crew => runtime.crew,
headless_contract::Feature::CodeSearch => false,
})?;
let output_allowance = args
.output_allowance
.or_else(|| cfg.find_model_tuning(&model)?.output_allowance);
newt_core::agentic::validate_output_allowance(output_allowance, args.context_window)?;
let run_allowance = args
.run_allowance
.or_else(|| cfg.find_model_tuning(&model)?.run_allowance);
let tenacity_level = runtime.tenacity.label();
let initiative_level = runtime.initiative.label();
let cognition = projected_cognition(runtime.cognition, kind, api, chat_capability);
let cognition_level = cognition.map_or("default", |level| level.label());
let instruction_file = args.instruction_file.canonicalize().with_context(|| {
format!(
"resolving --instruction-file {}",
args.instruction_file.display()
)
})?;
let instruction = std::fs::read_to_string(&instruction_file)
.with_context(|| format!("reading --instruction-file {}", instruction_file.display()))?;
let workspace = args
.cwd
.canonicalize()
.unwrap_or_else(|_| args.cwd.clone())
.to_string_lossy()
.into_owned();
let _herdr = newt_tui::herdr::session_guard(&workspace);
let headless_session = newt_core::lifecycle::new_session_id();
newt_core::lifecycle::set_active_session(&headless_session);
newt_core::lifecycle::emit_for(
Some(headless_session.as_str().to_string()),
newt_core::lifecycle::LifecycleEvent::SessionStarted {
session_id: headless_session.as_str().to_string(),
},
);
let mut dc = TurnDriverConfig::new(&url, &model, kind, &workspace);
apply_context_config(&mut dc, cfg.context.as_ref());
dc.output_allowance = output_allowance;
dc.overflow_retry = cfg
.find_model_tuning(&model)
.and_then(|t| t.overflow_retry)
.unwrap_or_default();
dc.run_allowance = run_allowance;
dc.api_key = api_key;
dc.chat_completions_capability = chat_capability;
dc.responses_capability = decision.responses();
dc.openai_api = api;
dc.reasoning_replay_scope = decision.reasoning_replay_scope();
dc.emits_leading_reasoning = decision.emits_leading_reasoning();
dc.max_tool_rounds = headless_tool_round_limit(
dc.max_tool_rounds,
newt_core::tenacity::cli_tenacity(),
args.max_rounds,
);
if let Some(tui) = &cfg.tui {
dc.workflow_grace_rounds = tui.workflow_grace_rounds;
}
let smart_config = cfg.smart_harness.clone().unwrap_or_default();
let smart_enabled = args.smart_harness || smart_config.enabled;
let (ocap_store, ocap_load_warnings) = resolve_ocap_store();
for warning in &ocap_load_warnings {
eprintln!("newt: OCAP policy: {warning}");
}
let mut ocap_admitted_grants: Vec<String> = Vec::new();
if lane == HeadlessLane::Confined {
let scratch = resolve_fence_scratch(std::path::Path::new(&workspace));
if let (false, Some(root)) = (smart_enabled, scratch.first()) {
unsafe { std::env::set_var("NEWT_CHILD_TMPDIR", root) };
}
dc.caveats = confined_bench_caveats(&workspace, &scratch);
let scoped = newt_core::confined_exec::build_tool_caveats(std::path::Path::new(&workspace));
calibrate_headless_filesystem(&mut dc.caveats, &scoped, smart_enabled);
if smart_enabled {
newt_core::caveats::apply_cli_fs_grants(&mut dc.caveats, &workspace);
}
ocap_admitted_grants = fold_ocap_grants(&mut dc.caveats, &ocap_store);
}
let launch = smart_launch(&args.launch, smart_enabled, args.hermetic_explicit);
anyhow::ensure!(
smart_enabled || (args.frame_dir.is_none() && launch.continuity.parent_frame().is_none()),
"frame storage and --resume-from require --smart-harness or [smart_harness] enabled = true"
);
let harness_launch = newt_core::config::HarnessLaunch {
workspace: std::path::Path::new(&workspace),
caveats: &dc.caveats,
frame_dir: args.frame_dir.as_deref(),
resume_from: launch.continuity.parent_frame(),
hermetic: !launch.continuity.is_resumable(),
};
let smart_config = smart_enabled.then_some(smart_config).and_then(|config| {
config.admit_startup(&harness_launch, |notice| eprintln!("newt: {notice}"))
});
let mut smart_manifest = None;
let smart_harness = if let Some(smart_config) = smart_config {
let auxiliary = newt_inference::smart_harness::build(&smart_config, &url, kind)
.with_context(|| format!("smart-harness: building the auxiliary against {url}"))?;
let mut manifest = auxiliary.manifest;
manifest["primary_api"] = serde_json::json!(api.label());
let session = smart_config
.open_session(&harness_launch, manifest.clone())
.with_context(|| {
format!(
"smart-harness: opening the session (workspace {}, frame dir {})",
harness_launch.workspace.display(),
harness_launch
.frame_dir
.map(|d| d.display().to_string())
.unwrap_or_else(|| "<default>".into())
)
})?;
let session_config = serde_json::to_value(session.config())?;
smart_manifest = Some(serde_json::json!({
"invocation_mode": if launch.continuity.parent_frame().is_some() { "resume" } else { "fresh" },
"starting_cid": launch.continuity.parent_frame(),
"configuration": session_config,
}));
let harness = Arc::new(newt_core::agentic::smart_harness::SmartHarness::new(
session,
auxiliary.complete,
smart_config.adjudication.clone(),
)?);
dc.smart_harness = Some(harness.clone());
Some(harness)
} else {
None
};
if let Some(cw) = args.context_window {
apply_context_window(&mut dc, cw);
}
let max_rounds = dc.max_tool_rounds as u32;
let read_scope = dc.caveats.fs_read.clone();
let mut driver =
TurnDriver::with_transcript(dc, vec![workspace_root_system_message(&workspace)])
.with_cognition(runtime.cognition)
.with_tenacity(runtime.tenacity)
.with_initiative(runtime.initiative);
if runtime.crew {
driver = driver.with_crew_runner(Arc::new(crate::crew_runner::LocalCrewRunner::new(
newt_core::Config::clone(&cfg),
PathBuf::from(&workspace),
newt_core::agentic::Presence::Prompt,
)));
}
if let Some((store, _)) = &scratchpad {
driver = driver.with_scratchpad(store.clone());
}
let crew_level = if driver.has_crew_runner() {
"on"
} else {
"off"
};
let repo_location = newt_core::agentic::locate_workspace_repo(&workspace, &read_scope);
let status_before = matches!(
repo_location,
newt_core::agentic::WorkspaceRepoLocation::OwnRoot
)
.then(|| newt_core::agentic::snapshot_workspace(&workspace, &read_scope))
.flatten();
let subtree_before = match &repo_location {
newt_core::agentic::WorkspaceRepoLocation::InsideRepo { prefix } => {
newt_core::agentic::snapshot_workspace_subtree(&workspace, prefix, &read_scope)
}
_ => None,
};
let nested_before = (!matches!(
repo_location,
newt_core::agentic::WorkspaceRepoLocation::OwnRoot
))
.then(|| newt_core::agentic::snapshot_nested_repos(&workspace, &read_scope));
let head_before = (!matches!(
repo_location,
newt_core::agentic::WorkspaceRepoLocation::NotARepo
))
.then(|| newt_git::GitEngine::open(std::path::Path::new(&workspace), &read_scope).ok())
.flatten()
.and_then(|e| {
e.head_snapshot(&newt_core::git_caveats::GitCaveats::read_only())
.ok()
});
let started = Instant::now();
driver
.submit(instruction.trim())
.map_err(|e| anyhow::anyhow!("submit failed: {e:?}"))?;
newt_core::lifecycle::emit(newt_core::lifecycle::LifecycleEvent::TurnStarted);
let outcome = loop {
match driver.poll() {
TurnStatus::Completed(o) => break Ok(o),
TurnStatus::Failed(e) => break Err(e),
TurnStatus::Idle | TurnStatus::Running => {
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
}
}
};
match &outcome {
Ok(o) if o.error.is_none() => {
newt_core::lifecycle::emit(newt_core::lifecycle::LifecycleEvent::TurnCompleted);
}
Ok(o) => {
newt_core::lifecycle::emit(newt_core::lifecycle::LifecycleEvent::TurnFailed {
reason: o.error.clone(),
});
}
Err(e) => {
newt_core::lifecycle::emit(newt_core::lifecycle::LifecycleEvent::TurnFailed {
reason: Some(e.clone()),
});
}
}
let elapsed = started.elapsed();
let wall_secs = elapsed.as_secs_f64();
let wall_ms = u64::try_from(elapsed.as_millis()).unwrap_or(u64::MAX);
let o_opt = outcome.as_ref().ok();
let head_error = match (&mut smart_manifest, &smart_harness) {
(Some(manifest), Some(harness)) => match harness.head() {
Ok(head) => {
manifest["head"] = serde_json::json!(head.to_string());
None
}
Err(e) => Some(format!("smart-harness head unavailable: {e}")),
},
_ => None,
};
let clean = head_error.is_none() && matches!(&outcome, Ok(o) if o.error.is_none());
let terminal = headless_contract::terminal(
clean,
match &outcome {
Ok(o) => o.error_class,
Err(_) => None,
},
o_opt.and_then(|o| o.end_reason),
smart_harness.is_some(),
);
let outcome_label = headless_contract::outcome_label(terminal);
let status = headless_contract::status_label(terminal);
let error = head_error.or_else(|| match &outcome {
Ok(o) => o.error.clone(),
Err(e) => Some(e.clone()),
});
let reply_chars = o_opt.map(|o| o.reply.len()).unwrap_or(0);
let usage = o_opt.and_then(|o| o.usage.as_ref().map(|u| u.total()));
let halluc = o_opt.map(|o| o.hallucinations).unwrap_or(0);
let (tool_calls, write_calls, calls_after_last_write, end_reason, trajectory) = match o_opt {
Some(o) => {
let writes = o
.tool_events
.iter()
.filter(|e| newt_core::agentic::is_workspace_write_call(&e.tool))
.count();
(
o.tool_events.len(),
writes,
headless_contract::calls_after_last_write(&o.tool_events),
format!("{:?}", o.end_reason),
serde_json::to_value(&o.tool_events).unwrap_or(serde_json::Value::Null),
)
}
None => (0, 0, None, "None".to_string(), serde_json::Value::Null),
};
let git_caveats = newt_core::git_caveats::GitCaveats::read_only();
let repo_location = newt_core::agentic::locate_workspace_repo(&workspace, &read_scope);
let is_root_repo = matches!(
repo_location,
newt_core::agentic::WorkspaceRepoLocation::OwnRoot
);
let git_engine = (!matches!(
repo_location,
newt_core::agentic::WorkspaceRepoLocation::NotARepo
))
.then(|| newt_git::GitEngine::open(std::path::Path::new(&workspace), &read_scope).ok())
.flatten();
let uncommitted_at_exit = is_root_repo
.then(|| {
git_engine
.as_ref()
.and_then(|e| uncommitted_paths(e, &git_caveats))
})
.flatten();
let uncommitted_delta = uncommitted_repo_file_list(
uncommitted_at_exit,
&repo_location,
&nested_before,
&workspace,
&read_scope,
);
let commits_this_run = git_engine.as_ref().and_then(|engine| {
commits_since(
engine,
&git_caveats,
head_before.as_ref().and_then(|h| h.head.as_deref()),
)
});
let mut record = serde_json::json!({
"kind": "solve_result",
"task_file": instruction_file.to_string_lossy(),
"cwd": workspace,
"model": model,
"endpoint": url,
"backend_kind": kind.label(),
"status": status,
"reply_chars": reply_chars,
"usage_total_tokens": usage,
"hallucinations": halluc,
"wall_secs": wall_secs,
"tool_calls": tool_calls,
"write_calls": write_calls,
"calls_after_last_write": calls_after_last_write,
"end_reason": end_reason,
"continuity": launch.continuity.as_str(),
"continuity_note": launch.describe(),
"resume_from": launch.continuity.parent_frame(),
"trajectory": trajectory,
"error": error,
"handback": headless_contract::handback(
files_changed_delta(
&status_before,
&subtree_before,
&repo_location,
&nested_before,
&workspace,
&read_scope,
),
o_opt.map_or(&[][..], |o| &o.tool_events[..]),
&end_reason,
o_opt.is_some_and(|o| !newt_core::agentic::model_reply_for_history(&o.reply).trim().is_empty()),
uncommitted_delta,
commits_this_run.clone(),
),
});
headless_contract::conditional_stanza(&mut record, "smart_harness", smart_manifest.clone());
let attempt_lines = match (o_opt, &args.events) {
(Some(o), Some(_)) => &o.attempt_lines[..],
_ => &[],
};
let usage_stanza = o_opt.and_then(|o| o.attempts).map(|totals| {
let local = newt_core::owned_hosts::inference_is_local(
kind == newt_core::BackendKind::Embedded,
Some(&url),
);
let cost = cfg
.pricing
.clone()
.unwrap_or_default()
.estimate_attempts_cost(&model, local, &totals);
let head = attempt_lines.last().map(|line| line.id.as_str());
headless_contract::usage_stanza(&totals, cost, head)
});
headless_contract::conditional_stanza(&mut record, "usage", usage_stanza);
let mut trace_lines: Vec<serde_json::Value> = attempt_lines
.iter()
.map(headless_contract::attempt_line)
.collect();
trace_lines.push(record);
if let Some(o) = o_opt {
trace_lines.extend(
o.parse_signals
.iter()
.map(headless_contract::parse_signal_line),
);
trace_lines.extend(
o.behavior_signals
.iter()
.map(headless_contract::behavior_signal_line),
);
}
let effective_model = o_opt
.and_then(|o| o.served_model.clone())
.unwrap_or_else(|| model.clone());
let digest_env = std::env::var("NEWT_MODEL_DIGEST").ok();
let model_digest = resolve_model_digest(args.model_digest.as_deref(), digest_env.as_deref());
trace_lines.push(headless_contract::contract_record(
&headless_contract::ContractInputs {
requested_model: &model,
effective_model: &effective_model,
model_digest: model_digest.as_deref(),
backend_name: &backend.name,
backend_kind: kind.label(),
outcome: outcome_label,
context_window: args.context_window,
tenacity: tenacity_level,
initiative: initiative_level,
cognition: cognition_level,
semantic_cognition: o_opt.map(|o| o.semantic_cognition),
responses_capability: o_opt.and_then(|o| o.responses_capability.as_ref()),
reasoning_effort: o_opt.and_then(|o| o.reasoning_effort),
crew: crew_level,
ocap: if lane == HeadlessLane::Yolo {
"off"
} else {
"on"
},
max_rounds,
wall_ms,
gen_tokens: o_opt
.and_then(|o| o.usage.as_ref())
.map(|u| u64::from(u.output_tokens)),
smart_harness: smart_manifest.as_ref(),
output_allowance: o_opt.and_then(|o| o.output_allowance),
run_allowance,
features: o_opt.map(|o| o.features),
durable_grants: &ocap_admitted_grants,
verification: Some(newt_core::agentic::verification_receipt(
newt_core::agentic::verification_gate_present(kind, api, smart_manifest.is_some()),
newt_core::agentic::self_verify_enabled(),
newt_core::agentic::verify_outcomes_requested(),
)),
scratchpad_seed: scratchpad.as_ref().map(|(_, seed)| seed.as_str()),
required: &args.require_feature,
},
));
if let Some(o) = o_opt.filter(|o| !o.was_streamed && !o.reply.is_empty()) {
if o.harness_reply {
newt_core::agentic::print_harness_notice(&o.reply, false);
} else {
println!("▸ {}", o.reply);
}
}
if let Some(path) = &args.events {
let mut f = std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(path)
.with_context(|| format!("opening --events {}", path.display()))?;
for line in &trace_lines {
writeln!(f, "{line}").context("writing events line")?;
}
}
for line in &trace_lines {
println!("{line}");
}
Ok(if clean { 0 } else { 1 })
}
fn resolve_profile(path: &std::path::Path) -> Result<newt_core::ResolvedConfig> {
use anyhow::Context as _;
crate::migration_notices::read(|report| Config::load(path, report))
.with_context(|| format!("loading --profile {}", path.display()))?
.prepare_runtime()
.with_context(|| format!("preparing --profile {}", path.display()))
}
fn pick_backend(
resolved: &newt_core::ResolvedConfig,
) -> anyhow::Result<newt_core::ResolvedBackend<'_>> {
use newt_core::config::{SelectedBackend, SelectionOutcome};
match resolved.select_backend() {
SelectionOutcome::Selected(SelectedBackend::Configured(backend)) => {
if backend.endpoint.is_empty() || backend.kind == Some(BackendKind::Embedded) {
anyhow::bail!(
"backend `{}` is an embedded (model_path) backend — `newt headless` \
drives HTTP backends only; select an HTTP backend, or give this \
one an endpoint",
backend.name
);
}
Ok(resolved
.selected_backend()
.expect("the shared index selector just picked a configured backend"))
}
SelectionOutcome::Selected(SelectedBackend::Provider(p)) => anyhow::bail!(
"the backend selection resolves to provider `{}` — `newt headless` drives \
configured [[backends]] only; point $NEWT_PROVIDER/default_backend at a \
backend (or unset them)",
p.name
),
SelectionOutcome::UnknownNamed(name) => anyhow::bail!(
"$NEWT_PROVIDER/default_backend names `{name}`, which matches nothing \
configured — fix the selector (headless will not silently run another backend)"
),
SelectionOutcome::UnroutableNamed(name) => anyhow::bail!(
"$NEWT_PROVIDER/default_backend names `{name}`, which has neither an \
endpoint nor a model_path — give it a destination (headless will not \
silently run another backend)"
),
SelectionOutcome::Unset => anyhow::bail!(
"no usable backend in config (set one in the --profile [[backends]] or via \
--backend-endpoint)"
),
}
}
fn confined_bench_caveats(workspace: &str, scratch: &[String]) -> Caveats {
let extra: Vec<String> = std::env::var_os("NEWT_WRITE_PATHS")
.map(|v| {
std::env::split_paths(&v)
.filter(|p| !p.as_os_str().is_empty())
.map(|p| p.to_string_lossy().into_owned())
.collect()
})
.unwrap_or_default();
confined_bench_caveats_with_grants(workspace, scratch, &extra)
}
fn calibrate_headless_filesystem(baseline: &mut Caveats, build: &Caveats, smart: bool) {
for (scope, requested) in [
(&mut baseline.fs_read, &build.fs_read),
(&mut baseline.fs_write, &build.fs_write),
] {
let covered = headless_fs_intersection(scope, requested);
if smart {
*scope = covered;
} else if let (Scope::Only(roots), Scope::Only(covered)) = (scope, covered) {
roots.extend(covered);
}
}
}
fn headless_fs_intersection(left: &Scope<String>, right: &Scope<String>) -> Scope<String> {
use newt_core::caveats::permits_path;
let (Scope::Only(left), Scope::Only(right)) = (left, right) else {
return if matches!(left, Scope::All) {
right.clone()
} else {
left.clone()
};
};
let mut covered = std::collections::BTreeSet::new();
for (candidates, allowed) in [(left, right), (right, left)] {
let physical = Scope::only(
allowed
.iter()
.filter_map(|path| resolve_headless_grant(path)),
);
covered.extend(
candidates
.iter()
.filter(|path| {
resolve_headless_grant(path).is_some_and(|path| permits_path(&physical, &path))
})
.cloned(),
);
}
Scope::Only(covered)
}
fn resolve_headless_grant(path: &str) -> Option<String> {
let path = std::path::Path::new(path);
if !path.is_absolute() {
return None;
}
for ancestor in path.ancestors() {
match std::fs::symlink_metadata(ancestor) {
Ok(_) => {
let suffix = path.strip_prefix(ancestor).ok()?;
if suffix
.components()
.any(|c| matches!(c, std::path::Component::ParentDir))
{
return None;
}
return Some(
ancestor
.canonicalize()
.ok()?
.join(suffix)
.to_string_lossy()
.into_owned(),
);
}
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
Err(_) => return None,
}
}
None
}
fn resolve_fence_scratch(workspace: &std::path::Path) -> Vec<String> {
let managed = newt_core::scratch::build_scratch_override()
.is_none()
.then(|| newt_core::confined_exec::build_scratch_root(workspace));
fence_scratch_roots(
&newt_core::scratch::scratch_dir(),
&std::env::temp_dir(),
managed.as_deref(),
)
}
fn fence_scratch_roots(
scratch_dir: &str,
temp_dir: &std::path::Path,
managed_build: Option<&std::path::Path>,
) -> Vec<String> {
if std::path::Path::new(scratch_dir).is_absolute() {
vec![scratch_dir.to_string()]
} else {
let mut roots = vec![temp_dir.to_string_lossy().into_owned()];
roots.extend(managed_build.map(|path| path.to_string_lossy().into_owned()));
roots
}
}
fn fold_ocap_grants(
caveats: &mut Caveats,
store: &newt_core::ocap_store::PolicySet,
) -> Vec<String> {
let is_high_danger = newt_tui::ocap_high_danger_predicate();
let grants: Vec<_> = newt_core::ocap_store::approved_grants(store)
.into_iter()
.filter(|(kind, target)| !is_high_danger(denial_kind_to_capability_class(*kind), target))
.collect();
if grants.is_empty() {
return Vec::new();
}
let already_permitted: Vec<_> = grants
.iter()
.map(|(kind, target)| grant_already_permitted(caveats, *kind, target))
.collect();
*caveats = newt_core::widen_caveats(caveats, &grants);
grants
.into_iter()
.zip(already_permitted)
.map(|((kind, target), no_op)| {
let label = format!("{}:{target}", ocap_grant_axis_label(kind));
if no_op {
format!("{label} (no-op: already permitted)")
} else {
label
}
})
.collect()
}
fn grant_already_permitted(caveats: &Caveats, kind: newt_core::DenialKind, target: &str) -> bool {
use newt_core::caveats::CaveatsExt;
match kind {
newt_core::DenialKind::FsRead => caveats.permits_fs_read(target),
newt_core::DenialKind::FsWrite => caveats.permits_fs_write(target),
newt_core::DenialKind::Exec => caveats.permits_exec(target),
newt_core::DenialKind::Net => caveats.permits_net(target),
_ => false,
}
}
fn denial_kind_to_capability_class(
kind: newt_core::DenialKind,
) -> newt_core::ocap_store::CapabilityClass {
match kind {
newt_core::DenialKind::Exec => newt_core::ocap_store::CapabilityClass::Exec,
newt_core::DenialKind::Net => newt_core::ocap_store::CapabilityClass::Net,
_ => newt_core::ocap_store::CapabilityClass::Fs,
}
}
fn ocap_grant_axis_label(kind: newt_core::DenialKind) -> &'static str {
match kind {
newt_core::DenialKind::Exec => "exec",
newt_core::DenialKind::FsRead => "fs_read",
newt_core::DenialKind::FsWrite => "fs_write",
newt_core::DenialKind::Net => "net",
newt_core::DenialKind::RemoteTool => "remote_tool",
newt_core::DenialKind::GitWrite => "git_write",
newt_core::DenialKind::Build => "build",
}
}
fn resolve_ocap_store() -> (newt_core::ocap_store::PolicySet, Vec<String>) {
let Some(config_path) = newt_core::Config::user_config_path() else {
return (newt_core::ocap_store::PolicySet::default(), Vec::new());
};
let root_vk = newt_identity::default_key_path()
.ok()
.and_then(|p| newt_identity::load_user_key(&p).ok())
.map(|user| user.public().as_bytes());
newt_core::ocap_store::load_store(&config_path, root_vk)
}
fn confined_bench_caveats_with_grants(
workspace: &str,
scratch_roots: &[String],
extra_write_roots: &[String],
) -> Caveats {
let mut write_roots: Vec<String> = vec![workspace.to_string()];
write_roots.extend(scratch_roots.iter().cloned());
write_roots.extend(extra_write_roots.iter().cloned());
Caveats {
fs_read: Scope::All,
fs_write: Scope::only(write_roots),
exec: Scope::All,
net: Scope::All,
max_calls: CountBound::Unlimited,
valid_for_generation: Scope::All,
}
}
struct NestedByRepo {
files: Vec<String>,
by_repo: Vec<(String, Vec<String>)>,
unprobed: Vec<String>,
}
fn nested_delta_by_repo(
before: &[newt_core::agentic::NestedRepoSnapshot],
after: &[newt_core::agentic::NestedRepoSnapshot],
) -> NestedByRepo {
let (files, unprobed) = newt_core::agentic::nested_files_changed_between(before, after);
let by_repo = after
.iter()
.map(|repo| {
let before_status = before
.iter()
.find(|b| b.repo == repo.repo)
.and_then(|b| b.status.as_ref());
let files = match (before_status, repo.status.as_ref()) {
(Some(b), Some(a)) => newt_core::agentic::files_changed_between(b, a),
_ => Vec::new(),
};
(repo.repo.clone(), files)
})
.collect();
NestedByRepo {
files,
by_repo,
unprobed,
}
}
fn nested_current_by_repo(snapshots: &[newt_core::agentic::NestedRepoSnapshot]) -> NestedByRepo {
let (files, unprobed) = newt_core::agentic::nested_current_paths(snapshots);
let by_repo = snapshots
.iter()
.map(|repo| {
let files = repo
.status
.as_ref()
.map(|s| s.keys().cloned().collect())
.unwrap_or_default();
(repo.repo.clone(), files)
})
.collect();
NestedByRepo {
files,
by_repo,
unprobed,
}
}
fn files_changed_delta(
status_before: &Option<newt_core::agentic::StatusSnapshot>,
subtree_before: &Option<newt_core::agentic::StatusSnapshot>,
repo_location: &newt_core::agentic::WorkspaceRepoLocation,
nested_before: &Option<Vec<newt_core::agentic::NestedRepoSnapshot>>,
workspace: &str,
read_scope: &newt_core::Scope<String>,
) -> Option<headless_contract::RepoFileList> {
if let Some(before) = status_before {
let after = newt_core::agentic::snapshot_workspace(workspace, read_scope)?;
return Some(headless_contract::RepoFileList::Root(
newt_core::agentic::files_changed_between(before, &after),
));
}
if let newt_core::agentic::WorkspaceRepoLocation::InsideRepo { prefix } = repo_location {
let before = subtree_before.as_ref()?;
let after = newt_core::agentic::snapshot_workspace_subtree(workspace, prefix, read_scope)?;
let mut files = newt_core::agentic::files_changed_between(before, &after);
let (by_repo, unprobed) = match nested_before.as_ref() {
Some(nb) if !nb.is_empty() => {
let after_nested = newt_core::agentic::snapshot_nested_repos(workspace, read_scope);
let nested = nested_delta_by_repo(nb, &after_nested);
files.extend(nested.files);
(nested.by_repo, nested.unprobed)
}
_ => (Vec::new(), Vec::new()),
};
files.sort();
return Some(headless_contract::RepoFileList::Subtree {
files,
by_repo,
unprobed,
});
}
let before = nested_before.as_ref()?;
if before.is_empty() {
return None;
}
let after = newt_core::agentic::snapshot_nested_repos(workspace, read_scope);
let nested = nested_delta_by_repo(before, &after);
Some(headless_contract::RepoFileList::Nested {
files: nested.files,
by_repo: nested.by_repo,
unprobed: nested.unprobed,
})
}
fn uncommitted_repo_file_list(
uncommitted_at_exit: Option<Vec<String>>,
repo_location: &newt_core::agentic::WorkspaceRepoLocation,
nested_before: &Option<Vec<newt_core::agentic::NestedRepoSnapshot>>,
workspace: &str,
read_scope: &newt_core::Scope<String>,
) -> Option<headless_contract::RepoFileList> {
match repo_location {
newt_core::agentic::WorkspaceRepoLocation::OwnRoot => {
uncommitted_at_exit.map(headless_contract::RepoFileList::Root)
}
newt_core::agentic::WorkspaceRepoLocation::InsideRepo { prefix } => {
let subtree =
newt_core::agentic::snapshot_workspace_subtree(workspace, prefix, read_scope)?;
let mut files: Vec<String> = subtree.into_keys().collect();
let (by_repo, unprobed) = match nested_before.as_ref() {
Some(nb) if !nb.is_empty() => {
let snapshots =
newt_core::agentic::snapshot_nested_repos(workspace, read_scope);
let nested = nested_current_by_repo(&snapshots);
files.extend(nested.files);
(nested.by_repo, nested.unprobed)
}
_ => (Vec::new(), Vec::new()),
};
files.sort();
Some(headless_contract::RepoFileList::Subtree {
files,
by_repo,
unprobed,
})
}
newt_core::agentic::WorkspaceRepoLocation::NotARepo => {
let before = nested_before.as_ref()?;
if before.is_empty() {
return None;
}
let snapshots = newt_core::agentic::snapshot_nested_repos(workspace, read_scope);
let nested = nested_current_by_repo(&snapshots);
Some(headless_contract::RepoFileList::Nested {
files: nested.files,
by_repo: nested.by_repo,
unprobed: nested.unprobed,
})
}
}
}
fn uncommitted_paths(
engine: &newt_git::GitEngine,
caveats: &newt_core::git_caveats::GitCaveats,
) -> Option<Vec<String>> {
let s = engine.status(caveats).ok()?;
let mut paths: Vec<String> = s
.staged
.iter()
.chain(s.unstaged.iter())
.map(|f| f.path.clone())
.chain(s.untracked)
.collect();
paths.sort();
paths.dedup();
Some(paths)
}
fn commits_since(
engine: &newt_git::GitEngine,
caveats: &newt_core::git_caveats::GitCaveats,
before_oid: Option<&str>,
) -> Option<Vec<String>> {
let before_oid = before_oid?;
let after_oid = engine.head_snapshot(caveats).ok()?.head?;
if after_oid == before_oid {
return Some(Vec::new());
}
engine
.log(
caveats,
headless_contract::HANDBACK_MAX_FILES,
Some(&format!("{before_oid}..{after_oid}")),
&[],
)
.ok()
.map(|commits| commits.into_iter().map(|c| c.id).collect())
}
#[cfg(test)]
mod tests {
use super::*;
use newt_core::config::BackendConfig;
#[cfg(unix)]
use newt_core::ScopeExt as _;
#[test]
fn commits_since_names_a_commit_made_from_a_repo_subdirectory() {
let repo = tempfile::tempdir().expect("repo root");
let git = |dir: &std::path::Path, args: &[&str]| {
assert!(std::process::Command::new("git")
.args(args)
.current_dir(dir)
.output()
.expect("git")
.status
.success());
};
git(repo.path(), &["init", "-q"]);
git(repo.path(), &["config", "user.email", "t@example.com"]);
git(repo.path(), &["config", "user.name", "t"]);
let crate_dir = repo.path().join("crate");
std::fs::create_dir_all(&crate_dir).unwrap();
std::fs::write(crate_dir.join("lib.rs"), "one\n").unwrap();
git(repo.path(), &["add", "-A"]);
git(repo.path(), &["commit", "-q", "-m", "init"]);
let read_scope = newt_core::Scope::All;
let crate_str = crate_dir.to_string_lossy().into_owned();
assert!(
matches!(
newt_core::agentic::locate_workspace_repo(&crate_str, &read_scope),
newt_core::agentic::WorkspaceRepoLocation::InsideRepo { .. }
),
"crate/ must resolve as a SUBDIRECTORY of the enclosing repo"
);
let engine = newt_git::GitEngine::open(&crate_dir, &read_scope)
.expect("the engine must open for a repo subdirectory too (#2552 blocker 1)");
let caveats = newt_core::git_caveats::GitCaveats::read_only();
let before = engine
.head_snapshot(&caveats)
.expect("head_snapshot must succeed");
std::fs::write(crate_dir.join("lib.rs"), "one\ntwo\n").unwrap();
git(&crate_dir, &["add", "-A"]);
git(&crate_dir, &["commit", "-q", "-m", "during the run"]);
let after_head = git_rev_parse_head(repo.path());
let commits = commits_since(&engine, &caveats, before.head.as_deref())
.expect("commits_since must resolve, not unavailable");
assert_eq!(
commits,
vec![after_head],
"the commit made from crate/ must be named"
);
}
#[cfg(test)]
fn git_rev_parse_head(dir: &std::path::Path) -> String {
let out = std::process::Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(dir)
.output()
.expect("git rev-parse HEAD");
String::from_utf8_lossy(&out.stdout).trim().to_string()
}
#[test]
fn a_scratchpad_seed_is_identified_by_its_entries_and_validated() {
use newt_core::ScratchpadStore;
let (store, seed) = seed_scratchpad(r#"{"b": "2", "a": "1"}"#).unwrap();
assert_eq!(store.get("a").as_deref(), Some("1"));
let (_, respelled) = seed_scratchpad("{\"a\":\"1\",\n \"b\":\"2\"}").unwrap();
assert_eq!(seed, respelled, "same entries, same seed");
let (_, other) = seed_scratchpad(r#"{"a": "1"}"#).unwrap();
assert_ne!(seed, other, "different entries, different seed");
assert!(seed_scratchpad(r#"{"a": 1}"#).is_err(), "non-string value");
assert!(seed_scratchpad(r#"["a"]"#).is_err(), "not an object");
assert!(seed_scratchpad(r#"{" ": "v"}"#).is_err(), "blank key");
}
#[test]
fn workspace_root_system_message_names_the_real_root() {
let msg = workspace_root_system_message("/home/dev/proj");
assert_eq!(msg.role, newt_core::memory::Role::System);
assert!(
msg.content.contains("/home/dev/proj"),
"message must name the real workspace root, got: {}",
msg.content
);
}
#[test]
fn smart_runs_are_resumable_unless_hermetic_was_explicit() {
let legacy = newt_launch::LaunchConfig::default();
assert!(!smart_launch(&legacy, false, false)
.continuity
.is_resumable());
assert!(smart_launch(&legacy, true, false).continuity.is_resumable());
assert!(!smart_launch(&legacy, true, true).continuity.is_resumable());
let resume = newt_launch::LaunchConfig {
continuity: newt_launch::Continuity::Resume {
from: Some("head".into()),
},
};
assert_eq!(
smart_launch(&resume, true, false).continuity.parent_frame(),
Some("head")
);
}
fn backend(name: &str, endpoint: &str) -> BackendConfig {
BackendConfig {
name: name.into(),
endpoint: endpoint.into(),
..Default::default()
}
}
#[test]
fn headless_principal_parity_for_unset_serving() {
use newt_core::model_card::{
CardApplicability, CardBindingSeed, ResolvedCapabilities, ServingPrincipal,
};
assert!(matches!(
headless_principal(None, "bound-model"),
ServingPrincipal::SelectedModel("bound-model")
));
assert!(matches!(
headless_principal(Some(newt_core::Serving::Instance), "m"),
ServingPrincipal::Instance
));
let dir = tempfile::tempdir().expect("tempdir");
let profile = dir.path().join("profile.toml");
std::fs::write(&profile, "# profile\n").expect("write profile");
std::fs::create_dir_all(dir.path().join("models")).expect("models dir");
std::fs::write(
dir.path().join("models/team.toml"),
"name = \"team\"\nbackend = \"vllm\"\nfamily = \"nemotron\"\n\n[vllm]\nserved_name = \"team\"\n\n[capability]\nemits_leading_reasoning = true\n",
)
.expect("write card");
let b = newt_core::BackendConfig {
name: "carded".into(),
endpoint: "http://local:8000".into(),
model: Some("bound-model".into()),
card: Some("team".into()),
..Default::default()
};
let seed = CardBindingSeed {
card: b.card.clone(),
bound_model: b.model.clone(),
bound_destination: newt_core::BackendDestination::of(&b),
};
let caps = ResolvedCapabilities::resolve(&b, &seed, Some(&profile)).expect("resolves");
let destination = newt_core::BackendDestination::of(&b);
let d = caps.for_route(&destination, headless_principal(None, "bound-model"));
assert!(d.emits_leading_reasoning(), "exact association activates");
assert_eq!(
caps.family_for_route(&destination, headless_principal(None, "bound-model")),
Some("nemotron")
);
let d = caps.for_route(&destination, headless_principal(None, "other-model"));
assert!(!d.emits_leading_reasoning(), "no false activation");
assert!(matches!(
d.applicability(),
CardApplicability::InactiveModel { .. }
));
assert_eq!(
caps.family_for_route(&destination, headless_principal(None, "other-model")),
None,
"no family on a retargeted principal"
);
}
#[test]
fn pick_backend_skips_endpointless_and_takes_the_first_usable() {
let _g = newt_core::test_guard::GlobalSettingsGuard::acquire();
unsafe { std::env::remove_var("NEWT_PROVIDER") };
let cfg = Config {
backends: vec![
backend("embedded-no-endpoint", ""),
backend("dgx", "http://router:8080"),
backend("other", "http://other:9000"),
],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let chosen = pick_backend(&cfg).expect("a usable backend exists");
assert_eq!(
chosen.backend.name, "dgx",
"skip the endpointless one, take the first usable"
);
}
#[test]
fn pick_backend_errors_when_no_endpoints() {
let _g = newt_core::test_guard::GlobalSettingsGuard::acquire();
unsafe { std::env::remove_var("NEWT_PROVIDER") };
let cfg = Config {
backends: vec![backend("a", ""), backend("b", "")],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let err = pick_backend(&cfg).expect_err("nothing routable");
assert!(err.to_string().contains("no usable backend"), "{err}");
}
#[test]
fn resolve_model_digest_flag_beats_env_and_never_invents() {
assert_eq!(
resolve_model_digest(Some("sha-flag"), Some("sha-env")).as_deref(),
Some("sha-flag")
);
assert_eq!(
resolve_model_digest(None, Some(" sha-env ")).as_deref(),
Some("sha-env"),
"env twin used when no flag; whitespace trimmed"
);
assert_eq!(
resolve_model_digest(Some(" "), Some("sha-env")).as_deref(),
Some("sha-env"),
"a blank flag falls through to the env twin"
);
assert_eq!(resolve_model_digest(None, None), None);
assert_eq!(resolve_model_digest(Some(""), Some("")), None);
}
#[test]
fn pick_backend_honors_default_backend_over_first_endpoint() {
let _g = newt_core::test_guard::GlobalSettingsGuard::acquire();
unsafe { std::env::remove_var("NEWT_PROVIDER") };
let cfg = Config {
default_backend: Some("sol".to_string()),
backends: vec![
backend("other", "https://other:9000"), backend("sol", "https://api.openai.com"),
],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
assert_eq!(
pick_backend(&cfg).expect("a backend").backend.name,
"sol",
"default_backend wins over the first endpoint-bearing entry"
);
}
#[test]
fn pick_backend_default_backend_unroutable_is_a_hard_error_not_a_fallback() {
let _g = newt_core::test_guard::GlobalSettingsGuard::acquire();
unsafe { std::env::remove_var("NEWT_PROVIDER") };
let cfg = Config {
default_backend: Some("ghost".to_string()),
backends: vec![backend("ghost", ""), backend("real", "http://r:1")],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let err = pick_backend(&cfg).expect_err("no silent fallback to `real`");
assert!(
err.to_string().contains("ghost") && err.to_string().contains("destination"),
"{err}"
);
}
#[test]
fn pick_backend_unknown_env_name_is_a_hard_error_not_a_fallback() {
let _g = newt_core::test_guard::GlobalSettingsGuard::acquire();
unsafe { std::env::set_var("NEWT_PROVIDER", "no-such-backend") };
let cfg = Config {
backends: vec![backend("real", "http://r:1")],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let err = pick_backend(&cfg).expect_err("no silent fallback to `real`");
assert!(err.to_string().contains("no-such-backend"), "{err}");
}
#[test]
fn pick_backend_provider_named_env_is_a_hard_error_not_a_fallback() {
let _g = newt_core::test_guard::GlobalSettingsGuard::acquire();
unsafe { std::env::set_var("NEWT_PROVIDER", "acme") };
let cfg = Config {
backends: vec![backend("real", "http://r:1")],
providers: vec![newt_core::config::ProviderConfig {
name: "acme".into(),
command: "newt-provider-openai".into(),
model: None,
env_pass: vec![],
tiers: vec![],
}],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let err = pick_backend(&cfg).expect_err("headless cannot drive a provider");
assert!(err.to_string().contains("provider `acme`"), "{err}");
}
#[test]
fn pick_backend_rejects_embedded_model_path_backends() {
let _g = newt_core::test_guard::GlobalSettingsGuard::acquire();
let embedded = || newt_core::BackendConfig {
name: "emb".into(),
model_path: Some("/models/x.gguf".into()),
kind: Some(newt_core::BackendKind::Embedded),
..Default::default()
};
unsafe { std::env::remove_var("NEWT_PROVIDER") };
let cfg = Config {
backends: vec![embedded()],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let err = pick_backend(&cfg).expect_err("sole embedded refused");
assert!(err.to_string().contains("HTTP backends only"), "{err}");
let cfg = Config {
backends: vec![backend("http", "http://h:1"), embedded()],
default_backend: Some("emb".into()),
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let err = pick_backend(&cfg).expect_err("default-named embedded refused");
assert!(err.to_string().contains("emb"), "{err}");
unsafe { std::env::set_var("NEWT_PROVIDER", "emb") };
let cfg = Config {
backends: vec![backend("http", "http://h:1"), embedded()],
..Default::default()
};
let cfg = newt_core::ResolvedConfig::unrequested(cfg);
let err = pick_backend(&cfg).expect_err("env-named embedded refused");
assert!(err.to_string().contains("emb"), "{err}");
}
#[test]
fn a_profile_with_invalid_backend_identity_is_a_hard_error() {
let dir = tempfile::tempdir().expect("tempdir");
let dup = dir.path().join("dup.toml");
std::fs::write(
&dup,
"[[backends]]\nname = \"twin\"\nendpoint = \"http://a:1\"\n\n\
[[backends]]\nname = \"twin\"\nendpoint = \"http://b:2\"\n",
)
.expect("write profile");
let err = resolve_profile(&dup).expect_err("duplicate names refuse");
assert!(format!("{err:#}").contains("twin"), "{err:#}");
let empty = dir.path().join("empty.toml");
std::fs::write(
&empty,
"[[backends]]\nname = \"\"\nendpoint = \"http://a:1\"\n",
)
.expect("write profile");
let err = resolve_profile(&empty).expect_err("empty names refuse");
assert!(format!("{err:#}").contains("no name"), "{err:#}");
let ok = dir.path().join("ok.toml");
std::fs::write(
&ok,
"[[backends]]\nname = \"a\"\nendpoint = \"http://a:1\"\n",
)
.expect("write profile");
let resolved = resolve_profile(&ok).expect("valid profile");
assert_eq!(resolved.receipts().len(), 1);
}
#[test]
fn headless_solve_applies_context_config_to_turn_driver() {
let mut driver = TurnDriverConfig::new(
"http://example.invalid",
"model",
BackendKind::Openai,
"/workspace",
);
let context = newt_core::ContextConfig {
estimation: newt_core::tokens::TokenEstimation::new(3),
summary_input_cap_floor_chars: 4_096,
input_ceiling_pct: 70,
low_budget_pct: 20,
compaction_trigger_policy: newt_core::CompactionTriggerPolicy::MessageCount,
..Default::default()
};
apply_context_config(&mut driver, Some(&context));
assert_eq!(driver.estimation.chars_per_token, 3);
assert_eq!(driver.summary_input_cap_floor_chars, 4_096);
assert_eq!(driver.input_ceiling_pct, 70);
assert_eq!(driver.low_budget_pct, 20);
assert_eq!(
driver.compaction_trigger_policy,
newt_core::CompactionTriggerPolicy::MessageCount
);
}
#[test]
fn context_window_uses_configured_input_ceiling() {
let mut driver = TurnDriverConfig::new(
"http://example.invalid",
"model",
BackendKind::Openai,
"/workspace",
);
driver.input_ceiling_pct = 83;
apply_context_window(&mut driver, 65_536);
assert_eq!(driver.num_ctx, Some(65_536));
assert_eq!(driver.safe_context, Some(54_394));
assert_eq!(driver.max_ok_input, Some(54_394));
}
#[test]
fn contract_dials_record_the_effective_cli_overrides() {
let _guard = newt_core::test_guard::GlobalSettingsGuard::acquire();
newt_core::initiative::set_initiative_config(Default::default());
newt_core::initiative::set_cli_initiative(newt_core::Initiative::Decisive);
newt_core::tenacity::set_cli_tenacity(newt_core::Tenacity::Relentless);
let runtime = resolve_runtime_posture(&Config::default(), None);
assert_eq!(runtime.initiative, newt_core::Initiative::Decisive);
assert_eq!(runtime.tenacity, newt_core::Tenacity::Relentless);
}
#[test]
fn explicit_relentless_tenacity_expands_solve_unless_max_rounds_wins() {
use newt_core::tenacity::RELENTLESS_TOOL_ROUND_TARGET;
use newt_core::Tenacity;
assert_eq!(
headless_tool_round_limit(40, Some(Tenacity::Relentless), None),
RELENTLESS_TOOL_ROUND_TARGET
);
assert_eq!(
headless_tool_round_limit(40, Some(Tenacity::Relentless), Some(2)),
2
);
assert_eq!(
headless_tool_round_limit(40, None, None),
40,
"automatic family tenacity must not silently expand the safety cap"
);
}
#[test]
fn contract_cognition_is_the_level_the_backend_can_receive() {
let level = Some(Cognition::Meticulous);
let capable = ChatCompletionsCapability {
cognition: Some(true),
..Default::default()
};
assert_eq!(
projected_cognition(
level,
BackendKind::Openai,
OpenAiApi::Responses,
Default::default()
),
level,
"Responses always has a cognition projection"
);
assert_eq!(
projected_cognition(
level,
BackendKind::Openai,
OpenAiApi::ChatCompletions,
capable,
),
level,
"an explicitly capable Chat endpoint receives the local policy"
);
assert_eq!(
projected_cognition(
level,
BackendKind::Openai,
OpenAiApi::ChatCompletions,
Default::default(),
),
None,
"an unknown Chat endpoint receives no cognition fields"
);
assert_eq!(
projected_cognition(level, BackendKind::Ollama, OpenAiApi::Responses, capable,),
None,
"the Ollama wire has no cognition projection"
);
}
#[test]
fn resolve_lane_precedence_and_trim() {
use HeadlessLane::*;
assert_eq!(resolve_lane(true, None, true), Confined);
assert_eq!(resolve_lane(true, Some("off"), false), Confined);
assert_eq!(resolve_lane(false, Some("on"), true), Confined);
assert_eq!(resolve_lane(false, Some(" ON "), true), Confined);
assert_eq!(resolve_lane(false, Some("On"), false), Confined);
assert_eq!(resolve_lane(false, Some("1"), true), Yolo);
assert_eq!(resolve_lane(false, None, true), Yolo);
assert_eq!(resolve_lane(false, Some("1"), false), Confined);
assert_eq!(resolve_lane(false, Some("true"), false), Confined);
}
#[test]
fn non_interactive_never_relaxes_authority() {
assert_eq!(resolve_lane(false, None, false), HeadlessLane::Confined);
assert_eq!(
resolve_lane(false, Some("off"), false),
HeadlessLane::Confined
);
assert_eq!(resolve_lane(false, None, true), HeadlessLane::Yolo);
}
use newt_core::caveats::CaveatsExt;
#[test]
fn confined_caveats_fence_writes_never_all() {
let cv =
confined_bench_caveats_with_grants("/app/task", &["/srv/scratch".to_string()], &[]);
assert!(
!matches!(cv.fs_write, Scope::All),
"confined lane must NEVER grant fs_write = Scope::All"
);
assert!(
matches!(cv.fs_write, Scope::Only(_)),
"confined fs_write must be an explicit Scope::Only fence"
);
assert!(matches!(cv.fs_read, Scope::All), "reads stay open");
assert!(matches!(cv.exec, Scope::All), "exec stays open");
assert!(matches!(cv.net, Scope::All), "net stays open");
}
#[test]
fn confined_caveats_permit_workspace_and_scratch_writes() {
let cv =
confined_bench_caveats_with_grants("/app/task", &["/srv/scratch".to_string()], &[]);
assert!(cv.permits_fs_write("/app/task"), "workspace root writable");
assert!(
cv.permits_fs_write("/srv/scratch"),
"configured scratch writable"
);
assert!(
!cv.permits_fs_write("/tmp"),
"/tmp is no longer a built-in root"
);
assert!(!cv.permits_fs_write("/usr"), "system roots are opt-in");
assert!(
!cv.permits_fs_write("/boot/vmlinuz"),
"a path outside every granted root fails closed"
);
}
#[test]
fn confined_fence_excludes_home_and_system_roots_by_default() {
use newt_core::caveats::permits_path;
let cv =
confined_bench_caveats_with_grants("/app/task", &["/srv/scratch".to_string()], &[]);
for p in [
"/home/u/.rustup/settings.toml",
"/home/u/.ssh/id",
"/root/x",
"/usr/bin/x",
"/etc/passwd",
] {
assert!(!permits_path(&cv.fs_write, p), "{p} must not be writable");
}
for p in ["/app/task/src/x", "/srv/scratch/x"] {
assert!(permits_path(&cv.fs_write, p), "{p} must be writable");
}
}
#[test]
fn confined_fence_broad_roots_are_opt_in_by_grant() {
use newt_core::caveats::permits_path;
let grants = ["/data/scratch".to_string(), "/home".to_string()];
let cv =
confined_bench_caveats_with_grants("/app/task", &["/srv/scratch".to_string()], &grants);
assert!(permits_path(&cv.fs_write, "/data/scratch/f"));
assert!(permits_path(&cv.fs_write, "/home/u/x"));
}
#[test]
fn smart_fence_is_within_the_default_fence() {
use newt_core::caveats::permits_path;
let default =
confined_bench_caveats_with_grants("/app/task", &["/srv/scratch".to_string()], &[]);
let build = newt_core::confined_exec::build_tool_caveats("/app/task".as_ref());
let mut smart = default.clone();
calibrate_headless_filesystem(&mut smart, &build, true);
let Scope::Only(roots) = &smart.fs_write else {
panic!("smart fs_write must be an explicit Scope::Only");
};
for root in roots {
assert!(
permits_path(&default.fs_write, root),
"{root} outside default"
);
}
}
#[test]
fn headless_build_projection_admits_only_covered_paths_in_both_modes() {
use newt_core::caveats::permits_path;
let fixture = tempfile::tempdir().unwrap();
let root = fixture.path().canonicalize().unwrap();
let workspace = root.join("workspace").to_string_lossy().into_owned();
let scratch = root.join("scratch").to_string_lossy().into_owned();
let partition = root
.join("scratch/build/workspace")
.to_string_lossy()
.into_owned();
let build = Caveats {
fs_read: Scope::only([workspace.clone(), partition.clone()]),
fs_write: Scope::only([workspace.clone(), partition]),
..Caveats::top()
};
for smart in [false, true] {
let default =
confined_bench_caveats_with_grants(&workspace, std::slice::from_ref(&scratch), &[]);
let mut session = default.clone();
calibrate_headless_filesystem(&mut session, &build, smart);
assert!(
build.leq(&session),
"already-granted build paths need exact declarations for admission: smart={smart}"
);
let Scope::Only(roots) = &session.fs_write else {
panic!("writes must remain fenced");
};
assert!(roots
.iter()
.all(|root| permits_path(&default.fs_write, root)));
assert!(!permits_path(
&session.fs_write,
&root.join("outside").to_string_lossy()
));
}
}
#[test]
fn headless_build_projection_admits_the_covered_managed_partition() {
let fixture = tempfile::tempdir().unwrap();
let workspace = fixture.path().canonicalize().unwrap();
let scratch = newt_core::confined_exec::build_scratch_dir(&workspace);
let scratch_parent = scratch.parent().unwrap().parent().unwrap();
let baseline = confined_bench_caveats_with_grants(
&workspace.to_string_lossy(),
&[scratch_parent.to_string_lossy().into_owned()],
&[],
);
let request = newt_core::confined_exec::build_tool_request(
&workspace,
&workspace,
"cargo",
["check"],
&baseline.net,
);
for smart in [false, true] {
let mut session = baseline.clone();
calibrate_headless_filesystem(&mut session, request.caveats(), smart);
assert!(
request.caveats().leq(&session),
"covered build: smart={smart}"
);
}
assert!(
!scratch.parent().unwrap().exists(),
"admission must not allocate scratch"
);
}
#[test]
fn default_scratch_policy_admits_only_its_managed_build_partition() {
use newt_core::caveats::permits_path;
let fixture = tempfile::tempdir().unwrap();
let root = fixture.path().canonicalize().unwrap();
let workspace = root.join("workspace");
let ordinary_temp = root.join("ordinary-temp");
let partition = root.join("managed-build/workspace");
let configured = root.join("configured-scratch");
let build = Caveats {
fs_read: Scope::only([
workspace.to_string_lossy().into_owned(),
partition.to_string_lossy().into_owned(),
]),
fs_write: Scope::only([
workspace.to_string_lossy().into_owned(),
partition.to_string_lossy().into_owned(),
]),
..Caveats::top()
};
let roots = fence_scratch_roots(".scratch", &ordinary_temp, Some(&partition));
assert_eq!(roots[0], ordinary_temp.to_string_lossy());
assert_eq!(roots.len(), 2);
let baseline =
confined_bench_caveats_with_grants(&workspace.to_string_lossy(), &roots, &[]);
for smart in [false, true] {
let mut session = baseline.clone();
calibrate_headless_filesystem(&mut session, &build, smart);
assert!(build.leq(&session), "default Build: smart={smart}");
for denied in [
partition.parent().unwrap().to_path_buf(),
partition.with_file_name("other-workspace"),
] {
assert!(!permits_path(&session.fs_write, &denied.to_string_lossy()));
}
for roots in [
fence_scratch_roots(
&configured.to_string_lossy(),
&ordinary_temp,
Some(&partition),
),
fence_scratch_roots(".scratch", &ordinary_temp, None),
] {
let mut session =
confined_bench_caveats_with_grants(&workspace.to_string_lossy(), &roots, &[]);
calibrate_headless_filesystem(&mut session, &build, smart);
assert!(
!build.leq(&session),
"configured scratch requires coverage: smart={smart}"
);
}
}
for planned in [&workspace, &ordinary_temp, &partition, &configured] {
assert!(!planned.exists(), "startup must only plan paths");
}
}
#[test]
fn headless_build_projection_preserves_narrow_reads_and_other_authority() {
use newt_core::caveats::CountBound;
let fixture = tempfile::tempdir().unwrap();
let root = fixture.path().canonicalize().unwrap();
let workspace = root.join("workspace").to_string_lossy().into_owned();
let build = Caveats {
fs_read: Scope::only([
workspace.clone(),
root.join("toolchain").to_string_lossy().into_owned(),
]),
fs_write: Scope::only([
workspace.clone(),
root.join("outside/scratch").to_string_lossy().into_owned(),
]),
..Caveats::top()
};
for smart in [false, true] {
let mut session = Caveats {
fs_read: Scope::only([workspace.clone()]),
fs_write: Scope::only([workspace.clone()]),
exec: Scope::none(),
net: Scope::none(),
max_calls: CountBound::AtMost(3),
valid_for_generation: Scope::only([42]),
};
let baseline = session.clone();
calibrate_headless_filesystem(&mut session, &build, smart);
assert_eq!(session, baseline, "startup may not acquire authority");
assert!(!build.leq(&session));
}
}
#[cfg(unix)]
#[test]
fn headless_build_projection_handles_aliases_without_granting_symlink_escapes() {
use std::os::unix::fs::symlink;
let fixture = tempfile::tempdir().unwrap();
let root = fixture.path().canonicalize().unwrap();
let granted = root.join("granted");
let outside = root.join("outside");
std::fs::create_dir(&granted).unwrap();
std::fs::create_dir(&outside).unwrap();
let alias = root.join("alias");
symlink(&granted, &alias).unwrap();
symlink(&outside, granted.join("escape")).unwrap();
for smart in [false, true] {
let mut session = confined_bench_caveats_with_grants(
"/app/task",
&[alias.to_string_lossy().into_owned()],
&[],
);
let admitted = granted
.join("uncreated-build")
.to_string_lossy()
.into_owned();
let escaped = granted
.join("escape/uncreated-build")
.to_string_lossy()
.into_owned();
let build = Caveats {
fs_read: Scope::All,
fs_write: Scope::only([admitted.clone(), escaped.clone()]),
..Caveats::top()
};
calibrate_headless_filesystem(&mut session, &build, smart);
assert!(
session.fs_write.permits(&admitted),
"canonical alias: smart={smart}"
);
assert!(
!session.fs_write.permits(&escaped),
"symlink escape: smart={smart}"
);
assert!(!granted.join("uncreated-build").exists());
assert!(!outside.join("uncreated-build").exists());
}
}
#[cfg(unix)]
#[tokio::test]
async fn headless_custom_scratch_denies_build_before_effects_in_both_modes() {
let workspace = tempfile::tempdir().unwrap();
let workspace = workspace.path().canonicalize().unwrap();
let configured = tempfile::tempdir().unwrap();
let baseline = confined_bench_caveats_with_grants(
&workspace.to_string_lossy(),
&[configured
.path()
.canonicalize()
.unwrap()
.to_string_lossy()
.into_owned()],
&[],
);
let build = newt_core::confined_exec::build_tool_caveats(&workspace);
let scratch = newt_core::confined_exec::build_scratch_dir(&workspace);
let partition = scratch.parent().unwrap();
assert!(
!partition.exists(),
"planning a Build must not create its scratch"
);
for smart in [false, true] {
let mut session = baseline.clone();
calibrate_headless_filesystem(&mut session, &build, smart);
let marker = workspace.join(format!("unapproved-build-{smart}"));
let output = newt_core::execute_tool(
"build_exec",
&serde_json::json!({"argv": ["touch", marker.to_string_lossy()], "timeout_secs": 5}),
&workspace.to_string_lossy(),
false,
20,
&session,
&mut newt_core::NoMcp,
None, None, None, None, None, None, None,
None, None, None, None, None, None,
).await;
assert!(
output.contains("requires explicit confined build authority; no command ran"),
"custom scratch cannot authorize the managed partition: smart={smart}: {output}"
);
assert!(!marker.exists());
assert!(
!partition.exists(),
"a refused Build must not allocate scratch"
);
}
}
#[test]
fn fence_scratch_root_comes_from_configuration_then_temp_dir() {
use newt_core::caveats::permits_path;
let base = std::env::temp_dir();
let configured = base.join("newt-scratch-test");
let temp = base.join("newt-fallback-test");
let (configured_s, temp_s) = (
configured.to_string_lossy().into_owned(),
temp.to_string_lossy().into_owned(),
);
let writable = |cv: &Caveats, dir: &std::path::Path| {
permits_path(&cv.fs_write, &dir.join("x").to_string_lossy())
};
let roots = fence_scratch_roots(&configured_s, &temp, None);
assert_eq!(roots, std::slice::from_ref(&configured_s));
let cv = confined_bench_caveats_with_grants("/app/task", &roots, &[]);
assert!(writable(&cv, &configured));
assert!(!writable(&cv, &temp));
assert!(!writable(&cv, &base), "the temp dir itself is not granted");
let roots = fence_scratch_roots(".scratch", &temp, None);
assert_eq!(roots, [temp_s]);
let cv = confined_bench_caveats_with_grants("/app/task", &roots, &[]);
assert!(writable(&cv, &temp));
assert!(!writable(&cv, &configured));
let cv = confined_bench_caveats_with_grants("/app/task", &[], &[]);
assert!(!writable(&cv, &temp));
assert!(permits_path(&cv.fs_write, "/app/task/x"));
}
#[test]
fn confined_caveats_honor_write_paths_grant() {
let cv = confined_bench_caveats_with_grants(
"/app/task",
&["/srv/scratch".to_string()],
&["/data/scratch".to_string()],
);
assert!(
cv.permits_fs_write("/data/scratch"),
"a per-task NEWT_WRITE_PATHS grant joins the fence"
);
}
#[test]
fn fold_ocap_grants_widens_a_fenced_axis_but_never_touches_an_open_one() {
use newt_core::ocap_store::{build_store, Verdict};
let (store, warnings) = build_store(&[(
Verdict::Approve,
Some("[[fs]]\npath = \"/opt/canvas-token\"\n".to_string()),
)]);
assert!(warnings.is_empty(), "{warnings:?}");
let mut open = confined_bench_caveats_with_grants("/app/task", &[], &[]);
assert_eq!(open.fs_read, Scope::All);
let admitted = fold_ocap_grants(&mut open, &store);
assert_eq!(open.fs_read, Scope::All, "an open axis must stay open");
assert_eq!(
admitted,
vec!["fs_read:/opt/canvas-token (no-op: already permitted)".to_string()]
);
let mut fenced =
newt_core::confined_exec::build_tool_caveats(std::path::Path::new("/app/task"));
assert!(!fenced.permits_fs_read("/opt/canvas-token"));
fold_ocap_grants(&mut fenced, &store);
assert!(fenced.permits_fs_read("/opt/canvas-token"));
assert!(!fenced.permits_fs_write("/opt/canvas-token"));
}
#[test]
fn fold_ocap_grants_refuses_a_signed_high_danger_root() {
use newt_core::ocap_store::PolicyFile;
let key = newt_identity::UserKey::generate();
let mut file = PolicyFile::parse("[[fs]]\npath = '/'\nwrite = true\n").expect("parse");
let (signed, refused) = newt_core::ocap_store::sign_approves(
&mut file,
|_, _| false,
|p| key.sign(p).to_bytes(),
);
assert_eq!(signed, 1, "the forged signature must still verify");
assert!(refused.is_empty());
let (store, warnings) = newt_core::ocap_store::build_store(&[(
newt_core::ocap_store::Verdict::Approve,
Some(file.to_toml().expect("serialize")),
)]);
assert!(warnings.is_empty(), "{warnings:?}");
let mut caveats =
newt_core::confined_exec::build_tool_caveats(std::path::Path::new("/app/task"));
let admitted = fold_ocap_grants(&mut caveats, &store);
assert!(
admitted.is_empty(),
"a High-danger root must never be admitted, signature or not: {admitted:?}"
);
assert!(!caveats.permits_fs_write("/etc/shadow"));
}
#[test]
fn fold_ocap_grants_of_an_empty_store_admits_nothing() {
let store = newt_core::ocap_store::PolicySet::default();
let mut caveats =
newt_core::confined_exec::build_tool_caveats(std::path::Path::new("/app/task"));
let admitted = fold_ocap_grants(&mut caveats, &store);
assert!(admitted.is_empty());
assert!(!caveats.permits_fs_read("/opt/canvas-token"));
}
}