use crate::orchestration::*;
use std::sync::Arc;
fn run_registered_closure_probe(source: &str) -> (Result<String, String>, usize) {
use std::sync::atomic::{AtomicUsize, Ordering};
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
let probe_calls = Arc::new(AtomicUsize::new(0));
let probe_for_rt = Arc::clone(&probe_calls);
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
let result = rt.block_on(async move {
let local = tokio::task::LocalSet::new();
local
.run_until(async move {
let chunk = crate::compile_source(source)?;
let mut vm = crate::Vm::new();
crate::stdlib::register_vm_stdlib(&mut vm);
let probe = Arc::clone(&probe_for_rt);
vm.register_builtin("__probe_bridge_gate", move |_args, _out| {
probe.fetch_add(1, Ordering::SeqCst);
crate::orchestration::enforce_current_policy_for_bridge_builtin(
"evaluate_burin_user_reminder_rules",
)?;
Ok(crate::value::VmValue::String(arcstr::ArcStr::from("ok")))
});
vm.register_async_builtin("__test_fire_reminders", |ctx, args| async move {
let session_id = args
.first()
.map(crate::value::VmValue::display)
.unwrap_or_default();
let report = crate::llm::reminder_providers::evaluate_and_inject(
Some(&ctx),
crate::orchestration::HookEvent::SessionStart,
&session_id,
serde_json::json!({}),
serde_json::json!({}),
)
.await?;
Ok(crate::json_to_vm_value(&report))
});
push_execution_policy(CapabilityPolicy {
tools: vec!["read".to_string()],
..Default::default()
});
let outcome = vm.execute(&chunk).await;
pop_execution_policy();
outcome
.map(|_| vm.output().to_string())
.map_err(|error| error.to_string())
})
.await
});
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
(result, probe_calls.load(Ordering::SeqCst))
}
#[test]
fn registered_provider_and_session_hook_evaluate_under_execution_policy() {
let script = r#"pipeline main() {
const session = agent_session_open("trusted-bridge-probe")
agent_session_reset(session)
register_reminder_provider({
id: "probe-provider",
subscribes_to: ["session_start"],
evaluate: { ctx ->
__probe_bridge_gate()
return []
},
})
register_session_hook("session_start", { _payload ->
__probe_bridge_gate()
return {control: "allow"}
})
__test_fire_reminders(session)
__host_fire_session_hook("session_start", {session: {id: session}, event: "session_start"})
}"#;
let (result, probe_calls) = run_registered_closure_probe(script);
result.expect(
"a registered reminder provider and session hook must evaluate under an active \
execution policy without tripping the bridged-builtin gate",
);
assert_eq!(
probe_calls, 2,
"both the reminder-provider closure and the session-hook closure must have executed \
the bridged-builtin probe exactly once each"
);
}
#[test]
fn bridged_builtin_outside_registered_closure_is_still_rejected_under_policy() {
let script = r"pipeline main() {
__probe_bridge_gate()
}";
let (result, probe_calls) = run_registered_closure_probe(script);
let error = result.expect_err(
"a bridged builtin invoked outside a registered provider/hook closure must remain \
rejected while an execution policy is active",
);
assert!(
error.contains("exceeds execution policy"),
"rejection must come from the execution-policy gate, got: {error}"
);
assert_eq!(
probe_calls, 1,
"the probe should have run once and been rejected by the gate"
);
}
const REGISTERED_CLOSURE_MODULE: &str = r#"pub fn compute_provider_reminders(ctx) {
return []
}
pub fn session_hook_decision(payload) {
return {control: "allow"}
}
pub fn register_provider_closure() {
register_reminder_provider({
id: "fn-provider",
subscribes_to: ["session_start"],
evaluate: { ctx -> return compute_provider_reminders(ctx) },
})
return nil
}
pub fn register_hook_closure() {
register_session_hook("session_start", { payload ->
return session_hook_decision(payload)
})
return nil
}
"#;
async fn register_from_disposable_vm(register_fn: &str) {
let mut vm = crate::Vm::new();
crate::stdlib::register_vm_stdlib(&mut vm);
let exports = vm
.load_module_exports_from_source(
"orchestration/tests/registered_closure_module.harn",
REGISTERED_CLOSURE_MODULE,
)
.await
.expect("compile registered-closure module");
let register = exports
.get(register_fn)
.unwrap_or_else(|| panic!("module must export {register_fn}"))
.clone();
vm.call_closure_pub(®ister, &[])
.await
.expect("registration closure must run");
drop(exports);
drop(vm);
}
#[test]
fn registered_provider_closure_resolves_sibling_fn_after_registering_vm_dropped() {
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
let result = rt.block_on(async {
let local = tokio::task::LocalSet::new();
local
.run_until(async {
register_from_disposable_vm("register_provider_closure").await;
let mut vm = crate::Vm::new();
crate::stdlib::register_vm_stdlib(&mut vm);
vm.register_async_builtin("__test_fire_reminders", |ctx, _args| async move {
let report = crate::llm::reminder_providers::evaluate_and_inject(
Some(&ctx),
crate::orchestration::HookEvent::SessionStart,
"provider-fn-probe",
serde_json::json!({}),
serde_json::json!({}),
)
.await?;
Ok(crate::json_to_vm_value(&report))
});
let chunk = crate::compile_source(
r#"pipeline main() {
const session = agent_session_open("provider-fn-probe")
agent_session_reset(session)
__test_fire_reminders()
}"#,
)?;
push_execution_policy(CapabilityPolicy {
tools: vec!["read".to_string()],
..Default::default()
});
let outcome = vm.execute(&chunk).await;
pop_execution_policy();
outcome.map(|_| ()).map_err(|error| error.to_string())
})
.await
});
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
result.expect(
"a registered reminder provider's evaluate closure must resolve its sibling module \
`pub fn` in-VM even after the registering VM is dropped, not fall through to \
host-bridge dispatch",
);
}
#[test]
fn registered_session_hook_closure_resolves_sibling_fn_after_registering_vm_dropped() {
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
let result = rt.block_on(async {
let local = tokio::task::LocalSet::new();
local
.run_until(async {
register_from_disposable_vm("register_hook_closure").await;
let mut vm = crate::Vm::new();
crate::stdlib::register_vm_stdlib(&mut vm);
let chunk = crate::compile_source(
r#"pipeline main() {
__host_fire_session_hook("session_start", {session: {id: "hook-fn-probe"}, event: "session_start"})
}"#,
)?;
push_execution_policy(CapabilityPolicy {
tools: vec!["read".to_string()],
..Default::default()
});
let outcome = vm.execute(&chunk).await;
pop_execution_policy();
outcome.map(|_| ()).map_err(|error| error.to_string())
})
.await
});
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
result.expect(
"a registered session hook's handler closure must resolve its sibling module `pub fn` \
in-VM even after the registering VM is dropped, not fall through to host-bridge \
dispatch",
);
}
#[test]
fn registered_provider_closure_unknown_name_still_falls_through_to_bridge() {
const MODULE: &str = r#"pub fn register_unknown_call_provider() {
register_reminder_provider({
id: "unknown-call-provider",
subscribes_to: ["session_start"],
evaluate: { ctx -> return definitely_not_a_defined_name(ctx) },
})
return nil
}
"#;
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
let result = rt.block_on(async {
let local = tokio::task::LocalSet::new();
local
.run_until(async {
let mut vm = crate::Vm::new();
crate::stdlib::register_vm_stdlib(&mut vm);
let exports = vm
.load_module_exports_from_source(
"orchestration/tests/unknown_call_module.harn",
MODULE,
)
.await
.expect("compile unknown-call module");
let register = exports
.get("register_unknown_call_provider")
.expect("module must export register fn")
.clone();
vm.call_closure_pub(®ister, &[])
.await
.expect("registration closure must run");
drop(exports);
drop(vm);
let mut vm = crate::Vm::new();
crate::stdlib::register_vm_stdlib(&mut vm);
vm.register_async_builtin("__test_fire_reminders", |ctx, _args| async move {
let report = crate::llm::reminder_providers::evaluate_and_inject(
Some(&ctx),
crate::orchestration::HookEvent::SessionStart,
"unknown-call-probe",
serde_json::json!({}),
serde_json::json!({}),
)
.await?;
Ok(crate::json_to_vm_value(&report))
});
let chunk = crate::compile_source(
r#"pipeline main() {
const session = agent_session_open("unknown-call-probe")
agent_session_reset(session)
__test_fire_reminders()
}"#,
)?;
let outcome = vm.execute(&chunk).await;
outcome.map(|_| ()).map_err(|error| error.to_string())
})
.await
});
clear_execution_policy_stacks();
crate::llm::reminder_providers::clear_reminder_providers();
clear_session_hooks();
let error = result
.expect_err("a genuinely unknown name must not resolve in-VM after the scope-pin fix");
assert!(
error.contains("definitely_not_a_defined_name"),
"the unresolved name must still fall through to builtin/host-bridge dispatch, got: {error}"
);
}