fix(ui): /ask loading state, safer RAG prompt, quieter Q&A, slash-hint + composer polish (LC-676) #636

Merged
longjacksonle merged 1 commit from fix/LC-676-ask-loading-rag-composer into main 2026-08-04 20:44:03 +02:00

Implements LC-676 (see the investigation comment on the ticket for root causes + the #2 proposal).

1. Loading state (the visible bug)

/ask ran the LLM synchronously and only posted the answer when done, so the UI froze for seconds with no feedback. handle_ask now posts a "The assistant is thinking..." placeholder as the bot and broadcasts it immediately, then runs the LLM and replaces that message's body in place (new silent db::chat::replace_message_body - no edit history, no "(edited)" marker) and re-broadcasts MessageEdited. No spawn; the asker sees the assistant working at once and the bubble resolves to the answer.

2. RAG answer quality + safety phrasing (the proposed, safe part)

The /ask system prompt was strict context-only, so out-of-room questions dead-ended and a harmful ask was phrased as a retrieval miss ("could not find information on making bombs in this room"), wrongly implying it would answer if the room had it. The prompt now (a) makes a no-context outcome helpful and explicit that it would not have answered anyway, and (b) refuses harmful/dangerous/unsafe requests on SAFETY grounds, never as a retrieval miss.

Deliberately NOT changed: a general-knowledge fallback (answer from the model's own knowledge, labelled "not from this room"). That changes the RAG-only contract - flagged in the ticket for your sign-off. Say the word and I'll add it.

3. Repetitive Q&A rendering

The asked-question is now a quiet single-line quote (> name: question) above the answer instead of a heavy > **name asked:** question blockquote, so consecutive exchanges read cleanly and stay subordinate to the answer.

4. Lingering slash hint

On a successful send the composer re-focuses the textarea, so the slash popover's blur-close never fired and the hint hung until an outside click. The slash clear is now exposed (window.__lcClearSlash) and called on send success, like __lcClearAttach.

5. Composer height

Trimmed the input's vertical padding (0.5rem -> 0.375rem) on the shared .lc-mdback/.lc-mdinput rule so the empty/single-line composer is compact while the LC-399 overlay metrics stay identical (highlight stays aligned).

Tests

  • Prompt unit test pins the helpful-no-context + safety-refusal intent.
  • /ask integration test asserts the answer replaces the placeholder in place (one message, no "thinking" left behind) with the quiet quote.
  • routes_assistant, routes_slash (17), fmt, clippy, i18n_catalog green.
  • The composer height (#5) and the loading/Q&A visuals want a staging eyeball - they can't be verified headlessly.

🤖 Generated with Claude Code

https://claude.ai/code/session_013pGppokMfgq5W46EY2Takg

Implements LC-676 (see the investigation comment on the ticket for root causes + the #2 proposal). ## 1. Loading state (the visible bug) `/ask` ran the LLM synchronously and only posted the answer when done, so the UI froze for seconds with no feedback. `handle_ask` now posts a "The assistant is thinking..." placeholder as the bot and broadcasts it immediately, then runs the LLM and replaces that message's body in place (new silent `db::chat::replace_message_body` - no edit history, no "(edited)" marker) and re-broadcasts `MessageEdited`. No spawn; the asker sees the assistant working at once and the bubble resolves to the answer. ## 2. RAG answer quality + safety phrasing (the proposed, safe part) The `/ask` system prompt was strict context-only, so out-of-room questions dead-ended and a harmful ask was phrased as a retrieval miss ("could not find information on making bombs in this room"), wrongly implying it would answer if the room had it. The prompt now (a) makes a no-context outcome helpful and explicit that it would not have answered anyway, and (b) refuses harmful/dangerous/unsafe requests on SAFETY grounds, never as a retrieval miss. **Deliberately NOT changed:** a general-knowledge fallback (answer from the model's own knowledge, labelled "not from this room"). That changes the RAG-only contract - flagged in the ticket for your sign-off. Say the word and I'll add it. ## 3. Repetitive Q&A rendering The asked-question is now a quiet single-line quote (`> name: question`) above the answer instead of a heavy `> **name asked:** question` blockquote, so consecutive exchanges read cleanly and stay subordinate to the answer. ## 4. Lingering slash hint On a successful send the composer re-focuses the textarea, so the slash popover's blur-close never fired and the hint hung until an outside click. The slash clear is now exposed (`window.__lcClearSlash`) and called on send success, like `__lcClearAttach`. ## 5. Composer height Trimmed the input's vertical padding (0.5rem -> 0.375rem) on the shared `.lc-mdback`/`.lc-mdinput` rule so the empty/single-line composer is compact while the LC-399 overlay metrics stay identical (highlight stays aligned). ## Tests - Prompt unit test pins the helpful-no-context + safety-refusal intent. - `/ask` integration test asserts the answer replaces the placeholder in place (one message, no "thinking" left behind) with the quiet quote. - `routes_assistant`, `routes_slash` (17), fmt, clippy, i18n_catalog green. - The composer height (#5) and the loading/Q&A visuals want a staging eyeball - they can't be verified headlessly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_013pGppokMfgq5W46EY2Takg
fix(ui): /ask loading state, safer RAG prompt, quieter Q&A, slash-hint + composer polish (LC-676)
All checks were successful
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / TruffleHog (push) Successful in 6s
check-secrets / Kingfisher (push) Successful in 9s
check-secrets / Nosey parker (pull_request) Successful in 4s
check-secrets / Kingfisher (pull_request) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 5s
Check / clippy + fmt + tests (pull_request) Successful in 6m2s
Create release / Create release from merged PR (pull_request) Has been skipped
09426e6dda
Five fixes to the /ask room assistant and the composer.

1. Loading state (the visible bug). /ask ran the LLM synchronously and only posted the answer when done, so the UI froze for seconds with no feedback. handle_ask now posts a "The assistant is thinking..." placeholder as the bot and broadcasts it immediately, then runs the LLM and replaces that message's body in place (a new silent db::chat::replace_message_body - no edit history, no "(edited)" marker) and re-broadcasts MessageEdited. No spawn; the asker sees the assistant working at once and the bubble resolves to the answer.

2. RAG answer quality + safety phrasing. The /ask system prompt was strict context-only, so out-of-room questions dead-ended and a harmful ask was phrased as a retrieval miss ("could not find information on making bombs in this room"), implying it would answer if the room had it. The prompt now (a) makes a no-context outcome helpful and explicit that it would not have answered anyway, and (b) refuses harmful/dangerous/unsafe requests on SAFETY grounds, never as a retrieval miss. The RAG-only contract is kept; a general-knowledge fallback is deliberately NOT added (flagged in the ticket for sign-off).

3. Repetitive Q&A rendering. The asked-question is now a quiet single-line quote ("> name: question") above the answer instead of a heavy "> **name asked:** question" blockquote, so consecutive exchanges read cleanly and stay subordinate to the answer.

4. Lingering slash hint. On a successful send the composer re-focuses the textarea, so the slash popover's blur-close never fired and the hint hung until an outside click. The slash clear is now exposed (window.__lcClearSlash) and called on send success, like __lcClearAttach.

5. Composer height. Trimmed the input's vertical padding (0.5rem -> 0.375rem) on the shared .lc-mdback/.lc-mdinput rule so the empty/single-line composer is compact while the LC-399 overlay metrics stay identical (highlight stays aligned).

Tests: the prompt unit test pins the helpful-no-context + safety-refusal intent; the /ask integration test asserts the answer replaces the placeholder in place (one message, no "thinking" left behind) with the quiet quote. routes_assistant, routes_slash (17), fmt, clippy, i18n green. Composer height + the Q&A/loading visuals want a staging eyeball.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013pGppokMfgq5W46EY2Takg
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-08-04 20:39:15 +02:00
longjacksonle deleted branch fix/LC-676-ask-loading-rag-composer 2026-08-04 20:44:03 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!636
No description provided.