fix(microvm): the third place that assumed a VM phase has a repository

The research-vm scenario failed on its first run, and said exactly why:

  mission has no checkout at /var/lib/clawmates-missions/<id>/repo
    — a microvm phase needs a repository

`phase_runner` refuses upstream of both places the last commit fixed. Three
guards, written independently, all encoding "a microVM phase implies a git
checkout" — which is why the capture filter could cite it as settled fact.

A repo-BACKED mission with no checkout is still a real fault and still refused;
booting a VM to hand the agent an empty directory would turn a setup failure
into a confusing agent report. A repo-LESS one now gets the empty workspace
made here, so the executor's inject has something to pack.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Omar Sobh
2026-08-09 19:08:00 -07:00
co-authored by Claude Opus 5
parent 768e106614
commit dd80b69992
+17 -5
View File
@@ -1148,15 +1148,27 @@ async fn launch_microvm_phase(
/dev/kvm" /dev/kvm"
.to_string() .to_string()
})?; })?;
if !repo.is_dir() { // A repo-BACKED mission with no checkout is a real fault: something
// A research-only mission has no checkout, and there is nothing // went wrong before the phase, and booting a VM to hand the agent an
// for a VM to work on. Better to say so than to boot one and hand // empty directory would turn it into a confusing agent report.
// the agent an empty directory. //
// A repo-LESS mission is a different thing entirely, and this guard
// used to refuse it too — "a microvm phase needs a repository" was
// the third of three places that assumed so, alongside the inject
// and the readiness probe. It gets an empty workspace instead, made
// here so the executor's inject has something to pack.
if has_repo && !repo.is_dir() {
return Err(format!( return Err(format!(
"mission has no checkout at {} — a microvm phase needs a repository", "mission has no checkout at {} — a repo-backed microvm phase \
needs one",
repo.display() repo.display()
)); ));
} }
if !has_repo {
std::fs::create_dir_all(&repo).map_err(|e| {
format!("create empty workspace {}: {e}", repo.display())
})?;
}
crate::microvm_executor::run_phase_in_vm( crate::microvm_executor::run_phase_in_vm(
&hub, &hub,
crate::microvm_executor::VmPhase { crate::microvm_executor::VmPhase {