Skip to content

[bug] Nothing reaps an idle coding session now — #271 removed the only thing that did, and the one reaper needs a human to open a tab #275

Description

@serge-ivo

Follow-up to #271, which was a good fix — this is the consequence it left open.

What changed

Before #271, coding-session.ts ended the session after every Pilot run. That was the bug (it made
delegation single-use), and the fix is right: a run now closes only the session it opened
(shouldEndSessionAfterRun({ openedByRun })).

But ending-every-run was also, accidentally, the only thing that reaped sessions. Nothing replaced
it with a deliberate policy.

What now ends a coding session

Path Trigger
routes/coding.ts:1384 the user clicks Kill
coding-session.ts:468 a run closes a session it opened
reconcileOrphanedSessions an active session the runner is not tracking, after a 3-min grace

STALE_DRIVER_MS (15 min) expires the driver claim, not the session — different thing.

There is no idle timeout. A session opened by a delegated run and then left alone stays active
indefinitely, with a live claude --dangerously-skip-permissions child process on the user's
machine.

And the one reaper is opportunistic, not scheduled

reconcileOrphanedSessions has exactly one caller — routes/coding.ts:1506, inside the sessions
listing. It runs when somebody loads the console. The cron (index.ts:206-217) runs
runDueTriggers, runDueDeliveries and runStaleRunSweep; sessions are not swept.

So for a user who delegates via chat/MCP and never opens the Coding tab — exactly the workflow #271
was built to enable — nothing reaps anything.

Why it matters

  • A persistent LLM CLI process per repo. Four repo coders under one Lead = four long-lived
    Claude Code processes, each holding a session and accumulating context, indefinitely.
  • Stale active rows. After a runner restart the rows stay active until someone opens the
    console; until then ensureActiveSession re-attaches to them (idempotent, so it mostly works) and
    connectivity reporting shows sessions that are not really there.
  • It is bounded but not small. One-active-session-per-repo caps the count at one per repo, so
    this is not unbounded growth — it is a permanent resident per repo.

Suggested shape

Decide the policy explicitly rather than inheriting the absence of one:

  • An idle timeout on sessions (last driver activity / last capture older than N), reaped by the
    cron alongside runStaleRunSweep — which already exists for precisely this class ("a row stuck at
    running forever tells every supervisor its subordinate is still working").
  • Move reconcileOrphanedSessions onto that cron too, so orphan detection does not depend on a
    human opening a tab.
  • If long-lived sessions are wanted (warm engine = faster delegation, which is a real benefit),
    then say so and make the idle window generous — but make it a decision, with the process cost
    visible in the session view.

Also: the two new modules from #271 have no tests

  • lib/coding-session-open.tsensureActiveSession + startSessionOnRunner: the create/reuse/
    race path, and the one that decides opened. No test file.
  • lib/instance-connectivity.tsruntimeConnectivity / runtimeConnectivityMany, now shared by
    the driver and supervision. No test file.

The pure classifiers are covered (subordinate-connectivity 7, coding-session-lifecycle 7). The
untested part is the orchestration, and specifically opened — get that wrong in either direction
and you either leak every session or destroy a session a human opened, which is #271 again from the
other side. The lost-race branch (catch → reuse winner → opened: false) is exactly the kind of
path that regresses silently.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions