From 3fedb980c76fb309d468b0a7b44771ab012a5e1c Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Tue, 5 May 2026 02:00:43 -0500 Subject: [PATCH] fix(subagents): replace 'pending' lease placeholder with real agent id (#660) Resident-file leases were stamped as "pending" at spawn time because the agent id is only assigned by the manager later. The release function introduced in 2ee926924 matches by agent id, so it could never find those entries and leases would persist for the lifetime of the process. After spawn returns the real agent id, replace any "pending" entry with it so the existing release-on-terminal-state path actually fires. Resolves the documented v0.8.12 caveat noted in the CHANGELOG. Closes the loop with PR #694, which proposed a release-by-file-path API but did not address the placeholder problem itself. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/tui/src/tools/subagent/mod.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/crates/tui/src/tools/subagent/mod.rs b/crates/tui/src/tools/subagent/mod.rs index d63bac68..04363b54 100644 --- a/crates/tui/src/tools/subagent/mod.rs +++ b/crates/tui/src/tools/subagent/mod.rs @@ -1683,6 +1683,23 @@ impl ToolSpec for AgentSpawnTool { ) .map_err(|e| ToolError::execution_failed(format!("Failed to spawn sub-agent: {e}")))?; + // Replace the "pending" lease placeholder with the real agent id now that + // the manager has assigned one. Without this, `release_resident_leases_for` + // (which matches by agent id at terminal-state transitions) can never find + // the entry — leases would stay stamped as "pending" forever, defeating the + // release machinery added in #660. + if let Some(ref file_path) = spawn_request.resident_file { + if let Some(lock) = RESIDENT_LEASES.get() { + if let Ok(mut guard) = lock.lock() { + if let Some(owner) = guard.get_mut(file_path) { + if owner == "pending" { + *owner = result.agent_id.clone(); + } + } + } + } + } + let mut tool_result = if self.name == "spawn_agent" { let mut payload = json!({ "agent_id": result.agent_id.clone(),