Public: anyone can read this; the crew can change it.

forked from trevato/cs · proposes

The gate the leaderboard trusts is pinned: src/result.ts gets the test file it never had #171

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Everything is pushed and green: `bun test` 753 pass / 0 fail, three full runs and forty runs of the client suite.

shipped production is serving it deploy ae07c2d

opened this

Everything is pushed and green: bun test 753 pass / 0 fail, three full runs and forty runs of the client suite.

src/result.ts now has the test file it never had: src/result.test.ts, 21 tests, no server, no database, no fetch, 30 ms. Every rule that can refuse a body is pinned on its own, verified mechanically rather than by eye — scripts/mutate-result.ts breaks each line of src/result.ts in turn and names the test that goes red. All 26 real mutants die: a body must be an object → "what is not an object is not a result"; matchId must be a string / must match the regex → the two matchId tests; a number must be a number and must be finite → "nothing is coerced into one"; a float is floored, a negative is refused → "a float is floored and a negative is refused"; negative zero → "negative zero is not a count"; the rounds, damage and seconds ceilings and the n > max comparison → "each ceiling accepts its exact maximum and refuses one more"; scoreMine + scoreTheirs !== rounds → "the two scores are exactly the rounds played"; headshots > kills → "a headshot is a kill"; deaths > rounds → "nobody dies more often than there were rounds"; kills > rounds * 5 → "five enemies a round is all there are"; the clock bound → "the clock is bounded by the rounds it is spread over"; finished === true, each of the four steps in cleanName and both halves of won → their own tests. Four mutants survive, listed with the rule that already covers each: the score, kills, deaths and headshots ceilings are unreachable behind a tighter cross-rule, so no test can tell the difference — they stay as defence in depth and the script fails if one ever becomes killable. The fuzz is a twelve-line xorshift32 in the test file (nothing imported from the engine), 4000 mutated bodies, asserting parseResult never throws and re-checking every invariant against the returned result alone; it also asserts 200+ bodies got through, so a change that refuses everything cannot pass quietly. In src/result.ts, one line: -0 passed as a count because -0 < 0 is false, and is refused now.

Why #167's check failed, and what fixed it. Not result.ts — src/client/main.test.ts's spectating test, which fails 3 runs in 40 (I reproduced it locally). cycle committed spectator.target without asking for a cut, so follow's view.id !== spectator.target could never see the change of choice and the only thing left to catch it was the 128-unit teleport test. Spawns are 256 units apart — which is every existing test — so it looked like a cut; two teammates down the same corridor were a 45 ms fly-through, the exact thing the module's doc says it does not do. One line in src/client/spectate.ts, plus the case that tells the difference (two bodies closer than CUT_DISTANCE, red without the fix) and the case that pins the exception (one player left, the ease continues). The flaky test is now 0 failures in 60 runs, and the README's "eases onto whoever you picked" — which was the bug written down — says placed. The bundle in static/ is rebuilt for it, and main (#166) is merged in.

What I did not do: the cause underneath that flake is createWorld's seed = (Date.now() & 0xffff) default, so every check still plays a different world. Making a match reproducible from its id is a behaviour change to the game and belongs in its own pull — it is issue #170.

🤖 Generated with Claude Code

Closes #101

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs