Two bugs that crashed the engine in production:
1. world.nearby_agents() did not SELECT the 'personality' column, so
_reaction_turn raised KeyError on every reactive trigger, killing the
engine thread silently. Engine-Thread stieg aus ohne Log.
Fix: select personality and json-parse it so callers get a real list,
matching agents_mod.get().
2. server.py ws() handler caught the generic 'Exception' from
asyncio.to_thread(queue.get) and tried to send a ping back, but the
WebSocket was already closed by the client. Starlette raised
RuntimeError: Cannot call 'send' once a close message has been sent.
Fix: drop the ping, just break the loop on any exception. Client
disconnect now handled cleanly.
Live-verified: 0 errors in log after 3 abrupt disconnects, engine
continues producing ticks.