Skip to content

test: replace wall-clock upper bounds with the behaviour they stood for - #485

Merged
MagicalTux merged 2 commits into
masterfrom
test/no-wall-clock-bounds
Sep 29, 2026
Merged

MagicalTux merged 2 commits into
masterfrom
test/no-wall-clock-bounds

Conversation

@MagicalTux

Copy link
Copy Markdown
Member

Follow-up to #484: a sweep of the suite for elapsed < N assertions, short Promise.race deadlines and polls that give up after a few seconds. Each measured the scheduler rather than the code, and each now observes the behaviour it was written for.

Test Was Now
upstream-timeout (×4) elapsed < 2000 after a 200 ms watchdog the error message names the budget that fired (after 200ms / idle for 200ms), which is what proves the configured watchdog, not Node's default, ended the wait
upstream-timeout (disconnect) race against 200 ms await the relay settling on cancel; the runner's timeout bounds it
upstream-pool total < 3× one delay a barrier: the upstream answers only once all N requests have arrived, which serialized requests can never reach
routing-failover elapsed < 10 s the failure line names the tunnel's own 800 ms budget
server-429 elapsed < 2 s, fetch abort at 2 s the bound is a fraction of the 300 s retry window the proxy must not sleep through
config-lock-file (×3) elapsed < 1 s absence of the bypass warning: a stale/dead lock is broken, not waited out
codex-reset-credits waited < 2 s the budget reason is the evidence
mcp-tools, request-log-sweep 5 s polls event-driven / open-ended waits
activity-entries, tui-remote 5 s poll defaults 60 s watchdogs

No production code changes.

🤖 Generated with Claude Code

MagicalTux and others added 2 commits September 29, 2026 11:52
A sweep of the suite for assertions of the form `elapsed < N`, short
`Promise.race` deadlines and polls that give up after a few seconds.
Each measured the scheduler; each now observes what the code does:

- upstream-timeout: the timeout error names the budget that fired
  (`after 200ms`, `idle for 200ms`), which is the proof that the
  configured watchdog ended the wait; the disconnect test awaits the
  relay settling instead of racing it against 200 ms.
- upstream-pool: parallelism is shown by a barrier the upstream holds
  until all N requests have arrived, which serialized requests can
  never reach; no comparison against a delay.
- routing-failover: the failure line names the tunnel's own budget.
- server-429: the bound is a fraction of the 300 s retry window the
  proxy must not sleep through, not a 2 s measure of speed.
- config-lock-file: a stale or dead-holder lock is shown to be broken
  by the absence of the bypass warning, not by a sub-second write.
- codex-reset-credits: the budget reason is the evidence; the timing
  assertion is gone.
- mcp-tools, request-log-sweep: waits are event-driven or open-ended,
  bounded by the runner's timeout.
- activity-entries, tui-remote: the poll helpers' defaults are
  watchdogs (60 s), not bounds.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The remaining short deadlines: 4-5 s per-test timeouts on tests whose
