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) <noreply@anthropic.com>
This commit is contained in:
Hunter Bown
2026-05-05 02:00:43 -05:00
parent 48d529fa93
commit 3fedb980c7
+17
View File
@@ -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(),