A human-maintained tracker for one recurring failure mode: a capability that took a milestone to build never reaches a demo, so it is invisible twice — it does not appear in the videos anyone evaluating the project watches, and it is never exercised by the demo drivers that would notice it breaking.
This is the mitigation ADR 0086 names for the fact that the videos are regenerated by hand and can therefore go stale. It is review discipline, not an enforced check. If it proves leaky, the ADR’s cheapest escalation is a CI check that a PR touching a client render path also touches this table.
This doc is not auto-generated, and it is not docs/client-parity.md. Parity
answers “does this client expose the capability at all?”; this answers “does a
demo actually show it, and does a driver actually walk it?” A row can be Done
in parity and not covered here.
AGENTS.md’s docs/ cross-silo exception, this file can land alongside a
change in any one silo.axon-demo-tui --scene <name> for the TUI, and for web the leading word of a
test title in clients/web/e2e/demo/{desktop,mobile}.spec.ts
(pnpm demo --grep rooms).Legend: scene name = covered · n/a = the client has no such capability
(see docs/client-parity.md) · not covered = the client has it and no demo
shows it.
| Capability | TUI (axon-demo-tui) |
Web desktop | Web mobile |
|---|---|---|---|
| Room list, with names and topics | rooms |
rooms |
rooms |
| Incoming invite inbox (Accept/Reject) | n/a | not covered — demo corpus joins invitees through the appservice, so there is no standing-invite scene | not covered |
| Room list sort (ADR 0042) | rooms |
rooms |
not covered |
| Room list filter: all / DMs / groups | rooms |
rooms |
not covered |
| Live room-name filter (Alt-/) | rooms |
rooms |
not covered |
| DM title derived from the other member | rooms |
rooms |
rooms |
| Timeline text, sender names, day separators | timeline |
timeline |
timeline |
| Formatted (HTML) messages with links | timeline |
timeline |
timeline |
| Bundled URL preview text/image cards (MSC4095) | n/a | not covered — demo corpus has no bundled preview metadata | not covered |
| Reactions (seeded badges render) | timeline |
timeline |
send |
| React to a message, then withdraw it | react |
send |
not covered |
| Custom reaction images (MSC4027) | not covered | not covered | not covered |
| Standalone sticker selection and sending | not covered | not covered | not covered |
Custom emoji packs and /react completion |
not covered | not covered | not covered |
| Reaction badge updating live from another user’s react | not covered | not covered | not covered |
| Replies | timeline |
timeline |
send |
Edits (m.replace, applied in place) |
threads |
threads |
not covered |
Redactions ([redacted] tombstone) |
threads |
threads |
not covered |
| In-timeline find (Ctrl-F, n/N) | threads |
n/a | n/a |
| Threads: open panel, read replies | threads |
threads |
threads |
| Inline images (Sixel / Kitty / iTerm2) | media |
n/a | n/a |
| Attachment card previews and downloads | n/a | not covered — no recorded attachment-preview scene | not covered |
| Full-size image preview | media |
media |
media |
| Image galleries (adjacency grouping, ADR 0081) | n/a | media |
media |
| Lightbox paging across a gallery run | n/a | media |
media |
| Upright thumbnail of an EXIF-rotated photo | not covered | not covered — no corpus photo carries an orientation tag or a sender thumbnail | not covered |
| Full-text search across rooms (Tantivy) | search |
search |
search |
Search field filters (room:, all:true) |
search |
search |
search |
| Search hit as a deep link into a room | not covered | search |
search |
| Jump to a date in history | jump |
not covered | not covered |
| Sending a message | send |
send |
send |
| Deleting one’s own message | not covered | send |
send |
| Shortcuts and help popups | shortcuts |
shortcuts |
n/a |
| Spaces: picker, filtering, hierarchy (ADR 0084) | not covered | spaces |
rooms |
| Single-pane navigation and Back (ADR 0062) | n/a | n/a | rooms |
| Room information panel | not covered | rooms |
timeline |
| User information panel | n/a | not covered — no demo scene opens a timeline sender | not covered |
| Unread thread picker (Alt-T) | not covered | not covered | not covered |
| Search result sort / group / edit toggles | not covered | not covered | not covered |
| Sending media | not covered | not covered | not covered |
| Message actions: edit, redact, reply | not covered | not covered | not covered |
| Room actions: invite, leave, pin (M19) | not covered | not covered | not covered |
| Room settings: name, topic, avatar (M19-W6, ADR 0100) | n/a | not covered | not covered |
| Device verification (SAS) | not covered | not covered — web UI exists; corpus has no second device | not covered |
| Megolm key backup snapshot and enable (ADR 0098) | not covered | not covered — /accounts is not a demo scene |
not covered |
| Matrix OAuth QR account acquisition | n/a | not covered — demo stack has no MAS or second trusted device | not covered |
| Matrix OAuth QR device authorization | n/a | not covered — demo stack has no MAS or second client to authorize | not covered |
| Matrix OAuth browser sign-in | n/a | not covered — demo stack has no MAS, and the approval happens on its page | not covered |
| Native Sign in with Apple (iOS shell, ADR 0054) | n/a | not covered — the web recordings run in a browser, not the iOS shell | not covered |
| Typing indicators and read receipts (M18) | not covered | not covered | not covered |
| Inline image whose terminal encode failed (placeholder) | not covered | n/a | n/a |
Debug overlay diagnostics (display.debug) |
not covered | n/a | n/a |
| Room list loading state during startup | not covered | not covered | not covered |
| State-event notices (ADR 0083) | not covered | not covered | not covered |
e2e/timeline-overflow.spec.ts.search scenes exercise relevance ordering only.
Server-wide newest/oldest ordering and restarting pagination when changing sort remain not covered by the recordings.search scene exercises the default ordering but does not toggle it or verify a match outside the first relevance page.
A dedicated scene should wait for the refreshed results before continuing.
Keeping an edited search form open while a pending sort refresh completes also remains uncovered.react shows the pattern the rest should
follow: script the undo as well, so the scene leaves the room as it found it
and its assertions stay honest on a second run — a react-only scene passes
vacuously the second time, on the badge the first run left behind.clients/web/e2e/popup-bounds.spec.ts exercises narrow tablet and phone layouts plus the wider mobile presentation.spaces scene demonstrates populated spaces but does not exercise empty-root hiding or restoration after a membership update.m.favourite reorder and the instance space_order rail are not shown in a scene.display.debug = true, which no scene sets. Covering the first
honestly means teaching the corpus to serve a deliberately undecodable image,
not writing a longer scene. The overlay is closer to a deliberate omission: it
is a diagnostic surface, and a demo of it would show a screen no user is meant
to see. Both are TUI-only — the web renders images natively with no encode
step (see the inline-images row) and has no equivalent overlay — hence n/a
rather than a gap.clients/tui/src/app/media.rs). The
media scenes render corpus photos, but none of the six in
smoke/local-stack/corpus/media/photos/ carries an orientation tag, and the
corpus attaches no sender thumbnail — so a scene would look identical before
and after the fix and prove nothing. Covering it honestly means adding a
tagged photo, with a stripped sideways thumbnail, to the corpus, not writing
a longer scene.timeline covers badges that were already in the aggregate at load, and react covers this client reacting to itself.
Neither exercises an m.reaction frame arriving over the WS for someone else’s reaction, which is a different code path — the frame patches the target message’s aggregate rather than being rendered as a row of its own./whereami renders cached room metadata, authoritative member counts, and the loaded /members projection (ADR 0114).
The popup can filter that loaded list from the keyboard (#656).
An open popup re-reads on reconnect, after a metadata or tombstone change or a redaction, and on a 30-second poll measured from when the previous read settled (#657).
The list is not a complete roster (#659), and no pilot scene opens the popup, so the row, the filter, and the refresh stay not covered.rooms pilot does not exercise those interactions, so coverage remains a gap until the separate testing-silo follow-up (#385).
That follow-up should also show the containing space header remaining visible while scrolling through a large group.
Exercise top-room startup, Left/Right group navigation, and pinning a focused space to the shared first position.
Also show confirmed empty spaces disappearing while loading and failed roots remain available.
Root reordering must also be demonstrated changing the web picker through the shared preference.n/a rather than a demo gap./jump has no web counterpart yet — so this is closer to a
parity gap than a demo gap; see docs/client-parity.md./createRoom does not honour a backdated ts, so the newest
event in every corpus room is the viewer’s own join; at the shipped default
every timeline would end on “Alex Marx joined the room”, which reads as a
broken client. Covering this honestly needs a corpus that ends each room on a
message, not a longer scene.In-timeline find on web. The web client has no Ctrl-F of its own; search
is the answer there, which the search scenes cover.
rooms scene shows an unnamed DM title.
Unnamed non-DM groups, live hero renames, and switching by calculated title are not covered; the corpus and driver have no such scenario.Things that are true of the clients, discovered by scripting them, and which a scene now depends on:
/room resolves room IDs, aliases, and displayed titles, including server-calculated names for unnamed rooms (ADR 0118).
The send scene still addresses the DM by ID (and waits on the showing <title> status, which names a DM by the other member); title-based switching is not covered by that driver.s sort, g
group, e edit, r reply, t thread). A command typed while it has focus is
not typed at all: it is read as that sequence of shortcuts. Esc first./createRoom does not honour a backdated ts. Anything that selects “the
last message” lands on that join, not on the last message.cells × cell size, so the pilot must know the
terminal’s true cell size in pixels. TIOCGWINSZ reports zeros on many
terminals; the answer has to come from an XTWINOPS query, which is why the
pilot asks on the child’s behalf. Guessing renders every image smaller than
the frame around it — subtle enough to reach a finished recording.U into the buffer rather than acting on the
message. The react scene uses /unreact, which acts on the selection.all:true, and one that searches for a word
living in another room finds nothing at all. Both web search scenes are
built around this rather than around it.1m → 2m). Comparing whole-row text across a scene reports a reorder that
never happened; the sort step compares href instead.a.search-hit is not.
The list auto-pages on scroll, so counting rendered hits measures where the
list happens to be scrolled to.pointerType, or the phone recording grows a desktop arrow
cursor hovering beside the finger.scrollBy rather than pretending to a gesture it is not.The web custom emoji picker is covered by clients/web/e2e/custom-emoji-picker.spec.ts, including personal and room packs, image previews, sends, withdrawals, and mobile safe-area and keyboard viewport containment in both room and thread pickers.
A recorded demo scene for pack selection remains outstanding; the existing react scene continues to demonstrate Unicode reactions.
Standalone sticker selection is covered by clients/web/e2e/stickers.spec.ts, including personal and room packs, room/thread sends, draft preservation, original image rendering, keyboard dismissal, and narrow viewport containment.
It is not yet shown in the recorded demo.
Standalone sticker shortcodes and discovery-error Unicode fallback are covered by clients/web/e2e/sticker-shortcodes.spec.ts in room and thread composers; the recorded demo does not yet show this path.
Case-insensitive sticker matching and shortcode autocomplete are covered in clients/web/e2e/sticker-shortcodes.spec.ts; no recorded demo scene covers them yet.
Bundled link images are covered by clients/web/e2e/link-preview-images.spec.ts in room and thread/caption timelines, with plain and encrypted descriptors, authenticated downloads, stable loading geometry, text/error fallback, transient-failure retry/reconnect, large plain-source thumbnails, and hostile URL/encrypted-dimension rejection.
Run the chromium and webkit-iphone projects for desktop and phone geometry evidence.
The recorded demo remains uncovered because the corpus has no bundled-preview events; image cards do not imply preview authoring, automatic generation, or native sharing support.
Attachment card layout and activation are covered by clients/web/e2e/attachment-cards.spec.ts in room and thread timelines on desktop Chromium and iPhone/WebKit.
The checks cover full-width caption geometry, top-right 44-pixel download targets, on-demand preview dialogs, keyboard dismissal/focus restoration, independent caption links/downloads/spoilers, desktop text selection without message actions, and swipe/hold arbitration for file, audio, video, and PDF cards.
Viewer download errors remaining visible on the card after close have component-test coverage; native image/gallery taps with double-tap disabled are covered by clients/web/e2e/message-gestures.spec.ts on iPhone/WebKit.
The existing media recording still demonstrates image galleries; a recorded audio/text/PDF/video attachment-card scene remains outstanding.