{
 "page": "messages",
 "audited": "2026-11-05",
 "stamp": "20261105as1",
 "method": "Served the worktree and drove it in Chromium against the stubbed-Supabase harness (qc/d3-accept-social.spec.cjs asserts every automatable pass). 'na' = needs a table, RPC or data FedM8 does not have; the UI is left out (R9) and the entry names what it would need.",
 "criteria": [
  {
   "i": 1,
   "result": "pass",
   "evidence": "1440px with a chat open: list, chat and 'Talking with' info pane render as 3 grid columns (320/720/320)."
  },
  {
   "i": 2,
   "result": "pass",
   "evidence": "List pane has the fm-search field, All/Rooms/DMs group and rows with name, role coins, 'today'/'yesterday', preview and an unread count."
  },
  {
   "i": 3,
   "result": "pass",
   "evidence": "Open row has aria-current and the --fm-row-selected-bg cream, title weight 700; not navy."
  },
  {
   "i": 4,
   "result": "pass",
   "evidence": "With the stub reading read state after mark_dm_read, the unread badge is gone about 1.5s after a chat opens (also when opened from a link: fixed, the list now reloads after the initial open)."
  },
  {
   "i": 5,
   "result": "pass",
   "evidence": "Rooms shows only followed rooms (my_rooms_feed.following); DMs shows only list_my_conversations rows."
  },
  {
   "i": 6,
   "result": "pass",
   "evidence": "Typing 'morgan' leaves one row, Morgan Fixture."
  },
  {
   "i": 7,
   "result": "na",
   "evidence": "Messages are 1:1 dm_conversations. There is no room presence, member roster or requirement coverage, so no 'N online / M members' and no Coverage chip. Header shows name, role coins and Block; the page H1 is 'Messages' (added: the shell H1 is hidden on D3 pages).",
   "needs": "team-room messages: a room_id on conversations, member_presence per room, a members list RPC, and requirement coverage"
  },
  {
   "i": 8,
   "result": "na",
   "evidence": "No Coverage chip exists (see 7).",
   "needs": "requirement coverage RPC per room"
  },
  {
   "i": 9,
   "result": "fail",
   "evidence": "Other-user messages show name, time of day ('11:30 AM', added) and bubble; own messages are right-aligned with 'You'. No per-message avatar or RoleBadge (role shows as coins in the header).",
   "needs": "per-message avatar and role badge from the existing other.coins; small, left for the next pass"
  },
  {
   "i": 10,
   "result": "pass",
   "evidence": "'Today \u00b7 Fri, Oct 30' divider (fm-divider) is inserted when the day changes."
  },
  {
   "i": 11,
   "result": "na",
   "evidence": "No reactions for messages: talk_emoji only inserts emoji into the box.",
   "needs": "a reactions table (dm_message_id, user_id, emoji) and a toggle_dm_reaction RPC"
  },
  {
   "i": 12,
   "result": "na",
   "evidence": "dm_messages has only a text body; send_dm(p_conversation, p_body) takes no attachment, so no ContractEmbedCard in a message.",
   "needs": "dm_messages.attachment jsonb {kind:'notice', id} and a send_dm argument"
  },
  {
   "i": 13,
   "result": "na",
   "evidence": "Depends on 12: no contract embed in messages, so no urgency chip.",
   "needs": "see 12"
  },
  {
   "i": 14,
   "result": "na",
   "evidence": "No file storage for chats; no FileCard.",
   "needs": "a private storage bucket, dm_messages.file_path, signed-URL RPC"
  },
  {
   "i": 15,
   "result": "na",
   "evidence": "mark_dm_read records only my own read; list_dm_messages does not return when the other side read, so no 'Seen by'.",
   "needs": "dm_messages.read_at (or a read cursor) exposed by list_dm_messages"
  },
  {
   "i": 16,
   "result": "na",
   "evidence": "No typing channel between members.",
   "needs": "a realtime presence channel per conversation"
  },
  {
   "i": 17,
   "result": "pass",
   "evidence": "Send is disabled while the box is empty; text enables it; Enter calls send_dm and Shift+Enter makes a new line."
  },
  {
   "i": 18,
   "result": "na",
   "evidence": "No attachments (see 14).",
   "needs": "see 14"
  },
  {
   "i": 19,
   "result": "na",
   "evidence": "No contract links in messages (see 12).",
   "needs": "see 12"
  },
  {
   "i": 20,
   "result": "pass",
   "evidence": "Send is the only primary (amber) button on the page; asserted in the spec."
  },
  {
   "i": 21,
   "result": "na",
   "evidence": "1:1 chats have no roster.",
   "needs": "see 7"
  },
  {
   "i": 22,
   "result": "na",
   "evidence": "No roster, so nothing to invite (the other person is the chat).",
   "needs": "see 7"
  },
  {
   "i": 23,
   "result": "na",
   "evidence": "No requirement coverage module.",
   "needs": "see 8"
  },
  {
   "i": 24,
   "result": "na",
   "evidence": "No pending-claim data in chats.",
   "needs": "see 8"
  },
  {
   "i": 25,
   "result": "na",
   "evidence": "No pinned items; chats do not pin.",
   "needs": "dm_pins table and RPCs"
  },
  {
   "i": 26,
   "result": "pass",
   "evidence": "With no chats and no followed rooms the empty state links to Teaming (#/team-up?tab=teams); changed from the People directory."
  },
  {
   "i": 27,
   "result": "pass",
   "evidence": "No 'Sample members' text in assets/jev-dm.js or assets/chat-home.js; the rendered page has none."
  }
 ]
}