Skip to content

fix(server): promote Claude account revive queue and rebalance to bkmain (#322) - #323

Closed
bk-agent-01 wants to merge 4 commits into
bkmainfrom
fix/claude-account-rotation-bkmain
Closed

bk-agent-01 wants to merge 4 commits into
bkmainfrom
fix/claude-account-rotation-bkmain

Conversation

@bk-agent-01

Copy link
Copy Markdown
Collaborator

Summary

This PR promotes the Claude account server fix from #322 (merged into stage as fd41ddad) to bkmain. It contains only the 4 commits of #322, cherry-picked onto origin/bkmain, so it carries none of the other stage-only merges (#317, #319, #320).

Production still shows the problem from 2026-10-16. A limit hit can leave a thread on a full account with a stale "All Claude accounts are at their limit" banner while other accounts have room. At 17:0x UTC, a production thread hit the barsha 5-hour limit, and a person had to change its account by hand.

Area Change
Hard-limit path A rejection that did not move the thread does not stay in the duplicate filter. Every new turn forgets old keys.
Notices Notices expire at their reset. The "all full" text is built live from the queue.
Revive queue (migration 1053) A thread that no account can take is parked, and continued in waves as accounts get room. The 5-minute reset wait is a queue entry and survives a restart.
Rebalance After a real turn end, an idle Auto thread on an account 2 or more sessions over its fair share moves, at most once an hour and one thread per account per status read.
Contracts and web ThreadClaudeAccount.wait, the claudeAccounts.leaveQueue RPC, and "Leave queue" in the picker.

The new switcher (bk-docs #1143, space-share-v2) is already live on dev-server-1 and supplies fair_share and recoveries.

How I tested

  • CI runs on this head. The same 4 commits were green on fix(server): Claude accounts revive waiting threads after resets and spread load #322 at 34d6ad4b5e (all jobs except the Blacksmith artifact job, which never starts in this fork). Two fresh-context code reviews found no open bug.
  • stagebkt3 serves fd41ddad. No limit event happened on stage after the deploy, so production is the first real check. After the deploy, I read the claude.account.* lines (place-none, revived, rebalance, hard-limit) of the next production limit event.

Risks and rollback

  • The merge restarts production BkT3, which stops every live session.
  • Migration 1053 only adds nullable columns to thread_claude_account. Older code ignores them.
  • Rollback: Revert this PR on bkmain.

🤖 Generated with Claude Code (Claude Opus 5.5, T3 Code)

bk-agent-01 and others added 4 commits October 17, 2026 08:21
…spread load

- A failed hard-limit move no longer leaves the rejection in the duplicate
  filter, so a new turn's rejection moves the thread (2026-10-16: a thread
  stayed on `sam` for 20 min while `tushar` had room).
- Limit notices expire at their reset; the "all accounts are at their limit"
  notice is derived live from a durable revive queue (migration 1053).
- A thread no account can take is parked and continued in waves as accounts
  reset (revive pass after every status poll); the 5-minute reset wait is now
  a queue entry, so a restart no longer loses it.
- Auto threads move off an account over its fair share at turn boundaries,
  at most once an hour.
- New claudeAccounts.leaveQueue RPC and a "Leave queue" item in the picker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…alance

- A revive checks it still owns the queue entry before it moves or continues
  the thread, so Leave queue / a user message during placement wins.
- The duplicate filter forgets a condition after a successful move and when the
  first turn on the new account starts.
- Rebalance runs only at a real turn end, pre-checks the last status before
  asking the switcher, backs off 5 min after a probe finds nowhere better,
  moves at most one thread per source account per status read, and writes
  only the row so the old session keeps its own attribution.
- Parking no longer forks a revive pass; archived threads leave the queue;
  a passed reset time is no longer shown as expected.
- Test counts for the new RPC (237) and migration 1053; formatting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…very turn start forgets stale limit keys

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…turn in flight

The provider-level idle check also counted the failed turn that parked the
thread, so a mid-turn thread never got its continue. Test for the race.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Oct 17, 2026
@bk-agent-01

Copy link
Copy Markdown
Collaborator Author

Closed on Tushar's instruction (2026-10-17): promote the full stage branch to bkmain instead of these 4 cherry-picked commits. A stage → bkmain PR replaces this one.

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

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant