Farouk Fusion cinematic command hub connecting games, trading cards, AI, news, community, and playtest routes
Farouk Fusion cinematic command hub connecting games, trading cards, AI, news, community, and playtest routes

The bug that only exists at season boundaries

3 min read

The calendar pitch called this “session-vs-persist state postmortem (the cinematic-flag class of bug)”. That is exactly what it is — two real bugs from the EFER codebase, both caused by the same shape: state that is correct during a session but wrong at the moment a boundary crosses.

Bug one: the season that ends while nobody is watching

SeasonService runs the end-of-season pipeline — snapshot winners, grant badges, archive, reset all five leaderboards, broadcast — exactly once per season. The obvious implementation is wrong: check on boot “did a season end since we last ran?” and if yes, run the pipeline.

Here is why that fails. The server restarts. During the downtime, season 4 ends. On boot, the check fires — season 4 “just ended” from the service’s point of view — and the pipeline runs. Badges re-grant to winners who already have them. The boards, which were correctly reset at the actual boundary by… nothing, because no server was alive — the boards were never reset at all. Now they get reset *after* players have been grinding into the new season’s standings for however long the server was down. Early season-5 progress wiped retroactively.

The fix in the shipped code is the opposite rule: SeasonService only fires SeasonEnded for seasons that end *while it is alive*. A season that ended during downtime is already over at boot — it is never replayed. The boards might sit with last season’s numbers through the gap (acceptable, self-corrects at the next live boundary) but no player’s badges duplicate and no one’s new-season progress gets eaten.

The lesson generalizes: when a boundary can cross while the system is down, “did it cross?” is the wrong question. “Did it cross *while I was running*?” is the right one.

Bug two: the camera that stayed a prisoner

The intro cinematic needs the camera in Scriptable mode — the game drives it, player input is ignored. When the cinematic ends, something has to hand the camera back. ColdOpenBoot’s releaseCamera() exists for exactly this.

The bug class it defends against: if release never runs — an edge case in the flow, a race at the boundary, a skipped cleanup — the camera stays Scriptable forever. Player connected, game running, HUD alive, and the camera does not respond to input. From the player’s seat the game looks frozen. From the console it is silent — nothing throws, because no code path is “wrong”; a state change simply never reverted.

The AGENTS.md trap list documents the aftermath: “Camera left Scriptable in Edit — right-click orbit and WASD do nothing; Studio looks frozen but MCP still answers.” It cost a full debug session once, which is why releaseCamera now has an explicit discipline: read the previous type, restore it, and if the previous type was itself Scriptable (or nil — no usable prior state), fall back to Custom rather than trust it.

The shared shape

Both bugs live at boundaries — a season boundary, a cinematic end — where state captured for one phase must transition to the next. Neither produces an error. Both are invisible in logs. And both only manifest in the thin slice of time when the hand-off happens, which is why tests that never exercise the boundary never catch them.

The rule I now write down: any state you take, you return — and you prove the return happens. Not “the function is called” — “the state is actually back.” The green suite describes the code. Only playing describes the game.

Keep reading

Share

Agree, disagree, or caught something off? The comment form is below — I read all of them.

Farouk Fusion

Official Farouk Fusion publishing account for Eternal Fusion games, TCG updates, lore, Jester King Prime AI, store news, community posts, and project announcements.

Leave a Reply