feat(infra): temp IdeA généralisé à tous les agents + purge du store managed-tmp au shutdown d'IdeA — #200 (QA verte)

This commit is contained in:
2026-08-15 00:14:25 +02:00
parent e6f6eb5b1b
commit b5653b24b5
10 changed files with 271 additions and 14 deletions

View File

@ -818,6 +818,12 @@ impl ManagedTempStore for FakeManagedTempStore {
async fn gc(&self, _now_ms: u64) -> Result<ManagedTempGcReport, ManagedTempError> {
Ok(ManagedTempGcReport { deleted: 0 })
}
async fn purge_all(&self) -> Result<ManagedTempGcReport, ManagedTempError> {
let deleted = self.leases.lock().unwrap().len();
self.leases.lock().unwrap().clear();
Ok(ManagedTempGcReport { deleted })
}
}
struct FixedClock;
@ -4665,13 +4671,17 @@ async fn launch_pty_allocates_managed_tmp_env_and_sandbox_from_same_path() {
let store = Arc::new(FakeManagedTempStore::default());
store.set_allocation_path(tmp.clone());
let (allocator, _resolver, releaser) = managed_temp_usecases(&store);
let profile = codex_profile().with_projector(ProjectorKey::Codex);
let profile = profile(
pid(9),
ContextInjection::convention_file("CLAUDE.md").unwrap(),
)
.with_projector(ProjectorKey::Claude);
let (launch, agent, _fs, pty, _sessions) = launch_with_projection(
profile,
Some(ContextInjectionPlan::File {
target: "AGENTS.md".to_owned(),
target: "CLAUDE.md".to_owned(),
}),
Some(full_registry()),
None,
Some(perm_doc(Posture::Ask)),
);
let launch = launch.with_launch_managed_temp(allocator, releaser);
@ -4691,6 +4701,51 @@ async fn launch_pty_allocates_managed_tmp_env_and_sandbox_from_same_path() {
let _ = std::fs::remove_dir_all(&root);
}
#[tokio::test]
async fn launch_structured_non_codex_uses_managed_tmp_for_env_and_sandbox_without_writable_roots() {
let root = fresh_temp_dir("launch-tmp-structured-non-codex");
let tmp = root.join("managed-tmp-main").to_string_lossy().into_owned();
let store = Arc::new(FakeManagedTempStore::default());
store.set_allocation_path(tmp.clone());
let (allocator, _resolver, releaser) = managed_temp_usecases(&store);
let profile = profile(
pid(9),
ContextInjection::convention_file("CLAUDE.md").unwrap(),
)
.with_projector(ProjectorKey::Claude)
.with_structured_adapter(StructuredAdapter::Claude);
let (mut launch, agent, _fs, pty, _sessions) = launch_with_projection(
profile,
Some(ContextInjectionPlan::File {
target: "CLAUDE.md".to_owned(),
}),
None,
Some(perm_doc(Posture::Ask)),
);
let factory = FakeStructuredFactory::new(trace(), sid(891));
let structured = Arc::new(StructuredSessions::new());
launch = launch
.with_launch_managed_temp(allocator, releaser)
.with_structured_routing_mode(StructuredRoutingMode::RequireStructured)
.with_structured(Arc::new(factory.clone()), Arc::clone(&structured));
launch
.execute(launch_input_with_project_root(agent.id, &root))
.await
.expect("structured launch");
assert!(pty.spawns().is_empty());
let env = factory.envs().remove(0);
let env: HashMap<_, _> = env.into_iter().collect();
assert_eq!(env.get("TMPDIR"), Some(&tmp));
assert_eq!(env.get("TMP"), Some(&tmp));
assert_eq!(env.get("TEMP"), Some(&tmp));
assert_eq!(factory.policies(), vec![None]);
let sandbox = factory.sandboxes().remove(0).expect("sandbox plan");
assert!(sandbox_has_rw_root(&sandbox, &tmp));
let _ = std::fs::remove_dir_all(&root);
}
#[tokio::test]
async fn launch_structured_codex_uses_same_managed_tmp_for_env_sandbox_and_writable_roots() {
let root = fresh_temp_dir("launch-tmp-structured");