52555e0455
Empty submission was producing a blank user_turn event in the log and firing the LLM stream anyway — the bot would invent a response from the kickoff context alone, producing a monologue with no user input. Two- layer fix: - Browser: add `required` to the prose textarea in chat.html so the form refuses to submit empty. - Server: 400 in post_turn when prose.strip() is empty. Defense in depth — if a client bypasses the textarea attribute (custom UI, curl, etc.), the server still rejects. Verified live: POST with empty body returns 400; POST with whitespace- only returns 400; chat shell renders the textarea with required. Full suite: 168 passed.