fix: async run_tests to prevent zombie cargo processes blocking gates

run_tests MCP tool now spawns tests in the background and returns
immediately. Agents poll get_test_result to check completion. This
prevents zombie cargo processes from holding the build lock when the
CLI times out the MCP call before tests finish.

Also fixes agent permission mode: acceptEdits replaces invalid
allowFullAutoEdit that was causing agents to crash-loop on spawn.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dave
2026-04-11 22:00:05 +00:00
parent 8393a67c89
commit f958f57e56
6 changed files with 262 additions and 63 deletions
+31
View File
@@ -6,9 +6,36 @@ use crate::state::SessionState;
use crate::store::JsonFileStore;
use crate::workflow::WorkflowState;
use poem::http::StatusCode;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::{broadcast, mpsc, oneshot};
/// A running or completed test job spawned by the `run_tests` MCP tool.
pub struct TestJob {
/// The child process handle. `None` once the process has exited and results
/// have been collected.
pub child: Option<std::process::Child>,
/// Populated once the child exits.
pub result: Option<TestJobResult>,
/// When the job was started.
pub started_at: std::time::Instant,
}
/// The result of a completed test job.
#[derive(Clone)]
pub struct TestJobResult {
pub passed: bool,
pub exit_code: i32,
pub tests_passed: u64,
pub tests_failed: u64,
pub output: String,
}
/// Shared registry of in-flight and recently completed test jobs, keyed by
/// worktree path.
pub type TestJobRegistry = Arc<std::sync::Mutex<HashMap<PathBuf, TestJob>>>;
/// The user's decision when responding to a permission dialog.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PermissionDecision {
@@ -75,6 +102,9 @@ pub struct AppContext {
/// spawned by the bot so that cancellations take effect in-memory rather
/// than only on disk.
pub timer_store: Arc<TimerStore>,
/// Registry of running/completed test jobs spawned by the `run_tests` MCP
/// tool. Keyed by worktree path so each worktree has at most one active job.
pub test_jobs: TestJobRegistry,
}
#[cfg(test)]
@@ -102,6 +132,7 @@ impl AppContext {
bot_shutdown: None,
matrix_shutdown_tx: None,
timer_store,
test_jobs: Arc::new(std::sync::Mutex::new(HashMap::new())),
}
}
}