Both handler loops caught all exceptions, printed e, and broke — hiding
errors entirely. Let exceptions propagate naturally; the parent handler's
FIRST_COMPLETED logic already handles task cleanup on disconnect.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tqxrk8uj4M3w3d3eXm3xK8
- ws/message.py, ws/server/ws_server_multi_user.py: drop the loop= kwarg
and replace asyncio.wait(coroutines) with asyncio.gather(), both of
which were removed/forbidden in Python 3.10+.
- brewpi/requirements.txt: pin websockets==10.4, the latest version that
still supports this code's serve()/handler API.
- config.json.sim: move Model to the top level and add the missing gain
field so it matches the schema brewpi.py and config.json.templ expect.
- brewpi/brewpi.py: add -c/-m/-s/-d CLI args for selecting config/model
files, simulation mode, and debug.
- .gitignore: exclude __pycache__, logs, the local config.json, and
editor/venv directories.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>