The fleet was in reverse
We hired a test pilot who never sleeps: an end-to-end suite that boots every theater’s real server, joins it from a real headless browser, picks a unit card, and holds the keys a player would hold. On its very first naval sortie it rang the telegraph to flank and reported the ship made 16 meters in 45 seconds. The whole fleet — every tank, every warship, for every fresh-settings player — had been driving backwards on W for two days.
Five theaters, one drill
The suite (make e2e) walks air, naval, land, combined arms,
and flight school through the loop a player actually lives: does the
join screen offer cards, does the shutter open, is the world already a
war when you arrive, does the HUD show the right gauges, does the hull
answer the helm, do rounds land on the wire when you hold the trigger,
can you die and roll back out. Every claim is checked against the
server’s own snapshots — positions from pl and
gv rows, ordnance from the bullet sections, score from the
scoreboard bytes — never against what the renderer happens to paint.
Alongside the pass/fail regressions it grades playability: seconds until a fog-of-war enemy first appears on your wire, seconds a hull sits at 0 km/h with the throttle rung up, hit points a straight-line pilot donates to bot gunnery in thirty seconds. Those report as warnings and metrics, run after run, so balance drift can’t hide behind a green build.
The catch
The naval spec’s helm probe holds W for 45 seconds and demands the hull make way. First run: 16 m traveled, top speed 0.0 m/s — and the drive slider bleeding down, 0.19→0. A second probe held S instead, and the battleship accelerated smartly to 8 m/s and kept building. S was full ahead. W was all stop. The HUD’s own recovery banner says “BACK UP (S)”.
The culprit was two days old. The
pull-back-to-climb change made the pitch keys share the
inverted-elevator flag, and inverted ships ON — so for every player
who never touched Settings, W now means “stick
forward”: kb.pitch = −1. And the hull
theaters’ drive slider was integrating kb.pitch
directly. In a cockpit that flip is the point; in a driver’s seat it
put the gearbox in reverse. No server metric could ever see it —
the server faithfully executed “astern, aye.”
The fix: a gearbox is not an elevator
The input layer now publishes a driveAxis — the raw
W/S reading, +1 ahead, −1 astern, deliberately upstream of the
elevator convention — and the drive slider consumes that instead of
kb.pitch. However a captain likes their elevator, W rings
the telegraph forward.
After: the warship logs 650 m in 45 s, top 18 m/s; the tank 908 m in 60 s at 19.6 m/s with 4 stuck-seconds crossing folds; the combined-arms respawn-into-armor drill — the one that guards the old tanks-parked-forever bug — covers 358 m in 25 s. All five theaters green.
The confession
Two, actually. The elevator change shipped with a careful headless playtest — of the air theater. Nobody re-drove a hull, because “it’s a mouse-reticle change.” The whole reason this suite now exists is that “the diff looks unrelated” is exactly the sentence that precedes a fleet sailing backwards. And second: the suite’s own first report said the ship moved 16 m but top speed 0.0 — the harness was reading the driver’s predicted velocity, which is always zero in a conning tower. It learned the same lesson it teaches: measure the hull on the wire, not the pilot in the chair.
The suite also left a warning we’ve only half-fixed: at single-digit frame rates the mouse-aim assist oscillates hard enough to auger a hands-off spawn into the dirt in about eight seconds. The control side is solved — the assist now refreshes at every input tick inside the physics loop, so a slow GPU puts the same 20 Hz command timeline on the wire as a fast one — but the probe still crashes, because the aim direction is born from the camera, and the camera trails the physics by a frame. Ten times the frame time is ten times the delay in that feedback loop, and past ~100 ms it crosses into instability. The real fix is deriving the aim from the predicted attitude instead of the rendered one — a feel change that gets its own tuning pass. Until then the warning fires on every run, with the fps printed beside it.
Flight school was hazing the students
The training sweep kept flagging one lesson: Bust the Column downed a straight-and-level student ten seconds after the briefing, every single run. The probe told the whole story in one line of events: the quad-flak half-track’s detection ring is 1100 m, and the drill spawned the student 900 m out — already inside it, first hits at three seconds, dead at seven. Worse, the run-in pointed toward the enemy base, so backing the spawn up just traded the half-track’s flak for the base’s. The fix: start the run head-on from the map-center side, 1600 m out, and stretch flight school’s spawn shield to cover reading the briefing card (the world doesn’t pause for it) — the shield drops on your first trigger pull, so the drill still has its teeth exactly when the lesson starts.
Then we handed it a phone
The suite’s second day added mobile phases: the same servers, joined again at 844×390 with a coarse pointer and real touch input. Taps join, the FIRE button and telegraph slider drive the real pointer pipeline, the hands-off autopilot latch keeps an idle spawn alive, the respawn card must come back with the scoreboard and flight HUD hidden — every fix from the mobile playability audit, frozen as a check. And the pairwise overlap guard paid for itself on its first run: in the air theater the throttle lever’s upper travel was hiding under the seven-row gauge stack — full throttle lived beneath the BMB row. One top-cap in the CSS, and the guard now stands watch over every control a thumb can reach.