"Answer in under 50 ms for the common request" is in AGENTS.md and in half the issues on this board as a bullet each builder measures by hand and nobody measures again. As the pages grow tallies, filters, threads and paging, the first slow query will arrive in a pull that looks fine. Make the budget a test, so the check is what notices.
What done looks like
[ ] src/budget.test.ts seeds a database that is larger than any real group — 200 proposals, 8 options each, 1000 remarks, a full roster, ballots where they exist — through the actions, once, shared by every case in the file.
[ ] It measures the common requests against a server started in the test: /, /p/:id on the heaviest proposal, /api/proposals, /api/health. Each is warmed, then timed over enough iterations to be stable, and the median is what is asserted — never a single sample.
[ ] The budget is generous and about regression, not about the number: assert the median under a ceiling several times the target (say 150 ms) so a shared, cold, throttled CI runner does not produce a red check for an app that is fine, and print every measured median in the test output so a person reading the log sees the real numbers move.
[ ] One case asserts the shape rather than the clock: the number of SQL statements / runs does not grow with the number of proposals on it. A counter around the database in the test is enough. This is the assertion that actually catches an N+1, on any machine, at any speed.
[ ] The file says in a comment what it is for and what to do when it fails: find the query, not the threshold. Raising the ceiling is a decision with a sentence in the pull, never a quiet edit.
[ ] forge.json's check already runs bun test, so this needs no new command; the pull says how long the new file adds to a run, and it stays under a few seconds.
[ ] bun test is green, and the pull quotes the medians it measured.
Files I expect to change:src/budget.test.ts (new), AGENTS.md (one line saying the budget is a test now), possibly a shared seeding helper if one already exists in the test files.
Risks: a timing test that fails on a busy machine teaches a crew to ignore the check, which is worse than having no test — the generous ceiling and the statement-count assertion are the two halves of this, and the second is the one with teeth. Do not measure through the network stack twice by starting a server per case. If #48 lands, reuse its seeding rather than writing a second generator.
Fit: Hearth — the app's promise about speed, checked by a machine instead of by hand. A person assigns; I do not.
"Answer in under 50 ms for the common request" is in
AGENTS.mdand in half the issues on this board as a bullet each builder measures by hand and nobody measures again. As the pages grow tallies, filters, threads and paging, the first slow query will arrive in a pull that looks fine. Make the budget a test, so the check is what notices.What done looks like
src/budget.test.tsseeds a database that is larger than any real group — 200 proposals, 8 options each, 1000 remarks, a full roster, ballots where they exist — through the actions, once, shared by every case in the file./,/p/:idon the heaviest proposal,/api/proposals,/api/health. Each is warmed, then timed over enough iterations to be stable, and the median is what is asserted — never a single sample./runs does not grow with the number of proposals on it. A counter around the database in the test is enough. This is the assertion that actually catches an N+1, on any machine, at any speed.forge.json's check already runsbun test, so this needs no new command; the pull says how long the new file adds to a run, and it stays under a few seconds.bun testis green, and the pull quotes the medians it measured.Files I expect to change:
src/budget.test.ts(new),AGENTS.md(one line saying the budget is a test now), possibly a shared seeding helper if one already exists in the test files.Risks: a timing test that fails on a busy machine teaches a crew to ignore the check, which is worse than having no test — the generous ceiling and the statement-count assertion are the two halves of this, and the second is the one with teeth. Do not measure through the network stack twice by starting a server per case. If #48 lands, reuse its seeding rather than writing a second generator.
Fit: Hearth — the app's promise about speed, checked by a machine instead of by hand. A person assigns; I do not.