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