Skip to content

feat(sessions): a rate-limited pool queues a run instead of crashing it (v0.448.0) - #835

Merged
vikasprogrammer merged 2 commits into
mainfrom
feat/limited-pool-defer
Sep 18, 2026
Merged

vikasprogrammer merged 2 commits into
mainfrom
feat/limited-pool-defer

Conversation

@vikasprogrammer

Copy link
Copy Markdown
Owner

What

A launch that only lacks a free runtime account is parked as queued and started by the 60s sweep once an account resets, instead of being refused and reported as a crash.

Why

instawp, 2026-09-17: 21 of the tenant's last 22 crashed sessions were not crashes. Both pool accounts hit their 5-hour session limit within an hour of each other, a third was at its weekly cap and a fourth was disabled, so rotation had nothing to hand out and every launch fell through to the box default ~/.claude — a login that had never been used and holds no tokens at all (expiresAt: 0). The pre-flight refused each run (correctly — it could not authenticate) and reported it as crashed, with a card telling an admin to re-login a credential that was not the problem. The accounts that were the problem reset themselves within the hour. Two humans re-clicked take-over and got the same card twice.

What changed

  • Capacity queue (TerminalManager): every account limited with a reset time + an unusable fallback → status queued, audited session.launch.queued, owner card naming the reset (“…at 14:14 UTC (in about 40 min)”). retryCapacityQueue() runs from the process-wide 60s sweep and launches it when rotation can serve it (session.launch.dequeued, card resolved).
  • Bounded, never silent. Past 6h the wait gives up and crashes with the original credential reason (session.launch.queue.expired) — a weekly cap can't hide a run forever. A queued row with no spec in memory (a restart mid-wait) is reported to its owner, not left waiting.
  • Unchanged where it should be. A pool that is empty, all-disabled, or parked with no recorded reset still refuses exactly as before: no moment to retry at is not a queue.
  • Console: queued is a session status — own dot, tooltip, filter. Stop calls off a wait; attach 409s with "has not started yet".
  • Fix: expiresAt: 0 no longer renders as "expired on 1970-01-01" on cards and admin alerts.

Testing

  • New scripts/capacity-queue-test.cjs (35 assertions), wired into npm run test:governance.
  • npm run typecheck, cd web && npm run build, full npm run test:governance — all green.

🤖 Generated with Claude Code

vikasprogrammer and others added 2 commits September 18, 2026 10:40
…it (v0.448.0)

When every runtime account is limited, rotation falls through to the box's own
login — which on most boxes has never been used and holds no tokens — so the
launch pre-flight refused the run and reported a crashed session. On live
instawp 21 of the last 22 `crashed` sessions were this: each card told an admin
to re-login a credential that was not the problem, while the accounts that were
reset themselves within the hour, and two humans re-clicked take-over into the
same card.

A temporary exhaustion (every account limited, with a reset time) now parks the
launch as `queued` and the 60s sweep launches it when an account frees up. A
pool with no moment to retry at — empty, or all disabled — still refuses as
before; a wait past 6h gives up with the original credential reason so a weekly
cap cannot hide a run forever; a `queued` row left by a restart is reported, not
left waiting. Stop calls off a wait; attach says the run has not started.

Also: `expiresAt: 0` is a record with no tokens, not a date — it no longer
renders as "expired on 1970-01-01" on cards and admin alerts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vikasprogrammer
vikasprogrammer merged commit bb33109 into main Sep 18, 2026
1 check passed
@vikasprogrammer
vikasprogrammer deleted the feat/limited-pool-defer branch September 18, 2026 05:14
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.

1 participant