Skip to content

fix(server): keep Claude messaging sessions alive - #9612

Open
Gigioxx wants to merge 1 commit into
pingdotgg:mainfrom
Gigioxx:t3code/keep-messaging-sessions-alive
Open

Gigioxx wants to merge 1 commit into
pingdotgg:mainfrom
Gigioxx:t3code/keep-messaging-sessions-alive

Conversation

@Gigioxx

@Gigioxx Gigioxx commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

What Changed

Keep live Claude sessions out of the inactivity reaper so their cross-session messaging endpoint remains addressable. Other providers and Claude bindings without a live adapter session keep the existing cleanup behavior.

Why

Claude's process owns its roster entry and messaging socket. Reaping an idle thread removes it from ListAgents, makes SendMessage fail, and resuming cannot restore the same endpoint identity.

Fixes #9586.

Verification

  • Reproduced the failure with a focused reaper test before the fix
  • vp test run apps/server/src/provider/Layers/ProviderSessionReaper.test.ts (9 passed)
  • Targeted format and lint passed
  • vp run --filter t3 typecheck passed
  • git diff --check passed

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No UI changes

Implemented with gpt-5.6-sol in T3 Code through the Codex harness.


Note

Medium Risk
Changes session lifecycle for Claude only and adds a listSessions dependency each sweep; wrong skip logic could leave zombie sessions or fail to reap when messaging is gone.

Overview
The inactivity ProviderSessionReaper no longer stops idle Claude bindings when listSessions() still reports a live claudeAgent session for that thread, so cross-session messaging can keep using the same process endpoint. Other providers and Claude bindings without a live adapter session still follow the existing stale-session cleanup.

Tests mock activeSessions on the harness, assert stale codex sessions are still reaped, and add cases for idle ready / error Claude threads that must not call stopSession. Multi-session failure/defect scenarios use error thread status on the Claude side so those bindings are not exempted by the new skip rule.

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

Note

Fix ProviderSessionReaper to keep live Claude messaging sessions alive

The reaper previously stopped stale persisted Claude bindings even when a live session was still active. The sweep in makeProviderSessionReaper now calls providerService.listSessions, builds a set of active Claude thread IDs, and skips stopping any Claude binding whose thread ID is in that set.

Tests in ProviderSessionReaper.test.ts are updated: the generic stale-session test switched to the Codex provider, and new parameterized tests verify that live idle Claude sessions in ready and error states are retained.

Risk: non-Claude providers are unaffected; only Claude bindings with a matching live thread ID are exempted from reaping.

Macroscope summarized c3ab694.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Sep 4, 2026
@macroscopeapp

macroscopeapp Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at c3ab694

Macroscope's review found this PR approvable — This is a small, focused server bug fix that preserves live Claude processes needed for cross-session messaging while leaving other provider cleanup behavior unchanged. Tests cover both retained Claude sessions and continued cleanup of stale Codex sessions.

You can add or adjust custom eligibility rules. Learn more.

@shivamhwp

Copy link
Copy Markdown
Collaborator

Note: GPT-6 on behalf of shivam (@shivamhwp).

Please rebase the new reaper cases onto the current sweepAt harness and await its completed sweep. Ten Effect.yieldNow calls do not prove the reaper finished, so the negative stop assertion can pass before the relevant work runs. Preserve the direct thread-shell query and the full idle window after turn settlement when resolving the rebase.

@KonstantinKo

Copy link
Copy Markdown

Just to note, I too am eagerly awaiting this PR getting merged. It also covers Claude sessions that are idle but armed to wake themselves, which the reaper can't see cause neither shows up as a background task. In my case, a scheduled wakeup (ScheduleWakeup, /loop, CronCreate; delays up to 60 min) plus the case of an MCP server channel push (notifications/claude/channel, enabled via --channels in Launch arguments). Both get stopped after 30 idle min...

Repro: T3 Code desktop, Claude provider with --channels in Launch arguments, and an MCP channel server that pushes an event ~40 min after the turn ends. Turn completed at 06:46:02 UTC; the session was stopped at 07:16:34 UTC (30.5 min, plain stopSession, no settle), so the push never arrived and the channel server's in-flight work was torn down with the session.

BTW I'd be happy to help with the test rebase if @Gigioxx has abandoned this.

@KonstantinKo

KonstantinKo commented Sep 18, 2026 •

Copy link
Copy Markdown

@Gigioxx I rebased this onto current main and moved the new cases onto the sweepAt harness: they now await the completed sweep instead of the yieldNow loop, and they fail with the exemption disabled. Your commit is unchanged apart from the rebase (no conflicts; the direct thread-shell query and the full idle window after settlement are intact).

On top of that, two separate commits you can take or drop:

  • the 3-line test change;
  • a fix for a regression the new lookup introduces: listSessions() dies on a binding mismatch, which aborts every sweep and stops reaping for all providers. An unknown live set now keeps Claude sessions and lets the sweep continue, with a regression test.

Compare against main: main...KonstantinKo:t3code:reaper-rebase-9612

Taking it is one command from your checkout:

git fetch https://github.com/KonstantinKo/t3code reaper-rebase-9612 && git push -f origin FETCH_HEAD:t3code/keep-messaging-sessions-alive

vp test run apps/server/src/provider/Layers/ProviderSessionReaper.test.ts passes 14/14; lint, fmt and the server typecheck are clean.

(Written by Claude Opus 5 for Konstantin)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Thread shows as live after the idle reaper has stopped its Claude Code process

3 participants