Make conversation mutations visible in v2-primary and fix two send-path state bugs (rebuild W4-A)#145
Make conversation mutations visible in v2-primary and fix two send-path state bugs (rebuild W4-A)#145MaxGhenis wants to merge 1 commit into
Conversation
…th state bugs (rebuild W4-A)
Mute, mentions-only, favorite, and archive-tab were legacy-store-only writes
that v2-primary reads never observed (silent no-op in the UI). They now
dual-write: legacy first, then the v2 conversations row, then an SSE
conversations publish. v2 failures surface as 500s; a conversation with no
v2 row yet (legacy-only creation paths) mutates legacy and skips the v2 leg
with a debug log rather than failing forever.
- v2 repo setters for notification_mode / is_favorite / archived_at_ms
(schema 0002 already carried the columns; archive maps tab=="archive" to
archived_at_ms, other tabs clear it; custom tabs stay legacy-only).
- Handler id resolution is O(1) via the v2 row's RemoteConversationID (the
migration's natural key) instead of a capped legacy scan, with the
legacy->v2 account map completed for gchat-archive/imessage-archive —
previously any mutation on an imported Google Chat or iMessage thread
500'd in primary.
- v2read serves archived as the legacy-compatible tab field; primary
mutation responses return the v2 projection, and the frontend patch path
treats legacy ids as aliases so a response can never mint a duplicate
mixed-id conversation entry.
- Two real product bugs found by the primary e2e lane and browser
instrumentation, both fixed at the source:
1) Mutation responses could insert a conversation-list entry keyed by the
wrong id family, so the next thread open fetched a different id than
the DOM was rendered from.
2) The optimistic queued bubble derived its platform label from mutable
conversation-list metadata; a patched entry whose source_platform
differed from the thread's message DTOs flipped every message's
render signature (single-source -> mixed-source), causing the keyed
reconciler to replace all thread nodes on send. The bubble now derives
its platform from the rendered messages' own field, and the canonical
google-bridge label remains "sms" everywhere (matching the legacy
schema, the R5 parity pins, and live installs).
- e2e: the four attribute-mutation specs are un-fixmed (header and context
menu paths, unweakened); the favorites spec cleans up its durable
favorites; the stable-thread-node helper tags the newest message so
legitimate tail-window eviction of old messages cannot masquerade as a
reconciliation bug.
d81a7bd to
f61cc51
Compare
|
Updated with the unread-count work (delta review's blocking find: v2-primary had rendered zero unread badges since R8 because v2read hardcoded UnreadCount:0). Now computed for real from v2 read_cursors (batched, no N+1) and wired through /api/mark-read end-to-end; the e2e fixture overlays that were false-greening it are deleted. Mentions-only is honestly re-fixmed (v2 messages schema has no mention column; migration drops the legacy flag — PRIMARY REGRESSION noted for a schema-bearing Wave-4 follow-up). Local gates: full Playwright 94 passed / 0 failed / 6 skipped; Go |
Rebuild W4-A — conversation mutations in primary + two real bug finds
First Wave-4 PR (spec: wave4-primary-parity-spec-2026-07-18). Mute / mentions-only / favorite / archive now dual-write (legacy → v2 → SSE publish) so primary reads see them; 4 e2e specs un-fixmed unweakened.
Review + probe findings fixed
-archiveaccounts). Fixed via O(1) resolve on the v2 row'sRemoteConversationID— no more capped legacy scans.showMixedSourceChips→ every thread message's render signature changed → the keyed reconciler replaced all nodes on send. Captured live: signature diffsingle-source→mixed-sourceat the exact removal. Bubble now derives platform from the rendered messages' field; canonical google-bridge label stays "sms" (legacy schema + R5 parity pins + live installs).Verification
GOWORK=off go test -race ./...: 32/32, exit 0🤖 Generated with Claude Code