1pub mod macros;
18
19mod agent_sessions;
20pub mod agent_state;
21pub(crate) mod agents;
22mod agents_daemon;
23mod artifact_emit;
24pub(crate) mod assemble;
25pub mod asset_paths;
26mod bytes;
27mod calendar;
28mod channel_guardrails;
29mod channels;
30pub(crate) mod clock;
31pub(crate) mod collections;
32mod command_policy;
33pub(crate) mod compaction;
34#[cfg(feature = "compression")]
35mod compression;
36mod concurrency;
37pub(crate) use concurrency::cancelled_vm_error;
38mod connectors;
39mod cookies;
40mod cron;
41mod crypto;
42mod csv;
43mod datetime;
44mod diff;
45pub(crate) use datetime::date_dict_from_millis;
46#[cfg(feature = "content")]
47mod document;
48mod durable_step;
49mod event_log;
50pub use event_log::mint_hypothesis_native_attestation;
51mod external_agent;
52pub(crate) mod files;
53mod flow;
54pub(crate) mod fs;
55mod git;
56pub(crate) mod git_topology;
57mod grounding;
58pub(crate) mod harn_entry;
59pub(crate) mod hitl;
60mod hitl_read;
61pub mod host;
62pub mod http_response;
63pub(crate) mod io;
64mod iter;
65pub(crate) mod json;
66mod json_query;
67pub(crate) mod json_stream;
68mod jsonrpc;
69mod junit;
70mod lifecycle_receipts;
71mod logging;
72pub mod long_running;
73mod math;
74pub(crate) use math::call_seeded_random_method;
75pub(crate) mod memory;
76mod monitors;
77mod multipart;
78mod net;
79mod net_policy;
80mod oauth_dynreg;
81mod oauth_storage;
82pub(crate) mod observability;
83pub(crate) mod options;
84mod package_snapshot;
85pub(crate) use package_snapshot::PackageSnapshotRegistry;
86mod path;
87pub(crate) mod path_scope_guard;
88pub(crate) mod pool;
89mod portable;
90#[cfg(feature = "postgres")]
91mod postgres;
92#[cfg(feature = "postgres")]
93pub use postgres::install_shared_pool_registry;
94pub mod process;
95pub(crate) mod process_spawn;
96mod project;
97mod project_catalog;
98mod project_enrich;
99mod regex;
100mod review;
101mod runtime_scope;
102pub(crate) mod sandbox;
103pub mod secret_scan;
104pub(crate) mod session_store;
105mod sets;
106pub(crate) mod shapes;
107mod skills;
108#[cfg(feature = "sqlite")]
109mod sqlite;
110pub(crate) mod strings;
111pub(crate) mod supervisor;
112pub mod template;
113mod testbench;
114mod testing;
115mod timing;
116pub mod token_redaction;
117pub(crate) mod tool_hooks;
118pub(crate) mod tools;
119pub mod tracing;
120mod transcript_compact;
121pub(crate) mod transcript_project;
122mod triggers_stdlib;
123mod tui;
124mod types;
125mod url_parse;
126mod vision;
127pub(crate) mod waitpoint;
128#[cfg(feature = "content")]
129mod web;
130pub mod workflow_messages;
131pub(crate) mod xml;
132
133use crate::http::register_http_builtins;
134use crate::llm::register_llm_builtins;
135use crate::mcp::register_mcp_builtins;
136use crate::mcp_server::register_mcp_server_builtins;
137use crate::vm::Vm;
138
139pub(crate) use crate::schema::{json_to_vm_value, schema_result_value};
140pub(crate) fn set_thread_source_dir(dir: &std::path::Path) {
141 process::set_thread_source_dir(dir);
142}
143
144pub fn register_core_stdlib(vm: &mut Vm) {
146 types::register_type_builtins(vm);
147 math::register_math_builtins(vm);
148 strings::register_string_builtins(vm);
149 json::register_json_builtins(vm);
150 json_stream::register_json_stream_builtins(vm);
151 xml::register_xml_builtins(vm);
152 datetime::register_datetime_builtins(vm);
153 diff::register_diff_builtins(vm);
154 #[cfg(feature = "content")]
155 document::register_document_builtins(vm);
156 calendar::register_calendar_builtins(vm);
157 cron::register_cron_builtins(vm);
158 regex::register_regex_builtins(vm);
159 bytes::register_bytes_builtins(vm);
160 #[cfg(feature = "compression")]
161 compression::register_compression_builtins(vm);
162 command_policy::register_command_policy_builtins(vm);
163 runtime_scope::register_runtime_scope_builtins(vm);
164 crypto::register_crypto_builtins(vm);
165 csv::register_csv_builtins(vm);
166 junit::register_junit_builtins(vm);
167 multipart::register_multipart_builtins(vm);
168 url_parse::register_url_builtins(vm);
169 #[cfg(feature = "content")]
170 web::register_web_builtins(vm);
171 cookies::register_cookie_builtins(vm);
172 path::register_path_helper_builtins(vm);
173 sets::register_set_builtins(vm);
174 collections::register_collection_builtins(vm);
175 iter::register_iter_builtins(vm);
176 event_log::register_event_log_builtins(vm);
177 durable_step::register_durable_step_builtins(vm);
178 channels::register_channel_builtins(vm);
179 channel_guardrails::register_channel_guardrail_builtins(vm);
180 shapes::register_shape_builtins(vm);
181 testing::register_testing_builtins(vm);
182 flow::register_flow_builtins(vm);
183 lifecycle_receipts::register_lifecycle_receipt_builtins(vm);
184 net_policy::register_net_policy_builtins(vm);
185 http_response::register_http_response_builtins(vm);
186 portable::register_portable_builtins(vm);
187}
188
189pub fn register_io_stdlib(vm: &mut Vm) {
191 io::register_io_builtins(vm);
192 host::register_host_builtins(vm);
193 fs::register_fs_builtins(vm);
194 package_snapshot::register_package_snapshot_builtins(vm);
195 files::register_file_builtins(vm);
196 git::register_git_builtins(vm);
197 vision::register_vision_builtins(vm);
198 agent_state::register_agent_state_builtins(vm);
199 memory::register_memory_builtins(vm);
200 session_store::register_session_store_builtins(vm);
201 net::register_net_builtins(vm);
202 process::register_process_builtins(vm);
203 process::register_path_builtins(vm);
204 sandbox::register_sandbox_builtins(vm);
205 clock::register_clock_builtins(vm);
208 crate::durable_rate_limit::register_durable_rate_limit_builtins(vm);
209 testbench::register_testbench_builtins(vm);
210 project::register_project_builtins(vm);
211 grounding::register_grounding_builtins(vm);
212 tracing::register_tracing_builtins(vm);
213 observability::register_observability_builtins(vm);
214 timing::register_timing_builtins(vm);
215 tui::register_tui_builtins(vm);
216}
217
218fn register_agent_stdlib_before_llm(vm: &mut Vm) {
219 concurrency::register_concurrency_builtins(vm);
220 connectors::register_connector_builtins(vm);
221 review::register_review_builtins(vm);
222 secret_scan::register_secret_scan_builtins(vm);
223 tools::register_tool_builtins(vm);
224 tool_hooks::register_tool_hooks_builtins(vm);
225 crate::composition::register_composition_builtins(vm);
226 skills::register_skill_builtins(vm);
227 agents_daemon::register_daemon_builtins(vm);
228 triggers_stdlib::register_trigger_builtins(vm);
229 #[cfg(feature = "postgres")]
230 postgres::register_postgres_builtins(vm);
231 #[cfg(feature = "sqlite")]
232 sqlite::register_sqlite_builtins(vm);
233 monitors::register_monitor_builtins(vm);
234 hitl::register_hitl_builtins(vm);
235 hitl_read::register_hitl_read_builtins(vm);
236 waitpoint::register_waitpoint_builtins(vm);
237 supervisor::register_supervisor_builtins(vm);
238 agents::register_agent_builtins(vm);
239 pool::register_pool_builtins(vm);
240 oauth_storage::register_oauth_storage_builtins(vm);
241 oauth_dynreg::register_oauth_dynreg_builtins(vm);
242 token_redaction::register_token_redaction_builtins(vm);
243 agent_sessions::register_agent_session_builtins(vm);
244 artifact_emit::register_artifact_emit_builtins(vm);
245 external_agent::register_external_agent_builtins(vm);
246 path_scope_guard::register_path_scope_guard_builtins(vm);
247 workflow_messages::register_workflow_message_builtins(vm);
248 transcript_compact::register_transcript_compaction_builtins(vm);
249 compaction::register_compaction_builtins(vm);
250 transcript_project::register_transcript_projection_builtins(vm);
251 assemble::register_assemble_context_builtin(vm);
252 crate::egress::register_egress_builtins(vm);
253 crate::security::register_security_builtins(vm);
254 register_http_builtins(vm);
255 jsonrpc::register_jsonrpc_builtins(vm);
256}
257
258fn register_agent_stdlib_after_llm(vm: &mut Vm) {
259 register_mcp_builtins(vm);
260 register_mcp_server_builtins(vm);
261 crate::step_runtime::register_step_builtins(vm);
262}
263
264pub fn register_agent_stdlib(vm: &mut Vm) {
266 register_agent_stdlib_before_llm(vm);
267 register_llm_builtins(vm);
268 register_agent_stdlib_after_llm(vm);
269}
270
271pub fn register_vm_stdlib(vm: &mut Vm) {
275 register_core_stdlib(vm);
276 register_io_stdlib(vm);
277 register_agent_stdlib(vm);
278 vm.project_declared_capability_methods();
279 if vm.harness().is_none() {
280 vm.set_harness(crate::harness::Harness::real());
281 }
282 if harn_parser::legacy_ambient_capabilities_enabled() && vm.global("harness").is_none() {
283 let harness = vm
284 .root_harness_value()
285 .expect("register_vm_stdlib installs a root Harness");
286 vm.set_global("harness", harness);
287 }
288 vm.project_legacy_capability_globals();
289 harn_builtin_registry::install_builtin_manifest(all_builtin_manifest());
290}
291
292pub(crate) fn rebind_execution_state_builtins(vm: &mut Vm) {
293 concurrency::register_concurrency_builtins(vm);
294}
295
296fn stdlib_probe_vm() -> Vm {
297 let mut vm = Vm::new();
298 register_vm_stdlib(&mut vm);
299 let tmp = std::env::temp_dir();
303 crate::store::register_store_builtins(&mut vm, &tmp);
304 crate::checkpoint::register_checkpoint_builtins(&mut vm, &tmp, "default");
305 crate::metadata::register_metadata_builtins(&mut vm, &tmp);
306 harn_builtin_registry::install_builtin_manifest(all_builtin_manifest());
311 vm
312}
313
314pub fn all_builtin_defs() -> &'static [&'static macros::VmBuiltinDef] {
330 let defs = ¯os::ALL_BUILTIN_DEFS;
331 validate_builtin_contracts(defs);
332 defs
333}
334
335fn validate_builtin_contracts(defs: &[¯os::VmBuiltinDef]) {
336 use harn_builtin_meta::BuiltinExposure;
337 let mut source_names = std::collections::BTreeSet::new();
338 let mut capability_methods = std::collections::BTreeSet::new();
339 for def in defs {
340 assert!(
341 def.contract.is_declared(),
342 "builtin `{}` has no typed exposure/effect contract",
343 def.sig.name
344 );
345 assert!(
346 !matches!(def.contract.exposure, BuiltinExposure::PureGlobal)
347 || def.contract.effects.is_empty(),
348 "ambient global builtin `{}` declares effects; effects must flow through Harness",
349 def.sig.name
350 );
351 if let BuiltinExposure::CapabilityFunction { authority_argument } = def.contract.exposure {
352 assert!(
353 !def.contract.effects.is_empty(),
354 "capability function `{}` must declare effects",
355 def.sig.name
356 );
357 assert!(
358 usize::from(authority_argument) < def.sig.params.len(),
359 "capability function `{}` authority argument is out of range",
360 def.sig.name
361 );
362 }
363 if def.runtime_only {
364 assert!(
365 matches!(def.contract.exposure, BuiltinExposure::RuntimeInternal),
366 "runtime_only builtin `{}` must use runtime_internal exposure",
367 def.sig.name
368 );
369 }
370 if let BuiltinExposure::HarnessMethod { method, .. } = def.contract.exposure {
371 assert!(
372 !method.is_empty(),
373 "harness method for `{}` cannot be empty",
374 def.sig.name
375 );
376 let BuiltinExposure::HarnessMethod { capability, method } = def.contract.exposure
377 else {
378 unreachable!()
379 };
380 assert!(
381 capability_methods.insert((capability, method)),
382 "duplicate contract for harness.{}.{}",
383 capability.field_name(),
384 method
385 );
386 }
387 if matches!(
388 def.contract.exposure,
389 BuiltinExposure::PureGlobal
390 | BuiltinExposure::CapabilityFunction { .. }
391 | BuiltinExposure::PrivilegedWire
392 | BuiltinExposure::HarnessMethod { .. }
393 ) {
394 assert!(
395 source_names.insert(def.sig.name),
396 "duplicate source contract name `{}`",
397 def.sig.name
398 );
399 }
400 }
401}
402
403pub fn force_link() {
411 let len = std::hint::black_box(macros::ALL_BUILTIN_DEFS.len());
417 assert!(
418 len >= 1,
419 "linkme distributed_slice ALL_BUILTIN_DEFS is empty — \
420 the binary is missing `harn_vm::stdlib::force_link()` at startup, \
421 or the linker stripped the harn-vm rlib statics (see linkme issue #36)"
422 );
423}
424
425pub fn all_builtin_manifest() -> &'static [&'static harn_builtin_registry::BuiltinManifestEntry] {
427 use std::sync::OnceLock;
428 static AGG: OnceLock<Vec<&'static harn_builtin_registry::BuiltinManifestEntry>> =
429 OnceLock::new();
430 AGG.get_or_init(|| {
431 let mut out = Vec::new();
432 let mut capability_methods = std::collections::BTreeSet::new();
433 for def in all_builtin_defs() {
434 if def.runtime_only {
435 continue;
436 }
437 out.push(
438 Box::leak(Box::new(harn_builtin_registry::BuiltinManifestEntry {
439 name: def.sig.name,
440 canonical_name: def.sig.name,
441 signature: &def.sig,
442 contract: def.contract,
443 })) as &'static harn_builtin_registry::BuiltinManifestEntry,
444 );
445 if let harn_builtin_meta::BuiltinExposure::HarnessMethod { capability, method } =
446 def.contract.exposure
447 {
448 capability_methods.insert((capability, method));
449 }
450 for alias in def.aliases {
451 let signature = Box::leak(Box::new(harn_builtin_meta::BuiltinSignature {
452 name: alias,
453 ..def.sig
454 }));
455 out.push(
456 Box::leak(Box::new(harn_builtin_registry::BuiltinManifestEntry {
457 name: alias,
458 canonical_name: def.sig.name,
459 signature,
460 contract: def.contract,
461 })) as &'static harn_builtin_registry::BuiltinManifestEntry,
462 );
463 }
464 }
465 for entry in harn_capability_contracts::manifest() {
466 let harn_builtin_meta::BuiltinExposure::HarnessMethod { capability, method } =
467 entry.contract.exposure
468 else {
469 unreachable!("leaf capability manifest contains a non-method contract")
470 };
471 if !capability_methods.insert((capability, method)) {
472 let runtime_entry = out
473 .iter()
474 .find(|candidate| candidate.contract.exposure == entry.contract.exposure)
475 .expect("duplicate capability key must have a runtime manifest entry");
476 assert_eq!(
477 runtime_entry.contract,
478 entry.contract,
479 "runtime effect contract drift for harness.{}.{}",
480 capability.field_name(),
481 method
482 );
483 assert_eq!(
484 runtime_entry.signature,
485 entry.signature,
486 "runtime signature drift for harness.{}.{}",
487 capability.field_name(),
488 method
489 );
490 continue;
491 }
492 out.push(*entry);
493 }
494 for group in harn_builtin_meta::host_capabilities::all_host_capability_groups() {
495 for method in group.methods {
496 if !capability_methods.insert((group.capability, *method)) {
497 continue;
498 }
499 let internal_name: &'static str = Box::leak(
500 format!("__cap_{}_{}", group.capability.field_name(), method).into_boxed_str(),
501 );
502 let params: &'static [harn_builtin_meta::Param] =
503 Box::leak(Box::new([harn_builtin_meta::Param::new(
504 "request",
505 harn_builtin_meta::Ty::Named("dict"),
506 )]));
507 let signature = Box::leak(Box::new(harn_builtin_meta::BuiltinSignature::simple(
508 internal_name,
509 params,
510 harn_builtin_meta::Ty::Named("dict"),
511 )));
512 out.push(Box::leak(Box::new(
513 harn_builtin_registry::BuiltinManifestEntry {
514 name: internal_name,
515 canonical_name: internal_name,
516 signature,
517 contract: harn_builtin_meta::BuiltinContract::harness(
518 group.capability,
519 method,
520 group.effects,
521 ),
522 },
523 )));
524 }
525 }
526 out
527 })
528 .as_slice()
529}
530
531struct BuiltinManifestIndex {
538 by_name: std::collections::HashMap<
539 &'static str,
540 &'static harn_builtin_registry::BuiltinManifestEntry,
541 >,
542 by_capability: std::collections::HashMap<
543 harn_builtin_meta::CapabilityId,
544 std::collections::HashMap<
545 &'static str,
546 &'static harn_builtin_registry::BuiltinManifestEntry,
547 >,
548 >,
549 recorded_effects_by_name: std::collections::HashMap<
550 &'static str,
551 &'static harn_builtin_registry::BuiltinManifestEntry,
552 >,
553}
554
555fn builtin_manifest_index() -> &'static BuiltinManifestIndex {
556 use harn_builtin_meta::BuiltinExposure;
557 use std::sync::OnceLock;
558
559 static INDEX: OnceLock<BuiltinManifestIndex> = OnceLock::new();
560 INDEX.get_or_init(|| {
561 let mut by_name = std::collections::HashMap::new();
562 let mut by_capability: std::collections::HashMap<
563 harn_builtin_meta::CapabilityId,
564 std::collections::HashMap<
565 &'static str,
566 &'static harn_builtin_registry::BuiltinManifestEntry,
567 >,
568 > = std::collections::HashMap::new();
569 let mut recorded_effects_by_name = std::collections::HashMap::new();
570 for entry in all_builtin_manifest() {
571 assert!(
572 by_name.insert(entry.name, *entry).is_none(),
573 "duplicate builtin manifest name `{}`",
574 entry.name
575 );
576 if let BuiltinExposure::HarnessMethod { capability, method } = entry.contract.exposure {
579 if entry.is_canonical() {
580 assert!(
581 by_capability
582 .entry(capability)
583 .or_default()
584 .insert(method, *entry)
585 .is_none(),
586 "duplicate Harness method manifest entry `harness.{}.{method}`",
587 capability.field_name()
588 );
589 }
590 }
591 if matches!(
592 entry.contract.exposure,
593 BuiltinExposure::CapabilityFunction { .. }
594 | BuiltinExposure::HarnessMethod { .. }
595 | BuiltinExposure::PrivilegedWire
596 ) && !entry.contract.effects.is_empty()
597 {
598 recorded_effects_by_name.insert(entry.name, *entry);
599 }
600 }
601 BuiltinManifestIndex {
602 by_name,
603 by_capability,
604 recorded_effects_by_name,
605 }
606 })
607}
608
609pub fn builtin_for_harness_path(path: &str) -> Option<&'static str> {
616 let (field, method) = path.strip_prefix("harness.")?.split_once('.')?;
617 let capability = harn_builtin_meta::CapabilityId::from_field_name(field)?;
618 capability_method_manifest_entry(capability, method).map(|entry| entry.name)
619}
620
621pub fn harness_method_for_builtin(
623 name: &str,
624) -> Option<(harn_builtin_meta::CapabilityId, &'static str)> {
625 match builtin_manifest_entry(name)?.contract.exposure {
626 harn_builtin_meta::BuiltinExposure::HarnessMethod { capability, method } => {
627 Some((capability, method))
628 }
629 _ => None,
630 }
631}
632
633pub fn builtin_manifest_entry(
635 name: &str,
636) -> Option<&'static harn_builtin_registry::BuiltinManifestEntry> {
637 builtin_manifest_index().by_name.get(name).copied()
638}
639
640pub fn capability_method_manifest_entry(
642 capability: harn_builtin_meta::CapabilityId,
643 method: &str,
644) -> Option<&'static harn_builtin_registry::BuiltinManifestEntry> {
645 builtin_manifest_index()
646 .by_capability
647 .get(&capability)
648 .and_then(|methods| methods.get(method))
649 .copied()
650}
651
652pub fn recorded_effect_builtin_manifest_entry(
658 name: &str,
659) -> Option<&'static harn_builtin_registry::BuiltinManifestEntry> {
660 builtin_manifest_index()
661 .recorded_effects_by_name
662 .get(name)
663 .copied()
664}
665
666mod harness_migration;
667
668pub use harness_migration::{
669 harness_migration_for_builtin, HarnessBuiltinArgumentMigration, HarnessBuiltinMigration,
670};
671
672pub fn register_all_macro_builtins(vm: &mut Vm) {
677 for def in all_builtin_defs() {
678 vm.register_builtin_def(def);
679 }
680}
681
682pub fn stdlib_builtin_names() -> Vec<String> {
685 let vm = stdlib_probe_vm();
686 let mut names = vm.builtin_names();
687 for extra in harn_parser::builtin_signatures::LANGUAGE_INTRINSICS {
690 names.push(extra.to_string());
691 }
692 names
693}
694
695pub fn stdlib_builtin_metadata() -> Vec<crate::vm::VmBuiltinMetadata> {
697 stdlib_probe_vm().builtin_metadata()
698}
699
700pub fn builtin_exposure(name: &str) -> Option<harn_builtin_meta::BuiltinExposure> {
714 use std::sync::OnceLock;
715 static BY_NAME: OnceLock<
716 std::collections::HashMap<String, harn_builtin_meta::BuiltinExposure>,
717 > = OnceLock::new();
718 BY_NAME
719 .get_or_init(|| {
720 stdlib_probe_vm()
721 .builtin_metadata()
722 .into_iter()
723 .map(|entry| (entry.name().to_string(), entry.contract().exposure))
724 .collect()
725 })
726 .get(name)
727 .copied()
728}
729
730#[derive(Debug, Clone, Copy, PartialEq, Eq)]
732pub struct HarnessMethodTarget {
733 pub capability: harn_builtin_meta::CapabilityId,
734 pub method: &'static str,
735}
736
737impl HarnessMethodTarget {
738 pub fn path(&self) -> String {
740 format!("{}.{}", self.capability.field_name(), self.method)
741 }
742}
743
744pub fn harness_method_for_host_operation(operation: &str) -> Option<HarnessMethodTarget> {
766 use harn_builtin_meta::{wire_identifier_key, BuiltinExposure, CapabilityId};
767 use std::collections::HashMap;
768 use std::sync::OnceLock;
769
770 let (namespace, operation_method) = operation.split_once('.')?;
771 if let Some((capability, method)) =
772 harn_builtin_meta::host_capabilities::capability_binding_for_schema(
773 namespace,
774 operation_method,
775 )
776 {
777 return Some(HarnessMethodTarget { capability, method });
778 }
779
780 static BY_CAPABILITY: OnceLock<HashMap<CapabilityId, Vec<&'static str>>> = OnceLock::new();
781 let declared = BY_CAPABILITY.get_or_init(|| {
782 let mut index: HashMap<CapabilityId, Vec<&'static str>> = HashMap::new();
783 for entry in all_builtin_manifest() {
790 if !entry.is_canonical() {
791 continue;
792 }
793 if let BuiltinExposure::HarnessMethod { capability, method } = entry.contract.exposure {
794 index.entry(capability).or_default().push(method);
795 }
796 }
797 index
798 });
799
800 let capability = CapabilityId::from_host_namespace(namespace)?;
803 let methods = declared.get(&capability)?;
804 if let Some(exact) = methods.iter().find(|method| **method == operation_method) {
805 return Some(HarnessMethodTarget {
806 capability,
807 method: exact,
808 });
809 }
810 let wanted = wire_identifier_key(operation_method);
811 let mut lenient = methods
812 .iter()
813 .filter(|method| wire_identifier_key(method) == wanted);
814 let only = lenient.next()?;
815 lenient.next().is_none().then_some(HarnessMethodTarget {
816 capability,
817 method: only,
818 })
819}
820
821pub fn exposure_is_source_nameable(exposure: harn_builtin_meta::BuiltinExposure) -> bool {
828 use harn_builtin_meta::BuiltinExposure;
829 match exposure {
830 BuiltinExposure::PureGlobal
831 | BuiltinExposure::CapabilityFunction { .. }
832 | BuiltinExposure::Undeclared => true,
833 BuiltinExposure::HarnessMethod { .. }
834 | BuiltinExposure::PrivilegedWire
835 | BuiltinExposure::RuntimeInternal => false,
836 }
837}
838
839pub fn reset_stdlib_state() {
852 logging::reset_logging_state();
853 process::reset_process_state();
854 clock::reset_clock_state();
855 io::reset_io_state();
856 sandbox::reset_sandbox_state();
857 git::reset_git_state();
858 fs::reset_fs_state();
859 json::reset_json_state();
860 json_stream::reset_json_stream_state();
861 host::reset_host_state();
862 host::reset_scoped_host_state();
863 observability::reset_observability_state();
864 timing::reset_timing_state();
865 durable_step::reset_durable_step_state();
866 crate::egress::reset_egress_policy_for_host();
867 hitl::reset_hitl_state();
868 crate::http::reset_http_state();
869 crate::external_agent::reset_external_agent_state();
870 monitors::reset_monitor_state();
871 waitpoint::reset_waitpoint_state();
872 triggers_stdlib::reset_auto_resume_timeouts();
873 compaction::reset_compaction_state();
874 agents::reset_agent_worker_state();
875 agents::workflow::reset_workflow_run_states();
876 pool::reset_pool_state();
877 #[cfg(feature = "postgres")]
878 postgres::reset_postgres_state();
879 #[cfg(feature = "sqlite")]
880 sqlite::reset_sqlite_state();
881 supervisor::reset_supervisor_state();
882 agents::records::reset_eval_metrics();
883 agents::records::reset_friction_events();
884 tools::clear_current_tool_registry();
885 tools::clear_tool_synthesis_cache();
886 vision::reset_vision_state();
887 crate::skills::clear_current_skill_registry();
888 template::reset_prompt_registry();
889 crate::triggers::clear_webhook_intake_state();
890 crate::llm::cache::reset_in_process_cache_state();
891}
892
893#[cfg(test)]
894mod tests {
895 use super::*;
896
897 #[test]
898 fn host_operation_resolves_to_its_declared_harness_method() {
899 let target = harness_method_for_host_operation("ast.outline")
900 .expect("`ast.outline` is declared by harn-hostlib");
901 assert_eq!(target.path(), "ast.outline");
902 }
903
904 #[test]
905 fn host_operation_namespace_matching_ignores_underscores() {
906 let squashed = harness_method_for_host_operation("prmonitor.run_commands")
909 .expect("`prmonitor` names the `pr_monitor` capability");
910 let spelled = harness_method_for_host_operation("pr_monitor.run_commands")
911 .expect("the declared spelling resolves too");
912 assert_eq!(squashed, spelled);
913 assert_eq!(squashed.path(), "pr_monitor.run_commands");
914 }
915
916 #[test]
917 fn host_operation_without_a_declared_owner_resolves_to_nothing() {
918 for operation in [
922 "ast.*",
923 "capability.operation",
924 "runtime.set_result",
925 "ast",
926 "",
927 ] {
928 assert_eq!(
929 harness_method_for_host_operation(operation),
930 None,
931 "`{operation}` must not resolve"
932 );
933 }
934 }
935
936 #[test]
937 fn host_operation_honors_the_schema_tables_deliberate_remapping() {
938 let target = harness_method_for_host_operation("session.open")
945 .expect("`session.open` is a declared hostlib schema operation");
946 assert_eq!(target.path(), "agent.session_open");
947 }
948
949 #[tokio::test(flavor = "current_thread")]
950 async fn register_vm_stdlib_passes_default_harness_only_to_main() {
951 let chunk = crate::compile_source(
952 r"
953fn __probe_harness_clock(clock: HarnessClock) {
954 const now = clock.now_ms()
955 return now >= 0
956}
957
958fn main(harness: Harness) {
959 return __probe_harness_clock(harness.clock)
960}
961",
962 )
963 .expect("compile harness clock probe");
964 let mut vm = Vm::new();
965 register_vm_stdlib(&mut vm);
966
967 assert!(vm.root_harness_value().is_some());
968 assert!(vm.global("harness").is_none());
969 let result = vm
970 .execute(&chunk)
971 .await
972 .expect("execute harness clock probe");
973 assert!(matches!(result, crate::value::VmValue::Bool(true)));
974 }
975
976 #[test]
982 fn every_stdlib_builtin_reexport_names_a_registered_builtin() {
983 let registered: std::collections::HashSet<&str> = all_builtin_defs()
984 .iter()
985 .flat_map(|def| std::iter::once(def.sig.name).chain(def.aliases.iter().copied()))
986 .collect();
987
988 let mut checked = 0;
989 for entry in harn_stdlib::STDLIB_SOURCES {
990 for name in harn_stdlib::builtin_reexports(entry.module) {
991 assert!(
992 registered.contains(name),
993 "std/{} re-exports '{name}', which is not a registered builtin",
994 entry.module
995 );
996 checked += 1;
997 }
998 }
999 assert!(
1000 checked > 0,
1001 "no re-exports were checked — the table or the module list is not being read"
1002 );
1003 }
1004
1005 #[test]
1006 fn ambient_effect_builtin_allowlist_is_empty() {
1007 let offenders = all_builtin_defs()
1008 .iter()
1009 .filter(|def| {
1010 matches!(
1011 def.contract.exposure,
1012 harn_builtin_meta::BuiltinExposure::PureGlobal
1013 ) && !def.contract.effects.is_empty()
1014 })
1015 .map(|def| def.sig.name)
1016 .collect::<Vec<_>>();
1017
1018 assert!(
1019 offenders.is_empty(),
1020 "ambient effect builtins are forbidden; route these through Harness: {offenders:?}"
1021 );
1022 }
1023
1024 #[test]
1025 fn harness_builtin_migrations_preserve_canonical_call_shapes() {
1026 use harn_builtin_meta::CapabilityId;
1027
1028 assert_eq!(
1029 harness_migration_for_builtin("provider_capabilities"),
1030 Some(HarnessBuiltinMigration {
1031 capability: CapabilityId::Llm,
1032 method: "provider_capabilities",
1033 arguments: HarnessBuiltinArgumentMigration::Forward,
1034 })
1035 );
1036 assert_eq!(
1037 harness_migration_for_builtin("log_info"),
1038 Some(HarnessBuiltinMigration {
1039 capability: CapabilityId::Observability,
1040 method: "log_info",
1041 arguments: HarnessBuiltinArgumentMigration::Forward,
1042 })
1043 );
1044 assert_eq!(
1045 harness_migration_for_builtin("runtime_introspection"),
1046 Some(HarnessBuiltinMigration {
1047 capability: CapabilityId::Runtime,
1048 method: "introspection",
1049 arguments: HarnessBuiltinArgumentMigration::Forward,
1050 })
1051 );
1052 assert_eq!(
1053 harness_migration_for_builtin("project_fingerprint"),
1054 Some(HarnessBuiltinMigration {
1055 capability: CapabilityId::Project,
1056 method: "fingerprint",
1057 arguments: HarnessBuiltinArgumentMigration::Forward,
1058 })
1059 );
1060 assert_eq!(
1061 harness_migration_for_builtin("project_scan_tree_native"),
1062 Some(HarnessBuiltinMigration {
1063 capability: CapabilityId::Project,
1064 method: "scan_tree",
1065 arguments: HarnessBuiltinArgumentMigration::Forward,
1066 })
1067 );
1068 assert_eq!(
1069 harness_migration_for_builtin("llm_call"),
1070 Some(HarnessBuiltinMigration {
1071 capability: CapabilityId::Llm,
1072 method: "call",
1073 arguments: HarnessBuiltinArgumentMigration::Forward,
1074 })
1075 );
1076 assert_eq!(
1077 harness_migration_for_builtin("llm_call_structured"),
1078 Some(HarnessBuiltinMigration {
1079 capability: CapabilityId::Llm,
1080 method: "call_structured",
1081 arguments: HarnessBuiltinArgumentMigration::Forward,
1082 })
1083 );
1084 assert_eq!(
1085 harness_migration_for_builtin("security_policy"),
1086 Some(HarnessBuiltinMigration {
1087 capability: CapabilityId::System,
1088 method: "security_policy",
1089 arguments: HarnessBuiltinArgumentMigration::Forward,
1090 })
1091 );
1092 assert_eq!(
1093 harness_migration_for_builtin("llm_provider_status"),
1094 Some(HarnessBuiltinMigration {
1095 capability: CapabilityId::Llm,
1096 method: "providers",
1097 arguments: HarnessBuiltinArgumentMigration::Forward,
1098 })
1099 );
1100 assert_eq!(
1101 harness_migration_for_builtin("agent_session_current_id"),
1102 Some(HarnessBuiltinMigration {
1103 capability: CapabilityId::Agent,
1104 method: "current_id",
1105 arguments: HarnessBuiltinArgumentMigration::Forward,
1106 })
1107 );
1108 assert_eq!(
1109 harness_migration_for_builtin("metadata_set"),
1110 Some(HarnessBuiltinMigration {
1111 capability: CapabilityId::Project,
1112 method: "metadata_set",
1113 arguments: HarnessBuiltinArgumentMigration::RequestRecord(&[
1114 "dir",
1115 "namespace",
1116 "data",
1117 ]),
1118 })
1119 );
1120 assert_eq!(
1121 harness_migration_for_builtin("metadata_save"),
1122 Some(HarnessBuiltinMigration {
1123 capability: CapabilityId::Project,
1124 method: "metadata_save",
1125 arguments: HarnessBuiltinArgumentMigration::RequestRecord(&[]),
1126 })
1127 );
1128 assert_eq!(
1129 harness_migration_for_builtin("platform"),
1130 Some(HarnessBuiltinMigration {
1131 capability: CapabilityId::System,
1132 method: "platform",
1133 arguments: HarnessBuiltinArgumentMigration::CallThenProperty("os"),
1134 })
1135 );
1136 assert_eq!(
1137 harness_migration_for_builtin("arch"),
1138 Some(HarnessBuiltinMigration {
1139 capability: CapabilityId::System,
1140 method: "platform",
1141 arguments: HarnessBuiltinArgumentMigration::CallThenProperty("arch"),
1142 })
1143 );
1144 assert_eq!(
1145 harness_migration_for_builtin("home_dir"),
1146 Some(HarnessBuiltinMigration {
1147 capability: CapabilityId::Fs,
1148 method: "home_dir",
1149 arguments: HarnessBuiltinArgumentMigration::Forward,
1150 })
1151 );
1152 assert_eq!(harness_migration_for_builtin("json_parse"), None);
1153 }
1154
1155 #[test]
1156 fn every_source_named_runtime_callable_has_a_typed_contract() {
1157 let manifest_names = all_builtin_manifest()
1158 .iter()
1159 .map(|entry| entry.name)
1160 .collect::<std::collections::HashSet<_>>();
1161 let offenders = stdlib_probe_vm()
1162 .builtin_names()
1163 .into_iter()
1164 .filter(|name| {
1165 !name.starts_with("__")
1166 && !manifest_names.contains(name.as_str())
1167 && !harn_parser::builtin_signatures::is_language_intrinsic(name)
1168 })
1169 .collect::<Vec<_>>();
1170
1171 assert!(
1172 offenders.is_empty(),
1173 "runtime callables without typed source contracts bypass the Harness gate: {offenders:?}"
1174 );
1175 }
1176
1177 #[test]
1178 fn builtin_manifest_indexes_preserve_the_authoritative_contracts() {
1179 use harn_builtin_meta::BuiltinExposure;
1180
1181 let mut capability_entries = 0;
1182 for entry in all_builtin_manifest() {
1183 assert!(
1184 std::ptr::eq(
1185 builtin_manifest_entry(entry.name).expect("indexed builtin entry"),
1186 *entry,
1187 ),
1188 "name index projected a different contract for `{}`",
1189 entry.name
1190 );
1191 let should_record = matches!(
1192 entry.contract.exposure,
1193 BuiltinExposure::CapabilityFunction { .. }
1194 | BuiltinExposure::HarnessMethod { .. }
1195 | BuiltinExposure::PrivilegedWire
1196 ) && !entry.contract.effects.is_empty();
1197 assert_eq!(
1198 recorded_effect_builtin_manifest_entry(entry.name).is_some(),
1199 should_record,
1200 "recorded-effect index drifted for `{}`",
1201 entry.name
1202 );
1203 if let BuiltinExposure::HarnessMethod { capability, method } = entry.contract.exposure {
1204 capability_entries += 1;
1205 let indexed = capability_method_manifest_entry(capability, method)
1206 .expect("indexed Harness method entry");
1207 assert_eq!(
1210 indexed.name,
1211 entry.canonical_name,
1212 "capability index projected a different builtin for `harness.{}.{method}`",
1213 capability.field_name()
1214 );
1215 assert_eq!(
1216 indexed.contract,
1217 entry.contract,
1218 "capability index projected a different contract for `harness.{}.{method}`",
1219 capability.field_name()
1220 );
1221 }
1222 }
1223 assert!(capability_entries > 0, "no Harness contracts were indexed");
1224 assert!(builtin_manifest_entry("__definitely_missing_builtin").is_none());
1225 assert!(capability_method_manifest_entry(
1226 harn_builtin_meta::CapabilityId::Fs,
1227 "__definitely_missing_method",
1228 )
1229 .is_none());
1230 }
1231}
1232
1233#[cfg(test)]
1234mod ambient_host_internal_projection_tests {
1235 use super::*;
1236
1237 #[test]
1238 fn ambient_bridge_projects_host_internal_emit_event_alias() {
1239 let previous = std::env::var_os(harn_parser::HARN_LEGACY_AMBIENT_CAPABILITIES_ENV);
1240 unsafe {
1241 std::env::set_var(harn_parser::HARN_LEGACY_AMBIENT_CAPABILITIES_ENV, "1");
1242 }
1243 let mut vm = Vm::new();
1244 register_vm_stdlib(&mut vm);
1245 assert!(
1246 vm.builtin_metadata_for("agent_emit_event").is_some(),
1247 "ambient bridge must project __host_agent_emit_event as agent_emit_event"
1248 );
1249 assert!(
1250 vm.builtin_metadata_for("__host_agent_emit_event").is_some(),
1251 "canonical host internal must remain registered"
1252 );
1253 unsafe {
1254 match previous {
1255 Some(value) => {
1256 std::env::set_var(harn_parser::HARN_LEGACY_AMBIENT_CAPABILITIES_ENV, value);
1257 }
1258 None => std::env::remove_var(harn_parser::HARN_LEGACY_AMBIENT_CAPABILITIES_ENV),
1259 }
1260 }
1261 }
1262}