AGENTS.md states the 1000-line ceiling is "enforced across Desktop, Web,
and Mobile by the repository-level `just file-size-check` gate", but the
desktop and web rule tables listed only `.ts`/`.tsx` for their script
roots, and `runFileSizeCheck` skips any file whose extension is not in
its rule's allowlist. Desktop's suite is `*.test.mjs` by convention and
its shared test rigs are plain `.mjs` modules, so 545 files inside roots
the ratchet already governs were outside the ceiling -- silently, since
an uncovered file makes the check exit 0 just like a clean one.
Found when review caught a 1253-line test file on #6720 that every local
gate and CI had passed. Refs #6726.
The gap and the fix, on a clean main checkout: a new 1501-line `.mjs`
under `src/features` exited 0 before this change, and byte-identical
content named `.ts` exited 1.
Adding the extension needs no splits, because the gate is a ratchet
rather than an absolute bound -- `allowedLineCount` returns `baseLines`
when the base file already exceeds the max. Verified against all twelve
oversize files at once: rewriting each without changing its line count
exits 0, and adding a single line to each exits 1 naming all twelve with
their inherited limits. New files are still held to 1000 from birth.
The rule tables move into `file-size-rules.mjs` so the tests can assert
the configuration the runners actually execute rather than a restatement
of it. The runners stay unconditional: a module that both exports its
rules and self-guards its execution can silently stop gating, which is
the same failure class this change exists to close.
Three tests, each proven non-vacuous by reverting the thing it covers in
isolation:
mutation fails
desktop table back to .ts/.tsx all 3
web table back to .ts/.tsx the allowlist test alone
grandfathering -> always maxLines the 2 inherited-size tests
The two behavioural tests drive the real rule table against throwaway
repositories in a child process, so a leaked `process.exitCode` cannot
mark the suite failed. Node exits 1 for an uncaught exception as well as
for a violation, so a failing child must also print the violation report
to count as one -- otherwise a broken harness would read as a passing
gate, which is the same trap again. That guard is itself covered: a bad
rules import fails with "crashed rather than gated" instead of passing.
Signed-off-by: ss-dev-01 <11939edb7df583f855dbef923f2358f1184538f88ca452e19e7e35e42ad6d796@buzz.block.builderlab.xyz>
Co-authored-by: Bradley Axen <baxen@squareup.com>
Signed-off-by: Bradley Axen <baxen@squareup.com>
## Summary
- replace the whole-tree file-size gate with a stateless differential
ratchet
- allow inherited files over 1,000 lines to hold or shrink, but never
grow
- delete the 44-entry numeric override ledger and run the same policy
across Desktop, Web, and Mobile CI
- fail closed when the local base cannot be resolved and cover policy,
Git status parsing, and base resolution in unit tests
This removes the shared mutable policy state that caused unrelated PRs
to fail after neighboring merges. It does **not** by itself prevent two
stale green PRs from becoming invalid when combined; that requires merge
queue or up-to-date branch enforcement.
### Related issue
None found. This follows the design discussion in the linked Buzz
channel.
### Testing
- `node --test scripts/check-file-sizes-core.test.mjs` (6/6)
- Desktop, Web, and Mobile ratchet entrypoints
- `just desktop-check`
- `just web-check`
- Mobile analysis
- `git diff --check`
The repository pre-push suite also exposed an unrelated existing Mobile
widget failure in `ChannelDetailPage keeps follow mode off while a tall
newest message stays visible`; it reproduces in isolation and this
branch does not touch Mobile widget behavior.
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>