Citation data model and rendering, end to end
Gadoes builds the citation pipeline from MCP tool result to UI card: a `citations` table, a parser that maps each source type's response format into the schema, SSE emission at end of turn, and a React component with compact/expanded views and RTL support for Arabic excerpts.
Backend (Chunk 4). Migration 001_citations.sql adds a citations table. The liveness_status column accepts only unchecked, live, or unreachable - the values verified and unverified are explicitly reserved in a migration comment for a later hallucination-verification feature. Keeping liveness and verification separate from the start avoids a schema migration when that feature arrives. citationParser.ts exposes parseSingleCitation() and parseMcpResultToCitations() covering all six source types. runToolCalls() accumulates citations from MCP results and passes them back; runLLMStream() emits an mcp_citations SSE event at the end of each assistant message, always - empty array when no MCP tools fired, so the frontend can reliably expect the event.
Excerpts are truncated to 500 characters before storage.
Frontend (Chunk 5). CitationCard.tsx exports three components: SingleCitationCard, CompactRow, and CitationList. The list renders up to three citations expanded; four or more collapse to a click-to-expand summary. Each card shows a coloured liveness dot, a source/region badge, and a dir=rtl attribute when the excerpt contains characters in the U+0600-U+06FF Arabic range. useAssistantChat.ts consumes the new SSE event; AssistantMessage.tsx renders the list below the message.
Chunk 5 also adds Vitest and React Testing Library to the frontend dev dependencies (22 component tests). If your fork runs Jest, reconciling the test suite is the main friction point.
The "Verify & read" button is present in this commit but stubbed - the actual verification endpoint arrives in Chunk 20.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?