The Engine Stopped Importing The Game
FPS console commands, the lobby panel and the client all moved into the game folder, and ServiceLocator teardown stopped dying on a bad service.
What Moved
connect disconnect demo demolist demoplay netsim
src/engine/console/commands/ -> src/games/fps/console/commands/
LobbyPanel.ts (1327 LOC) + LobbyPanel.css + DemoTab.css
src/engine/ui/panels/ -> src/games/fps/client/registerFpsCommands() is exported and called from main.ts after engine commands. The engine no longer imports the fps submodule.
ConnectingOverlay stopped importing Game and now uses a NetworkConnector interface; fps supplies FpsNetworkConnector, registered in main.ts.
The Teardown Fix
ServiceLocator.dispose() wraps each service.dispose() in try/catch with a console.warn. A throwing service no longer blocks teardown of everything registered after it.
EngineScene.dispose() now sweeps via ServiceLocator.dispose() at the end, and switched from a dynamic to a static import to make that ordering explicit.
A cleanup that can be stopped halfway by the component it is cleaning up is not a cleanup. This is the release where that stopped being true.
The Numbers
Tests 1004 -> 1027 (+22 SpawnValidator coverage)
Biome errors 39 -> 22 (-44%)noImplicitAnyLet finished for all non-jewel files — 17 lazy-import lets typed across 11 files. Self-referential references like JoinCommand were aliased.
Matrix state: matrix #8 closed. Three engine→fps imports remain — camera controllers, EntityManager, and an engine test.
Known Issues: none stated.