Intent.AGENTS.md states the bar — little JavaScript, a first paint that is server-rendered HTML, no dependency without a reason, a page in milliseconds — and nothing checks it. Turn the bar into a test, now, while the numbers are small and the budget is easy to meet.
Done looks like
[ ] src/budget.test.ts (new), one file, no dependency, that fails with a message naming the number that moved.
[ ] Dependencies:package.json has no dependencies and no devDependencies; if one is ever added the test fails and the pull that added it says why in README.md. (Today it has none — record that.)
[ ] Weight: the whole of static/ is under a stated budget, and each of CSS and JS separately. Record what they are today (about 4.7 KB of CSS and 2.1 KB of JS on main) and set the budget a little above what the app actually needs, not an order of magnitude above.
[ ] The page: every route in the routes.ts table that answers HTML is fetched against a served instance and asserted to be complete HTML on the first byte — no route that renders an empty shell for JavaScript to fill — and under a stated size.
[ ] Speed: each of those routes is measured warm and asserted under 50 ms, with the measurement printed so a reader sees the margin rather than a bare pass. Say in the test's comment that this is one machine and a rough guard, not a benchmark.
[ ] No inline script: no HTML response contains a <script> with a body — the CSP already forbids it, and this catches it before the browser does.
[ ] The test discovers routes from routes.ts rather than listing them, so a page added by #12, #15, #21 or #29 is covered the day it lands without anyone remembering to add it.
Filessrc/budget.test.ts (new), README.md, AGENTS.md (one line pointing the bar at the test that keeps it).
Risks A flaky timing test is worse than none: measure warm, take a median of several, keep the threshold well clear of the real number, and skip the timing assertions when the environment says it is under load rather than failing a pull for someone else's noise. Several pulls are open on routes.ts and static/ — this file only reads them.
Brief that fits @scout — small, fast, correct, and it keeps the rest honest. (A person assigns.)
Intent.
AGENTS.mdstates the bar — little JavaScript, a first paint that is server-rendered HTML, no dependency without a reason, a page in milliseconds — and nothing checks it. Turn the bar into a test, now, while the numbers are small and the budget is easy to meet.Done looks like
src/budget.test.ts(new), one file, no dependency, that fails with a message naming the number that moved.package.jsonhas nodependenciesand nodevDependencies; if one is ever added the test fails and the pull that added it says why inREADME.md. (Today it has none — record that.)static/is under a stated budget, and each of CSS and JS separately. Record what they are today (about 4.7 KB of CSS and 2.1 KB of JS onmain) and set the budget a little above what the app actually needs, not an order of magnitude above.routes.tstable that answers HTML is fetched against a served instance and asserted to be complete HTML on the first byte — no route that renders an empty shell for JavaScript to fill — and under a stated size.<script>with a body — the CSP already forbids it, and this catches it before the browser does.routes.tsrather than listing them, so a page added by #12, #15, #21 or #29 is covered the day it lands without anyone remembering to add it.Files
src/budget.test.ts(new),README.md,AGENTS.md(one line pointing the bar at the test that keeps it).Risks A flaky timing test is worse than none: measure warm, take a median of several, keep the threshold well clear of the real number, and skip the timing assertions when the environment says it is under load rather than failing a pull for someone else's noise. Several pulls are open on
routes.tsandstatic/— this file only reads them.Brief that fits @scout — small, fast, correct, and it keeps the rest honest. (A person assigns.)