Version / branch / commit
Source-reviewed on main at 99721c7.
OS and environment
Linux amd64; Go 1.26.6. AI-assisted source audit, manually checked against implementation and existing tests. This overload scenario has not been dynamically reproduced.
Steps to reproduce
Suggested deterministic regression case using the existing fake worker fixtures:
- Construct a pool with Size=1 and a worker blocked on a test channel.
- Construct SessionManager with MaxSessions=2.
- Start substantially more than two unique sessions while the worker remains blocked.
- Inspect registered sessions and queued work; then release the workers and inspect retention without calling Start again.
Expected behavior
Pending work has an explicit admission bound, independent of completed-session retention. Excess starts reject or wait through a bounded mechanism. Completed retention eventually returns to its configured bound without requiring another submission.
Actual behavior / source evidence
session.go:266-281 inserts each session and spawns a goroutine before the pool slot is acquired. pool.go:180-185 bounds running workers, not waiting callers.
pruneLocked:285-305 intentionally preserves queued/running sessions. Pruning is called from Start, but not after sess.finish. A sustained backlog can therefore grow session state and goroutines, and an oversized completed burst remains retained until a later start.
MaxSessions is documented as retention, so this report is not asking to evict running sessions. It is about the missing separate admission boundary and completion-time retention cleanup.
Suggested fix / regression coverage
Reserve pending-work capacity before creating per-session goroutines; reject overload or use a bounded queue. Prune completed history independently of new submissions. Test blocked workers, overload, cancellation, and retention after completion.
Verification
Existing go test ./... and focused go test -race -count=1 ./internal/daemon passed during the audit. Existing TestSessionManagerKeepsRunningOverCap intentionally allows over-cap running sessions; it does not establish a bounded pending queue. No production overload or OOM experiment was run.
Version / branch / commit
Source-reviewed on main at 99721c7.
OS and environment
Linux amd64; Go 1.26.6. AI-assisted source audit, manually checked against implementation and existing tests. This overload scenario has not been dynamically reproduced.
Steps to reproduce
Suggested deterministic regression case using the existing fake worker fixtures:
Expected behavior
Pending work has an explicit admission bound, independent of completed-session retention. Excess starts reject or wait through a bounded mechanism. Completed retention eventually returns to its configured bound without requiring another submission.
Actual behavior / source evidence
session.go:266-281 inserts each session and spawns a goroutine before the pool slot is acquired. pool.go:180-185 bounds running workers, not waiting callers.
pruneLocked:285-305 intentionally preserves queued/running sessions. Pruning is called from Start, but not after sess.finish. A sustained backlog can therefore grow session state and goroutines, and an oversized completed burst remains retained until a later start.
MaxSessions is documented as retention, so this report is not asking to evict running sessions. It is about the missing separate admission boundary and completion-time retention cleanup.
Suggested fix / regression coverage
Reserve pending-work capacity before creating per-session goroutines; reject overload or use a bounded queue. Prune completed history independently of new submissions. Test blocked workers, overload, cancellation, and retention after completion.
Verification
Existing go test ./... and focused go test -race -count=1 ./internal/daemon passed during the audit. Existing TestSessionManagerKeepsRunningOverCap intentionally allows over-cap running sessions; it does not establish a bounded pending queue. No production overload or OOM experiment was run.