Public: anyone can read this; the crew can change it.

Pacing: the crew's concurrency and dispatch rate follow each subscription's remaining window, and a paused successor says the real reason #382

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The crew's slots now follow what each subscription has left in its windows, and a paused run says which account, which window and when it resets. The new pacing tests, the changed subscriptions, usage and autonomy tests, and `crew.test.ts` pass. I did not get a clean full `bun test`: the last full run had 13 failures and 2 errors. One of them was `crew.test.ts`, which asserted the old pause label.…

shipped production is serving it deploy 058b6cf

opened this

The crew's slots now follow what each subscription has left in its windows, and a paused run says which account, which window and when it resets. The new pacing tests, the changed subscriptions, usage and autonomy tests, and crew.test.ts pass. I did not get a clean full bun test: the last full run had 13 failures and 2 errors. One of them was crew.test.ts, which asserted the old pause label. I updated it and it now passes. The other 12 failures were in unrelated tests (Instagram, redirect, sign-in throttle, scaffold typecheck, fork flow, N+1 dashboard, resilience, fifty pushes), which I did not re-run on main. tsc --noEmit couldn't run here because the bun type definitions are missing.

What changed

  • Pacing policy: src/crew/pacing.ts is a pure function. Account standing, the operator's slots and the mean run cost go in; slots, a next-look-again time and a reason come out.

- Each account's room is its tightest window's crew-remaining dollars (cap minus the operator's headroom), counted in runs of the repository's recent mean cost (a dollar before there is any history). - Accounts add up, capped at the operator's slots. Any window with room left counts as at least one run. - An account with no known cap counts for the full ceiling, so a new account is not throttled on a guess. - At a wall, slots are 0 and the next time is the earliest reset.

  • Dispatch gate: driveRepo in src/crew/autonomy.ts gates on the paced slots. If they are 0 and nothing is in flight, it returns the new result waiting and starts nothing. The reset is the paced next-look-again time (nextAt). The loop does not use it to schedule: the next autonomy tick re-evaluates, and the run's own resumeAt handles runs that are already paused. Slots count only slot-taking runs, as before.
  • Which accounts count: the repository's own grants, otherwise its owner's, whichever agent they name. I did not copy pickSubscription's per-agent grant choice. It is grantedAccounts in src/core/subscriptions.ts.
  • Pause label: the successor of a paused run now reads paused: work's weekly window is full until 21:00 UTC; resumes …. With a rotation it reads …; <next> takes over. The provider's own words are the fallback when it names no window. The text comes from pauseReason in src/crew/pacing.ts.
  • Stickiness: I changed no code here, because the takes over path already ended the run and started a new one. test/subscriptions.test.ts now asserts that the refused run stays on its account and the successor is a different run on the other account.

Tests

  • test/pacing.test.ts has hand-worked cases covering the ceiling cap, the sliver of room, accounts adding up, a walled account beside an open one, the earliest reset, and a stale wall.
  • test/crew.test.ts now expects the new label.

Left out

  • Slots do not shrink or cancel runs already in flight when a wall nears. They only gate new starts.
  • The paced slots are not shown on the studio or crew page.
  • There is no per-agent grant resolution in pacing.

To try it Grant an account to a repository and turn autonomy on. Once the account's window is full, the repository logs waiting and a paused run's card names the account, window and reset time.

🤖 Generated with Claude Code

Closes #373

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs