You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Runner pruning counts terminal runs with active subscribers against MaxCompletedRetention even though they are ineligible for deletion. With a retention limit of one and one subscriber-pinned terminal run, a newly completed run can be pruned immediately before the StartRun caller subscribes. Hosted race CI exposed this in TestRunner_PruneKeepsCompletedRunWithActiveSubscriber when collectRunEvents received run not found.
Acceptance criteria
Subscriber-pinned terminal runs remain protected but do not consume the quota for drainable terminal runs.
The newest unpinned completed run remains subscribable while older unpinned runs are pruned to the configured limit.
Cancelling the pinned subscriber re-runs pruning and brings the retained terminal set back within the configured unpinned quota.
Persistent run records and terminal-event persistence gates remain unchanged.
Focused normal/race stress, harness normal/race, full regression, and GitHub required checks pass.
In scope
Completed-run pruning quota calculation and regression coverage.
Engineering log, plan, impact map, plans index.
Out of scope
Conversation mirror retention, persistent store deletion, subscriber delivery, terminal event ordering, or retention configuration shape.
Current architecture and search evidence
RunnerConfig.MaxCompletedRetention says the cap applies after terminal events are persisted and subscribers drain.
pruneCompletedRunsLocked increments terminalCount for every persisted terminal run, but adds only zero-subscriber runs to candidates; it then deletes terminalCount-limit candidates.
A subscriber-pinned run therefore consumes quota without being deletable, causing a just-completed candidate to be removed immediately.
Subscribe returns run not found if pruning wins between StartRun and the caller subscription.
Harness/API: StartRun followed by Subscribe remains reliable under retention pressure; persistent records unchanged.
TUI/macOS GUI: run-scoped clients no longer lose a just-finished run because another terminal stream remains pinned. Conversation-level callback/cron streams are unchanged but benefit from stable run state.
Config: MaxCompletedRetention retains its current field/default; semantics now match its documented after-subscribers-drain boundary.
Persistence/schema/providers/tools/security: none after repository search.
Concurrency/reliability: pruning continues under Runner locking; only eligible candidate counting changes.
Compatibility: may retain up to configured unpinned limit plus any subscriber-pinned terminal runs, which is the documented exception.
Deployment/observability: no migration or flag. Existing run-not-found errors disappear. Rollback by reverting if memory can grow after subscriber cancellation.
Documentation: engineering/long-term logs, plan, impact map, plans index; no public API schema changes.
Test-first plan
Red: existing TestRunner_PruneKeepsCompletedRunWithActiveSubscriber fails under hosted race CI because extra run 2 is pruned before subscription.
Green: compute pruning pressure from eligible zero-subscriber terminal candidates, not all terminal states.
Stress: focused normal/race at count=100 plus adjacent pruning tests and complete harness normal/race.
Full: ./scripts/test-regression.sh and hosted required checks.
Rollout and rollback
Merge through an exact-head reviewed closing PR after all gates. Revert if cancellation no longer reclaims pinned state or unpinned retention exceeds the configured limit.
Summary
Runner pruning counts terminal runs with active subscribers against MaxCompletedRetention even though they are ineligible for deletion. With a retention limit of one and one subscriber-pinned terminal run, a newly completed run can be pruned immediately before the StartRun caller subscribes. Hosted race CI exposed this in TestRunner_PruneKeepsCompletedRunWithActiveSubscriber when collectRunEvents received run not found.
Acceptance criteria
In scope
Out of scope
Current architecture and search evidence
Impact analysis
Test-first plan
Rollout and rollback
Merge through an exact-head reviewed closing PR after all gates. Revert if cancellation no longer reclaims pinned state or unpinned retention exceeds the configured limit.
Dependencies
Related #958 and epic #1000. Blocks PRs #1047, #1045, #1043, #1041, #1033 and the callback/GUI merge chain.