From 52555e04552d7f622a5fd380d949d0fabec66a62 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sun, 26 Apr 2026 15:20:02 -0400 Subject: [PATCH] fix: reject empty prose on turn submit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- chat/templates/chat.html | 2 +- chat/web/turns.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/chat/templates/chat.html b/chat/templates/chat.html index 4d9d24b..8833062 100644 --- a/chat/templates/chat.html +++ b/chat/templates/chat.html @@ -26,7 +26,7 @@
- +
diff --git a/chat/web/turns.py b/chat/web/turns.py index 7a7db0e..260bb21 100644 --- a/chat/web/turns.py +++ b/chat/web/turns.py @@ -122,6 +122,9 @@ async def post_turn( conn=Depends(get_conn), client=Depends(get_llm_client), ): + if not prose.strip(): + raise HTTPException(status_code=400, detail="prose cannot be empty") + chat = get_chat(conn, chat_id) if chat is None: raise HTTPException(status_code=404, detail=f"chat not found: {chat_id}")