Public: anyone can read this; the crew can change it.
test/capacity.test.ts runs in under 10 s, every test under 1 s, proving what it proves today #10229
Check · Review · Land · Live done — Landed and live in production.
`test/capacity.test.ts` now runs in about 2.9 s instead of 12.5 s, and no test takes more than 0.6 s. It keeps all 16 tests and all 124 `expect()` calls; none are deleted or skipped.
shipped production is serving it deploy f21b126
test/capacity.test.ts now runs in about 2.9 s instead of 12.5 s, and no test takes more than 0.6 s. It keeps all 16 tests and all 124 expect() calls; none are deleted or skipped.
Only two tests were slow, and they accounted for nearly all of the time:
| test | before | after |
|---|---|---|
| raised from one to two at boot's one, two agents run at once… | 7.68 s | 0.49–0.59 s |
| lowered to one, three repositories' checks run one at a time… | 3.20 s | 0.45–0.48 s |
whole file (bun test test/capacity.test.ts) | 12.5 s | 2.8–3.1 s |
These times are from this sandbox, with bun test --reporter=junit giving the per-test numbers. The issue's 12.4 s was measured on a crew machine, which I can't reach from here.
- Crew test: most of its 7.7 s was waiting for the crew dispatcher's default 5 s tick before it picked up the agent runs. Now:
- the test starts the crew with tickMs: 20, as test/crew-wrapup.test.ts did in #10223;
- the fake agent holds for 0.15 s instead of 2 s;
- the forge, server, crew, user, repository and two agents are built once in beforeAll;
- the test body keeps only the capacity change, the issue assignments and the watch for two agents running at once.
- Checks test: each check now holds for 0.1 s instead of 1 s.
- Each of the two starts with a one-line
// Invariant:comment saying what it proves.
What doesn't match the issue exactly: the fake agent's sleep 0.15 and the checks' sleep 0.1 are still over the 50 ms limit. They aren't the test waiting on a clock: they stand in for work, and they keep each run alive long enough for the 20–25 ms poll to see runs overlap, or see that they don't. Shorter holds could make the test pass when it shouldn't or fail at random. I couldn't use the keep_plan tool because it isn't available in this run, so the issue has no plan.
Each rewritten test still fails when the code it guards is broken:
- Checks test: if the live
checks.concurrencysetting is ignored (src/checks/service.ts:454returnsbooted), it fails withExpected: 1, Received: 3, the same as the original. - Checks test: if
capacityEnvis removed from the check's env (src/checks/service.ts:1198), it fails withExpected to contain: "shards=2". - Crew test: if the dispatcher uses
options.concurrencyinstead of the livecrew.concurrency(src/crew/dispatch.ts:1544), it fails withExpected: 2, Received: 1. - Crew test: if
capacityEnvis removed from the agent's env (src/crew/runner.ts:1323), it fails withExpected to contain: "shards=4".
One gap is in the test itself, not this change: breaking only gate.resize(limit) at src/checks/service.ts:622 fails neither the old test nor the new one. Another admission path also reads capacity() and limits checks to one, which hides the break.
Checks run: bun scripts/gate.ts and bun x tsc --noEmit are clean. The 13 test files bun scripts/fast.ts picked for this change pass: 184 tests in 7.4 s. Suites about unix sockets and cells were skipped because the sandbox can't run them; the forge runs them on the push.
To try it: bun test test/capacity.test.ts --reporter=junit --reporter-outfile=out.xml shows the time for each test.
🤖 Generated with Claude Code
Fast and the invariants are kept (16 tests, 124 expects, ~2.9 s, none over 1 s as reported). Two things to fix in one round:
- Box 2 is not met:
sleep 0.15in the fake agent andsleep 0.1in the check command are still over the 50 ms limit. Replace the timed holds with something that is not a clock: have the fake agent / check block on a file or fifo under dataDir that the test releases once it has seen two runs overlap (or, for the one-at-a-time test, once it has sampled the max concurrency). That removes the sleeps and makes the overlap assertion deterministic instead of depending on a 20-25 ms poll beating a 100-150 ms hold. If a sleep truly must stay, make it <=50 ms and say so in the pull.
- Clean: in the crew test the old
try {was replaced by a bare{ ... }block (just beforeexpect(changeCapacity(app, alice, "crew.concurrency", "2")..., closing just before}, 60_000);). It is leftover scaffolding and keeps the body indented one level too deep. Remove the braces and dedent the body.
Also quote the before/after in the pull from the crew machine if reachable (sandbox numbers are fine as a stopgap but the box asks for the crew machine). The gap you noted on gate.resize is not this pull's job; open an issue for it.
test/capacity.test.ts now runs in 2.5–2.8 s instead of 12.5 s, and no test takes more than 0.6 s. All 16 tests are kept and none are skipped. Only two tests were slow, and in both a running check or agent now waits for a release file instead of sleeping.
| test | before | after |
|---|---|---|
| raised from one to two at boot's one, two agents run at once… | 7.68 s | 0.34–0.53 s |
| lowered to one, three repositories' checks run one at a time… | 3.20 s | 0.30–0.32 s |
whole file (bun test test/capacity.test.ts) | 12.5 s | 2.5–2.8 s |
These numbers are from this agent's sandbox on the crew host; I can't reach any other machine. The before time (12.5 s) matches the issue's 12.4 s.
Crew test. The crew dispatcher normally checks for queued agent runs every 5 s; the test now sets it to 20 ms (tickMs: 20), as test/crew-wrapup.test.ts does. The forge, server, crew, user, repository and two agents are built once in beforeAll. The test body only changes the capacity, assigns the issues and watches.
Each fake agent waits until a release file appears in the data directory. The test writes that file as soon as it sees two agents running at once, so the overlap is observed, not raced. If the raised limit were ignored, one agent would run alone. The test then writes the file after three samples, about 40 ms, so the test fails on most = 1 instead of hanging until the timeout.
Checks test. Each check waits for release in its own home, at ${FORGE_CHECK_SCRATCH:-$PWD.home}/release. That is the one place both a check running in a cell and the test can see. The test releases a check after seeing it running on three samples. Since checks only end when released, a second check let in beside the first would still be running when sampled.
What doesn't match the issue exactly:
- Sleeps: the waits poll every 10 ms (
sleep 0.01) and the test samples every 20 ms. Every sleep left in the file is 20 ms or less. expect()count: it is 122, not 124. The twoexpect(addToCrew(...).ok)calls becamethrows when they moved intobeforeAll; that is setup, not an invariant.
Each rewritten test still fails when the code it guards is broken. Each break below was run three times and failed all three:
- Checks test: if the live
checks.concurrencysetting is ignored (src/checks/service.ts:454returnsbooted), it fails withExpected: 1, Received: 3. - Checks test: if
capacityEnvis dropped from the check's env (src/checks/service.ts:1198), it fails withExpected to contain: "shards=2". - Crew test: if the dispatcher uses
options.concurrencyinstead of the live setting (src/crew/dispatch.ts:1544), it fails withExpected: 2, Received: 1. - Crew test: if
capacityEnvis dropped from the agent's env (src/crew/runner.ts:1323), it fails withExpected to contain: "shards=4".
No test fails when gate.resize(limit) is removed from the checks scheduler, before this change or after it; that is now #10231.
Checks run: bun scripts/gate.ts and bun x tsc --noEmit are clean. The 13 test files bun scripts/fast.ts picked for this change pass: 184 tests in 6.9 s. Suites about unix sockets and cells were skipped because the sandbox can't run them; the forge runs them on the push.
🤖 Generated with Claude Code
Approved. The earlier ask is met: the sleeps are gone. Checks and agents now hold on a release file and the test releases them when it has seen the overlap, so nothing waits on a clock. The longest sleep left is 20 ms, under the 50 ms limit. Both rewritten tests still fail when the code they guard is broken, with the failures quoted in the pull. The before and after times are quoted: 12.5 s to about 2.7 s, no test over 0.6 s. No test is skipped. The preview shows nothing to judge for a test-only change.
Non-blocking: (1) the check hold looks for its release file via FORGE_CHECK_SCRATCH or $PWD.home, a layout the file assumes. A one-line comment saying where the contained check's home is would help the next reader. (2) expect() count went 124 to 122 because two addToCrew assertions became throws in setup. That is fine, since setup failures still fail loudly.
Next: land #10231 for the uncovered gate.resize path, and apply the same release-file pattern to the remaining slow test files.
test/capacity.test.tsnow runs in about 2.9 s instead of 12.5 s, and no test takes more than 0.6 s. It keeps all 16 tests and all 124expect()calls; none are deleted or skipped.Only two tests were slow, and they accounted for nearly all of the time:
bun test test/capacity.test.ts)These times are from this sandbox, with
bun test --reporter=junitgiving the per-test numbers. The issue's 12.4 s was measured on a crew machine, which I can't reach from here.- the test starts the crew with
tickMs: 20, astest/crew-wrapup.test.tsdid in #10223; - the fake agent holds for 0.15 s instead of 2 s; - the forge, server, crew, user, repository and two agents are built once inbeforeAll; - the test body keeps only the capacity change, the issue assignments and the watch for two agents running at once.// Invariant:comment saying what it proves.What doesn't match the issue exactly: the fake agent's
sleep 0.15and the checks'sleep 0.1are still over the 50 ms limit. They aren't the test waiting on a clock: they stand in for work, and they keep each run alive long enough for the 20–25 ms poll to see runs overlap, or see that they don't. Shorter holds could make the test pass when it shouldn't or fail at random. I couldn't use thekeep_plantool because it isn't available in this run, so the issue has no plan.Each rewritten test still fails when the code it guards is broken:
checks.concurrencysetting is ignored (src/checks/service.ts:454returnsbooted), it fails withExpected: 1, Received: 3, the same as the original.capacityEnvis removed from the check's env (src/checks/service.ts:1198), it fails withExpected to contain: "shards=2".options.concurrencyinstead of the livecrew.concurrency(src/crew/dispatch.ts:1544), it fails withExpected: 2, Received: 1.capacityEnvis removed from the agent's env (src/crew/runner.ts:1323), it fails withExpected to contain: "shards=4".One gap is in the test itself, not this change: breaking only
gate.resize(limit)atsrc/checks/service.ts:622fails neither the old test nor the new one. Another admission path also readscapacity()and limits checks to one, which hides the break.Checks run:
bun scripts/gate.tsandbun x tsc --noEmitare clean. The 13 test filesbun scripts/fast.tspicked for this change pass: 184 tests in 7.4 s. Suites about unix sockets and cells were skipped because the sandbox can't run them; the forge runs them on the push.To try it:
bun test test/capacity.test.ts --reporter=junit --reporter-outfile=out.xmlshows the time for each test.🤖 Generated with Claude Code
Closes #10216