@@ -8777,6 +8777,107 @@ console.log(JSON.stringify({ status: "ok", summary }));
87778777 fs::remove_dir_all(host_dir).expect("remove temp dir");
87788778 }
87798779
8780+ fn disposing_dirty_process_does_not_reconcile_live_host_mount_into_itself() {
8781+ let host_dir = temp_dir("agentos-native-sidecar-live-host-dir-dispose");
8782+ let generated_dir = host_dir.join("generated");
8783+ fs::create_dir(&generated_dir).expect("create generated workspace directory");
8784+ let generated_file = generated_dir.join("generated.txt");
8785+ fs::write(&generated_file, "keep me").expect("seed generated host file");
8786+ let stale_process_dir = temp_dir("agentos-native-sidecar-stale-process-output");
8787+ std::os::unix::fs::symlink("stale-target", stale_process_dir.join("generated.txt"))
8788+ .expect("seed stale process symlink");
8789+
8790+ let mut sidecar = create_test_sidecar();
8791+ let (connection_id, session_id) =
8792+ authenticate_and_open_session(&mut sidecar).expect("authenticate and open session");
8793+ let vm_id = create_vm(
8794+ &mut sidecar,
8795+ &connection_id,
8796+ &session_id,
8797+ PermissionsPolicy::allow_all(),
8798+ )
8799+ .expect("create vm");
8800+ sidecar
8801+ .vms
8802+ .get_mut(&vm_id)
8803+ .expect("created vm")
8804+ .kernel
8805+ .symlink("/workspace/generated", "/current")
8806+ .expect("create guest alias before mounting its target");
8807+ sidecar
8808+ .dispatch_blocking(request(
8809+ 4,
8810+ OwnershipScope::vm(&connection_id, &session_id, &vm_id),
8811+ RequestPayload::ConfigureVm(ConfigureVmRequest {
8812+ mounts: vec![MountDescriptor {
8813+ guest_path: String::from("/workspace"),
8814+ guest_source: String::from("host_dir"),
8815+ guest_fstype: String::from("host_dir"),
8816+ read_only: false,
8817+ plugin: MountPluginDescriptor {
8818+ id: String::from("host_dir"),
8819+ config: json!({
8820+ "hostPath": host_dir,
8821+ "readOnly": false,
8822+ })
8823+ .to_string(),
8824+ },
8825+ }],
8826+ software: Vec::new(),
8827+ permissions: None,
8828+ module_access_cwd: None,
8829+ instructions: Vec::new(),
8830+ projected_modules: Vec::new(),
8831+ command_permissions: std::collections::HashMap::new(),
8832+ loopback_exempt_ports: Vec::new(),
8833+ packages: Vec::new(),
8834+ packages_mount_at: String::new(),
8835+ bootstrap_commands: Vec::new(),
8836+ binding_shim_commands: Vec::new(),
8837+ }),
8838+ ))
8839+ .expect("configure live host mount");
8840+
8841+ insert_fake_javascript_parent_process(
8842+ &mut sidecar,
8843+ &vm_id,
8844+ &stale_process_dir,
8845+ "dirty-host-mount-process",
8846+ );
8847+ {
8848+ let mut vm = sidecar.vms.get_mut(&vm_id).expect("configured vm");
8849+ let process = vm
8850+ .active_processes
8851+ .get_mut("dirty-host-mount-process")
8852+ .expect("inserted dirty process");
8853+ process.guest_cwd = String::from("/current");
8854+ process.host_write_dirty = true;
8855+ }
8856+
8857+ sidecar
8858+ .dispose_vm_internal_blocking(
8859+ &connection_id,
8860+ &session_id,
8861+ &vm_id,
8862+ DisposeReason::Requested,
8863+ )
8864+ .expect("dispose VM with live host mount");
8865+
8866+ assert_eq!(
8867+ fs::read_to_string(&generated_file).expect("generated host file must survive"),
8868+ "keep me"
8869+ );
8870+
8871+ sidecar
8872+ .close_session_blocking(&connection_id, &session_id)
8873+ .expect("close session");
8874+ sidecar
8875+ .remove_connection_blocking(&connection_id)
8876+ .expect("remove connection");
8877+ fs::remove_dir_all(host_dir).expect("remove host dir");
8878+ fs::remove_dir_all(stale_process_dir).expect("remove stale process dir");
8879+ }
8880+
87808881 fn configure_vm_passes_resource_read_limits_to_host_dir_mounts() {
87818882 let host_dir = temp_dir("agentos-native-sidecar-host-dir-read-limit");
87828883 fs::write(host_dir.join("hello.txt"), "hello from host").expect("seed host dir");
@@ -25687,6 +25788,16 @@ try {
2568725788 dirty_host_shadow_sync_precedes_top_level_and_nested_spawn_actions();
2568825789 }
2568925790
25791+ #[test]
25792+ fn service_dispose_preserves_live_host_mount_symlinks() {
25793+ disposing_dirty_process_does_not_reconcile_live_host_mount_into_itself();
25794+ }
25795+
25796+ #[test]
25797+ fn service_node_input_type_module_eval_uses_esm_parser() {
25798+ command_resolution_executes_node_module_eval_command();
25799+ }
25800+
2569025801 #[test]
2569125802 fn service_posix_spawnp_path_and_recursive_shebang_match_linux() {
2569225803 posix_spawnp_path_and_recursive_shebang_match_linux();
0 commit comments