feat(FN-4040): add optimistic room send with failure handling and reconcili

The merge implements optimistic room send with failure recovery in the ChatView and useChatRooms hook, including a reconciliation flow that handles send failures gracefully and documents the UX behavior. The dashboard guide and architecture docs are updated to reflect the new room messaging pattern.

Fusion-Task-Id: FN-4040
This commit is contained in:
Fusion
2026-05-11 16:45:34 -07:00
committed by gsxdsm
parent 2ccf8c699d
commit a2303c67a9
7 changed files with 124 additions and 14 deletions

View File

@@ -283,7 +283,8 @@ Intentional exclusions from shared snapshots:
- Room messages persist through `POST /api/chat/rooms/:id/messages`; the route persists the user message first, then calls `ChatManager.sendRoomMessage(...)` to orchestrate room-member responders and persist assistant room replies with `chatStore.addRoomMessage(...)` (including `senderAgentId` for each responder).
- `sendRoomMessage(...)` uses existing room-member + mention resolution rules: mentioned members are direct responders, non-mentioned members are ambient responders (capped by `ROOM_AMBIENT_MAX_RESPONDERS`), and non-member mentions are handled explicitly by the manager instead of silently disappearing.
- Room-reply generation is now non-silent on failure: if a room has members but no active responders can be resolved, or all responder generations fail/return empty output, `sendRoomMessage(...)` throws `RoomReplyGenerationError` and the route surfaces HTTP 502 instead of returning a silent user-only success.
- UI does not optimistically insert room messages; `useChatRooms.sendRoomMessage()` re-fetches authoritative room messages immediately after `POST /api/chat/rooms/:id/messages` so persisted assistant replies remain visible across SSE timing gaps, then continues applying `chat:room:message:*` events for live updates.
- `useChatRooms.sendRoomMessage()` now follows direct-chat style optimistic UX: append a temporary local user room message before `POST /api/chat/rooms/:id/messages`, reconcile that temp entry to the persisted user message on success, then refresh authoritative transcript state while continuing `chat:room:message:*` live SSE updates.
- On failures, `useChatRooms.sendRoomMessage()` performs state reconciliation (rollback temp entry or replace with persisted transcript when POST partially succeeded) and rethrows; `ChatView` owns the single user-facing toast and keeps composer text for retry.
- Mention UI in rooms keeps direct-chat behavior unchanged while adding room affordances:
- `AgentMentionPopup` receives room membership context and shows members first with a `status-dot` member indicator (`aria-label="Room member"`).
- With an empty mention filter in room mode, only room members are listed; a hint row prompts the user to type to search non-members.