Skip to content

fix(coding-agent): honest status and prompt eviction for empty sessions - #1920

Merged
xeophon merged 8 commits into
mainfrom
snimu/empty-session-lifecycle
Aug 31, 2026
Merged

fix(coding-agent): honest status and prompt eviction for empty sessions#1920
xeophon merged 8 commits into
mainfrom
snimu/empty-session-lifecycle

Conversation

@snimu

@snimu snimu commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Two empty-session lifecycle fixes, found while investigating the macOS "ctrl+c never ends the session / after a couple of sessions it can't create a new one" report (companion to #1918).

Status honesty

A 0-message detached session was pinned at "working" forever - rendered as a red running entry in the agents view and prime-agent list - because activeActivityForSession holds sessions at "working" until a summarizer verdict exists, and an empty session never produces one. Users reasonably concluded that exiting "never ends the session". The fix is the same carve-out finished subagents already have: a session with 0 messages and nothing in flight is idle. An accepted in-flight first prompt still shows "working" (the busy guard runs first, pinned by test).

Evict empty unnamed sessions on last-client disconnect

An abandoned empty session parked a resident worker (~80 MB) plus an IPython kernel for the 90-minute idle-eviction window, holding 2 daemon file descriptors - the accumulation ingredient behind the EMFILE failure fixed in #1918. Now, when the last client disconnects from a worker whose sessions are all empty (0 messages), unnamed, not busy, and hold no heartbeat/cron registration, the supervisor passivates it immediately through the existing eviction path. Action-driven only - no new timers. Naming a session exempts it (that is the "I want to come back" signal); client-owned workers keep their existing cleanup path; eviction remains passivation, so the on-disk session survives as a draft.

Races verified against the ownership machinery from #1756/#1864: a create/attach arriving mid-stop fails cleanly with "worker is stopping" and relaunches from the draft; the eviction re-checks worker identity after its summary refresh and cannot stop a relaunched successor (stopWorker additionally pins the entry pid). Cold reopen of an evicted draft measures ~0.55s on macOS, indistinguishable from a warm attach.

Deliberately not gated on idleEvictionMinutes: "off": everything a user wants kept warm (messages, a name, a schedule, an attached client) already blocks this eviction, and gating would reinstate the leak for exactly the users most exposed to it.

Tests

Six behavior tests plus one extended assertion across daemon-session-list and a new daemon-supervisor-eviction case set: empty-idle status (proven red), the in-flight-first-prompt guard, last-client-only eviction (proven red), named/busy/non-empty exemptions, schedule-pinned and client-owned exemptions, and a replaced-worker race guard.

Linear: ENG-5809


Note

Medium Risk
evictEmptySessionOnLastDetach stops workers on detach; reconnecting spins up a new worker, and fence/drain logic must stay correct alongside idle sweeps and mid-flight mutations.

Overview
Fixes two empty-session lifecycle issues in the coding-agent daemon: misleading "working" status and workers staying resident after abandon.

Status: activeActivityForSession now treats zero-message resident sessions as idle (like finished subagents), so prime-agent list and the agents view no longer show abandoned empty drafts as permanently running. Sessions with real in-flight work still report working first.

Eviction: When the last client detaches or disconnects, the supervisor may passivate the worker immediately if every session on it matches isEvictableEmptySessionSummary (no messages, no name, not busy, no heartbeat/cron). Named sessions, busy sessions, client-owned workers, and multi-attach cases are exempt; eviction reuses the idle-sweep mutation drain + fence (withEvictionFence) so detach eviction and periodic idle sweeps do not race. On-disk draft sessions are preserved.

Tests cover empty-idle classification, detach-only eviction, exemptions, worker-replacement races, and fence coordination with idle sweeps.

Reviewed by Cursor Bugbot for commit 2114326. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix coding-agent daemon to report idle status and evict empty sessions on detach

  • Empty resident sessions with zero messages and nothing in flight now report activity as "idle" instead of staying pinned at "working" in daemon-session-list.ts.
  • When the last client detaches from an empty, unnamed, idle session, the worker is immediately stopped and its on-disk draft persists, via daemon-supervisor.evictEmptySessionOnLastDetach.
  • Eviction runs under a reusable eviction fence (withEvictionFence) that drains pending mutations before the decision, preventing races with in-flight worker refreshes or schedules registered during the drain.
  • Behavioral Change: daemon-supervisor client disconnect and detach command handlers now trigger eviction for qualifying empty sessions; sessions that were previously kept alive will be passivated immediately.

Macroscope summarized 2114326.

snimu added 3 commits August 31, 2026 16:08
…G-5809 review)

Adversarial-review killer tests for three mutants that survived the shipped
suite: dropping the heartbeat/cron registration checks from
isEvictableEmptySessionSummary, dropping the client-owned worker exclusion,
and removing the post-refresh identity/stopping re-check in
evictEmptySessionOnLastDetach.
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d63475f. Configure here.

Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts Outdated
@snimu
snimu requested a review from xeophon August 31, 2026 15:31
@xeophon
xeophon merged commit cbc0f7d into main Aug 31, 2026
23 checks passed
@xeophon
xeophon deleted the snimu/empty-session-lifecycle branch August 31, 2026 15:47
PR9000 pushed a commit to PR9000/prime-agent that referenced this pull request Sep 1, 2026
…ns (PrimeIntellect-ai#1920)

* fix(coding-agent): report an empty resident session as idle instead of pinning it at working (ENG-5809)

* feat(coding-agent): evict an empty unnamed session's worker when its last client disconnects (ENG-5809)

* test(coding-agent): kill surviving empty-session eviction mutants (ENG-5809 review)

Adversarial-review killer tests for three mutants that survived the shipped
suite: dropping the heartbeat/cron registration checks from
isEvictableEmptySessionSummary, dropping the client-owned worker exclusion,
and removing the post-refresh identity/stopping re-check in
evictEmptySessionOnLastDetach.

* chore(coding-agent): fold empty-session tests and trim comments

* fix(coding-agent): drain admitted mutations before deciding empty-session eviction (ENG-5809 Macroscope)

* chore(coding-agent): drop comments that restate the code

* fix(coding-agent): share one eviction-fence acquisition between the idle sweep and detach eviction (ENG-5809 review)

* refactor(coding-agent): extract the shared fenced passivation primitive (ENG-5809)
ketema added a commit to ketema/prime-agent that referenced this pull request Sep 1, 2026
- Direct session transport between TUI and worker (ENG-5817, PrimeIntellect-ai#1926)
- Event-driven supervisor agent roster with push subscriptions (PrimeIntellect-ai#1897, PrimeIntellect-ai#1900, PrimeIntellect-ai#1895)
- Hardened daemon startup, recovery ownership, and worker launch diagnostics (PrimeIntellect-ai#1929, PrimeIntellect-ai#1918)
- Python REPL runtime single-dump snapshots and bash preview tool (PrimeIntellect-ai#1945, PrimeIntellect-ai#1911)
- Non-blocking RLM subagent deletion and snapshot update suppression (PrimeIntellect-ai#1954, PrimeIntellect-ai#1944)
- Saved catalog loading on Agents View open (PrimeIntellect-ai#1960)
- Advanced Anthropic prompt caching marker across tool results (PrimeIntellect-ai#1927)
- TUI process replacement on update and empty draft eviction (PrimeIntellect-ai#1631, PrimeIntellect-ai#1946, PrimeIntellect-ai#1920)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants