Skip to content

fix(background-agent): decrement spawn budget on task completion, cancellation, error, and interrupt#2725

Merged
code-yeongyu merged 2 commits intocode-yeongyu:devfrom
cphoward:fix/spawn-budget-lifetime-semantics-clean
Mar 25, 2026
Merged

fix(background-agent): decrement spawn budget on task completion, cancellation, error, and interrupt#2725
code-yeongyu merged 2 commits intocode-yeongyu:devfrom
cphoward:fix/spawn-budget-lifetime-semantics-clean

Conversation

@cphoward
Copy link
Copy Markdown
Contributor

@cphoward cphoward commented Mar 20, 2026

Summary

Fixes #2700 — subagents stop spawning after 50 total per session.

Root Cause

rootDescendantCounts in BackgroundManager increments on every spawn but only decrements on pre-start rollback or root session deletion. Task completion, cancellation, error, and interrupt never decrement the counter. This makes background_task.maxDescendants (default: 50) a session-lifetime quota instead of its intended semantics as a concurrent-active agent cap.

After 50 total spawns across a session (completed + cancelled + errored), no new subagents can be created — even if all 50 have finished.

Fix

Add this.unregisterRootDescendant(task.rootSessionID) in five terminal-state handlers:

  1. tryCompleteTask() — task completes successfully
  2. cancelTask() — running task cancelled (with wasRunning guard: pending tasks already decrement via rollbackPreStartDescendantReservation to prevent double-decrement)
  3. session.error handler — task errors
  4. promptAsync catch in startTask — task interrupted on launch
  5. promptAsync catch in resume — task interrupted on resume
  6. onTaskPruned callback — stale task pruned (with wasPending guard)

Tests

Four regression tests added to manager.test.ts:

  • Completed task releases quota (was blocked before fix, passes after)
  • Cancelled running task releases quota (was blocked before fix, passes after)
  • Errored task releases quota (was blocked before fix, passes after)
  • No double-decrement for pending cancellation (guard correctness)

Verification

Before fix: spawn 51st agent after 1st completes → blocked with maxDescendants=50 error
After fix: spawn 51st agent after 1st completes → succeeds

Full test suite: 121 pass, 3 fail (3 pre-existing failures in unrelated session.error > retry path tests, present before this change)


Summary by cubic

Fixes spawn budget leaks in BackgroundManager by decrementing root descendant counts when tasks end. Restores background_task.maxDescendants to act as a concurrent cap so new subagents can spawn after others finish.

  • Bug Fixes
    • Decrement on completion, running cancel, error, start/resume interrupt, and stale prune with guards to prevent double-decrement for pending tasks.
    • Added regression tests for complete/cancel/error and a case ensuring pending cancel does not double-decrement.

Written for commit 031503b. Summary will update on new commits.

…cellation, error, and interrupt

rootDescendantCounts was incremented on every spawn but never decremented
when tasks reached terminal states (completed, cancelled, error, interrupt,
stale-pruned). This made maxDescendants=50 a session-lifetime quota instead
of its intended semantics as a concurrent-active agent cap.

Fix: add unregisterRootDescendant() in five terminal-state handlers:
- tryCompleteTask(): task completes successfully
- cancelTask(): running task cancelled (wasRunning guard prevents
  double-decrement for pending tasks already handled by
  rollbackPreStartDescendantReservation)
- session.error handler: task errors
- promptAsync catch (startTask): task interrupted on launch
- promptAsync catch (resume): task interrupted on resume
- onTaskPruned callback: stale task pruned (wasPending guard)

Fixes: code-yeongyu#2700
…nt on task completion

Tests prove rootDescendantCounts is never decremented on task completion,
cancellation, or error — making maxDescendants a lifetime quota instead of
a concurrent-active cap. All 4 tests fail (RED phase) before the fix.

Refs: code-yeongyu#2700
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Fixes a significant resource leak in the subagent spawn budget. Includes defensive guards against double-decrementing for pending tasks and adds comprehensive regression tests.

@cryptobetEU
Copy link
Copy Markdown

@code-yeongyu please merge/add this PR

@code-yeongyu code-yeongyu merged commit 5df54bc into code-yeongyu:dev Mar 25, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage:bug-fix PR: Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Many subagents keep getting canceled, not proceeding after 50 subagents.

3 participants