point is that something does NOT wait a minute or more, a 500 ms and a
50 ms headers deadline that a slow machine trips as easily as the bug
would, and 5-10 s watchdogs on subprocess startup and socket close.
Each is now either gone (the runner's timeout is the bound) or wide
enough to be a watchdog only; the one bound that carries meaning — the
headers deadline armed at admission, not enqueue — is made
deterministic by queueing longer than the deadline itself.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@MagicalTux
MagicalTux merged commit 02458d7 into master Sep 29, 2026
5 checks passed
@MagicalTux MagicalTux mentioned this pull request Sep 29, 2026
MagicalTux added a commit that referenced this pull request Sep 29, 2026
Thirty-two commits since 1.1.21. Two change routing on an existing
config without an opt-in (#480, #481); the rest is opt-in, additive, or
display.

Behaviour changes
  #481 an API-key account's 401 is a cooldown, not a permanent `error`:
       1 min, then 5, 15 and 60 for every further rejection with no success
       in between; any 2xx/3xx resets it. The request still fails over and
       the client never sees the 401. OAuth accounts are unchanged
  #480 with session distribution on, requests carrying no session id stay
       within the top priority tier, so a fallback gateway no longer answers
       Claude Code's bootstrap and connector calls
  #470 a 200 whose SSE stream reports a provider failure before any output
       (`server_is_overloaded`, `response.failed`) fails over once, like a
       status-shaped failure would
  #465 a reload removes running accounts whose config entry is gone from
       disk, so `teamclaude remove` from another shell takes effect at once
  #460 `import` refuses an account whose token upstream has definitively
       rejected (401/403), even with `--name`; a 5xx or timeout still imports

Rename
  #483 the project is being renamed to TeamRouter (#72). This release accepts
       the new name everywhere the old one is read and changes nothing an
       install has on disk: `teamrouter` runs the same CLI, every
       `TEAMCLAUDE_*` variable is also read as `TEAMROUTER_*` (which wins when
       both are set), every `/teamclaude/…` control route also answers at
       `/teamrouter/…`, and `~/.config/teamrouter.json` is used when it exists

Features
  #441 per-account egress proxy (`accounts[].routing`: http, socks4/4a,
       socks5/5h) for refresh, probes and requests; `login --routing`,
       `teamclaude routing set/show/clear`, a connection check before it is
       relied on, and a short hold when the proxy is unreachable
  #427 `accounts[].allowExtraUsage: true` lets a paid extra-usage account
       serve once every account is past its threshold, instead of a 429
  #466 `accounts[].maxSpend`, a money cap judged against the month-to-date
       extra-usage spend upstream reports; the TUI shows what an account
       has billed
  #436 `autoRedeemResets` spends a free Codex rate-limit reset credit when
       the Codex pool runs dry (off by default)
  #482 `advisorEligibility: "strict" | "prefer"`; when the advisor model
       narrows selection to a subset of the fleet the log says so, and status
       carries the reading (`advisorNarrowing`)
  #478 `stripOverageHeaders` drops another org's per-organization billing
       headers from responses, for a pool spanning several orgs (#476)
  #471 `quota.unified5hSeenAt` / `unified7dSeenAt` in status: when upstream
       last stated each shared window
  #446 client and dimension usage for the last 5h and 24h in status and the
       dashboard, resumed across restarts
  #458 #459 #461 the dashboard sets the switch threshold, enables/disables and
       reprioritizes an account, and has a light theme remembered per browser
  #464 `l` in the TUI signs an account in `error` in again from the dashboard
  #457 status records which Codex limit meters each model
       (`quota.codexModelLimits`)
  #442 `quotaBarPercent` drops the percentage beside a TUI bar's countdown
  #451 `stripRequestFields` takes `content.<block type>` to drop content
       blocks a strict Anthropic-compatible upstream rejects
  #469 `proxy.mcp` schemas declare their item types, the write audit line
       records what happened, and the write queue has a depth (#447–#450)

Fixes
  #477 a refused WebSocket handshake whose headers all drop is relayed as a
       well-formed head instead of a blank line and body bytes
  #474 two members of one ChatGPT workspace are told apart by user id, so a
       second `login --codex` no longer replaces the first
  #469 a Codex Responses stream with no Content-Type is relayed as a stream
       and booked; thread repair on the global upstream; TUI settings and
       status gaps; a hint when a local login would have served
  #463 a Codex row with no session window draws one wide weekly bar

Tests
  #484 #485 #486 the suite asserts behaviour, not the scheduler: wall-clock
       upper bounds are gone, and subprocess tests spawn the server through
       `test-helpers/spawn-server.js`, which verifies the server it reached by
       `server.pid` (new in status) instead of trusting a port

Tooling
  #452 #453 #454 #455 docker workflow actions bumped
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