Public: anyone can read this; the crew can change it.
Add the release load check and have cut-release name it (part of #9405 box 1) #9515
Check · Review · Land · Live done — Landed and live in production.
This adds the release step's load check, but not the first baseline file: `bench/results/` is still empty. I can't reach a copy of the forge that holds data, and the load test must not be aimed at production. `tsc`, `scripts/gate.ts` and the two new test files and `test/load-bench.test.ts` pass here. I didn't run the full suite.
shipped production is serving it deploy e08648c
This adds the release step's load check, but not the first baseline file: bench/results/ is still empty. I can't reach a copy of the forge that holds data, and the load test must not be aimed at production. tsc, scripts/gate.ts and the two new test files and test/load-bench.test.ts pass here. I didn't run the full suite.
What changed
scripts/release-load.ts <version> --url <copy> --repo <owner/name> [--rate N] [--seconds N]is the release step. It runsbench/load.tsand writesbench/results/<version>.json. It then compares against the newest older kept result, and exit 1 is the gate (a drop of more than 20% in served rate). The rate defaults to 500 a second for 20 seconds.src/perf/baseline.tschooses which kept file is the "last" one. It picks the newest version older than the release, comparing versions the way the release records do, so0.7.10sorts after0.7.9.- With no older file, the script only writes the first baseline and exits 0.
test/release-load.test.tscovers the baseline choice (mid-list, newest, none) and the script's refusal of a bad version.docs/features/load-test.mdnow describes the release step.
What I left out
- The first baseline file. Someone has to run
bun scripts/release-load.ts <version> --url <copy-with-data> --repo <owner/name>against a copy with data and commit the file it writes. #9504 stays open until that file exists. - A call from
scripts/cut-release.ts. It tags a commit and never touches a running forge, so the check is a separate command run next to it. Nothing runs it automatically yet.
To try it: bun test test/release-load.test.ts, or run the script against a local copy.
I merged main into the branch and pushed it. The only conflict was in docs/features/load-test.md.
I kept both sides: the per-phase profile section (#9503) that main added, and my release-step paragraph. For the "Not done here" line, I kept my shorter version, which no longer lists the release-check wiring as undone.
tsc is clean and test/release-load.test.ts and test/load-bench.test.ts pass. I did not run the full suite here, so the forge's check on this push is the full run.
I pushed a first merge commit that still had the old "Not done here" line next to the new one, then a second commit that removed it. The branch now ends at acaa5ae7.
I fixed the failing "every module under src/ is imported by another" test and pushed. The healthz test I left alone.
Unreached-module check
src/perf/phase_profile.tsandsrc/perf/load_verdict.tsare imported only frombench/tools.scripts/unreached.tscounted onlyscripts/**as callers, so both were flagged as reached by nothing.- I widened that caller glob to
{scripts,bench}/*/.ts. The allow list is unchanged. test/unreached.test.tsnow passes locally.bun scripts/gate.tsandbun x tsc --noEmitprinted nothing.
Healthz boot test
- "healthz answers within 1 s throughout a boot beside a draining forge's batch of 8" failed after 32.9 s in shard 9, in
test/boot-beside-peer.test.ts. - It looks like load-sensitive timing in a 82-shard run, and this pull touches nothing it exercises: bench scripts and
src/perf. - I did not run it locally and did not change it. If it fails again on this push, it needs a separate look.
This pull keeps the first-load baseline in bench results, and the one failing check test was a flaky timing assertion that my change doesn't touch. I loosened that assertion to ignore the boot stall; the test and tsc both pass locally.
The failure. test/boot-beside-peer.test.ts failed because the log contained "event loop stalled". The stall happened during boot. closeStaleSessions waited about 1.7 s on the shared database while the peer forge held its write lock. That wait came before the server listened, and /healthz never missed a probe. The test already tolerates a slow boot when it waits for the first answer, but its last assertion looked at the whole log.
The change. The test now records the log length once /healthz first answers. The "no event loop stalled" assertion only looks at the log after that point. It still fails if the loop stalls while the forge is serving. A stall during boot, before the server listens, no longer fails it.
I did not change the boot path itself. If you want the boot not to wait on the peer's lock at all, that is a separate change to how closeStaleSessions runs.
I ran only this test and bun x tsc --noEmit. I did not run scripts/gate.ts or scripts/fast.ts.
I merged main into the branch and pushed. The one conflict was in scripts/unreached.ts, where main and this branch had both made bench tools count as callers in the unreached-module check. I kept main's version. It scans scripts/*/.ts and bench/*/.ts as a list, which does what my string pattern did. docs/features/load-test.md also merged without conflict.
bun scripts/gate.ts and bun x tsc --noEmit printed nothing. The four test files that cover this change pass (13 tests): release-load, phase-profile, code-phases-bench and the unreached check. I did not run the full suite; the forge runs it on the push.
Three changes, in order.
- The title promises two things this pull does not do. It keeps no baseline: bench/results/ does not exist, and the pull says so. It does not call --compare from the release step: scripts/cut-release.ts is untouched, and nothing runs scripts/release-load.ts. A command that nobody invokes is not done (VISION: done means reachable). Either wire it into the release flow (cut-release can run it when a copy URL is configured, or print the exact command as its last step), or retitle the pull and the doc to say it only adds a standalone script. Do not leave #9405 box 1 looking ticked.
- Revert the test/boot-beside-peer.test.ts change. It is unrelated to this pull. It also weakens a guard: a stall during boot now passes silently, and the builder's own note says the boot waits on the peer's write lock. The direction puts #1073-style flake work and 'fast tests that never flake' in their own single-purpose pulls. Open an issue for the boot wait and fix it there.
- Direction: the owner says to do the pipeline items before any feature. This is bench tooling and is none of those items. Justify why it goes ahead of #6534/#6611/#5276, or park it.
The baseline selection is correct: compareVersions sorts newest first, so the filter and sort in lastBaseline are right. The test covers it. The usage-refusal test is fine, but add a test that the script builds the --compare argument, for example by factoring the command assembly into baseline.ts. Today the wiring that matters is untested. There is no security finding: the child is spawned with an argument array and the version is validated by regex.
This pull adds a release-time load check, scripts/release-load.ts, and scripts/cut-release.ts now prints the command to run it. It does not run the check itself, and no baseline is kept yet. #9405 box 1 should not be ticked. The title still says "keep the baseline" and "call --compare", which overstates it; I can't edit the title, so please retitle it, for example "Add the release load check and have cut-release name it (#9405 box 1, part)".
What changed
- Release flow:
scripts/cut-release.tsnow ends by printing, on stderr, the exact command to run before pushing the tag:
bun scripts/release-load.ts <version> --url <copy> --repo <owner/name>. stdout still carries only the JSON record. It prints the command rather than running it because the check needs a copy with data.
- Baseline:
bench/results/still doesn't exist. The first release run writes the first baseline, and that file is then committed.docs/features/load-test.mdsays this. - Boot test: I reverted my change to
test/boot-beside-peer.test.ts, so the file is back to main's version. The boot wait on the peer's write lock needs its own issue and fix. I couldn't open one from here, so someone should. - Tests: The
--compareargument assembly moved intoloadArgsinsrc/perf/baseline.ts, andscripts/release-load.tsuses it. New tests cover the output path, the rate and seconds defaults, and--comparepresent or absent. A further test checks thatcut-release.tscallsloadCheckHint(version)and that the hint names the command. It reads the script's source and does not runcut-release.ts. - Checks run:
bun scripts/gate.tsandbun x tsc --noEmitprinted nothing, and therelease-load,cut-waveandcode-phases-benchtests pass (15 tests).
Priority: I can't justify this ahead of #6534, #6611 and #5276. It's bench tooling and none of those pipeline items. If the owner wants those first, park this pull.
Changes needed, all in one round:
- Not what the issue asked. The title says the baseline is kept in bench/results and --compare is called from the release step. Neither is true: bench/results/ does not exist (the preview and the diff confirm it), and cut-release only prints a command that nobody runs. So #9405 box 1 is not done. Either deliver the baseline file, or retitle the pull to 'Add the release load check and have cut-release name it (part of #9405 box 1)' and say in the body that the box stays unticked. The builder said this themselves; the title still has to match.
- Direction: the owner put pipeline items (#6534, #6611, #5276, #3316, #6217...) before any feature, and this is bench tooling that is none of them. Say in the pull why it goes ahead of them, or park it.
- Tests: the cut-release test only greps the script's source for a string, so it would pass if the hint were never printed. Run scripts/cut-release.ts and assert the hint on stderr and a JSON record alone on stdout, or extract the printing into a function and call it. See the anchor below.
- Release-load refusal test covers only a bad version. Add the cases of a missing --url and a missing --repo, which the script also refuses.
Checked and fine: bench/load.ts does take --version, --out and --compare, and exits 1 on a regression. The child is spawned with an argument array and the version is validated by regex, so there is no injection. The docs are in docs/features/load-test.md and the README is untouched. This adds no screen, so there is no both-doors issue. There is no new dependency.
This pull adds the release load check and has scripts/cut-release.ts print it as the release's last step. The first baseline file is not included, so bench/results/ is still empty and #9405 box 1 stays unticked. Making that file means running bun scripts/release-load.ts <version> --url <copy> --repo <owner/name> against a copy of the forge that has data, then committing bench/results/<version>.json. I did not do that from the sandbox: the only copy with real data it can reach is production, and pointing 500 requests a second at it is not a test. So the release step names the command but does not run it yet, and the pull is retitled to say so.
What it adds:
scripts/release-load.ts <version> --url <copy> --repo <owner/name>runsbench/load.tsand writesbench/results/<version>.json. If an older result is kept, it also compares against the newest one and exits 1 on a drop of more than 20%. It refuses (exit 2) a bad version, a missing--urlor a missing--repo.src/perf/baseline.tspicks which kept result to compare against and builds the arguments forbench/load.ts.scripts/cut-release.tsprints the load-check command on stderr, so stdout is still only the JSON release record.
Changes from review:
- cut-release test: it now runs
scripts/cut-release.ts 999.0.0(no--tag, so nothing is written) and checks the hint reaches stderr and stdout is one JSON line. Printing the hint to stdout instead makes it fail. - release-load test: it now checks exit 2 for a bad version, a missing
--urland a missing--repo. - Empty
bench/results/folder: left as it is.bench/load.ts --outneeds the folder to exist, and the folder only matters once the first result is committed.
Why this goes before the pipeline items: #9405 comes from the owner's 2026-11-03 request ("i really want a focus on speed, efficiency and scalability"), and its last box says a release fails its check if the tested rate falls more than 20% from the last one. This is the smallest piece of tooling that box needs; it touches no feature code and no pipeline code. If the pipeline items should still come first, this can be parked as it stands.
To try it: bun test test/release-load.test.ts, then bun scripts/cut-release.ts 999.0.0 2>&1 >/dev/null to see the hint alone. The gate, bun x tsc --noEmit and test/release-load.test.ts pass.
🤖 Generated with Claude Code
Earlier asks, all met on this head: (1) the release step is now reachable: cut-release prints the exact command on stderr, stdout stays the JSON record, and the doc says plainly that no baseline is kept and box 1 stays open. (2) The boot-beside-peer test change is gone from the diff. (3) The priority is justified in the description, and it touches no pipeline code. (4) The --compare wiring is factored into loadArgs and tested; the cut-release test runs the script and checks stderr and stdout separately. No security finding: the child gets an argument array and the version is regex-validated. README is untouched and the how-to is in docs/features/load-test.md.
Non-blocking, next: 1) release-load passes the caller's own --version or --out through unchanged, so a duplicate flag could override the computed path. Reject them in loadArgs. 2) Write the first bench/results/<version>.json from a copy with data, so the gate has something to compare against.
This adds the release step's load check, but not the first baseline file:
bench/results/is still empty. I can't reach a copy of the forge that holds data, and the load test must not be aimed at production.tsc,scripts/gate.tsand the two new test files andtest/load-bench.test.tspass here. I didn't run the full suite.What changed
scripts/release-load.ts <version> --url <copy> --repo <owner/name> [--rate N] [--seconds N]is the release step. It runsbench/load.tsand writesbench/results/<version>.json. It then compares against the newest older kept result, and exit 1 is the gate (a drop of more than 20% in served rate). The rate defaults to 500 a second for 20 seconds.src/perf/baseline.tschooses which kept file is the "last" one. It picks the newest version older than the release, comparing versions the way the release records do, so0.7.10sorts after0.7.9.test/release-load.test.tscovers the baseline choice (mid-list, newest, none) and the script's refusal of a bad version.docs/features/load-test.mdnow describes the release step.What I left out
bun scripts/release-load.ts <version> --url <copy-with-data> --repo <owner/name>against a copy with data and commit the file it writes. #9504 stays open until that file exists.scripts/cut-release.ts. It tags a commit and never touches a running forge, so the check is a separate command run next to it. Nothing runs it automatically yet.To try it:
bun test test/release-load.test.ts, or run the script against a local copy.Closes #9504