Skip to content

Preserve rich content across client edits - #165

Merged
wesbillman merged 7 commits into
mainfrom
zmarley/bot-1939-rich-content-compat
Sep 24, 2026
Merged

wesbillman merged 7 commits into
mainfrom
zmarley/bot-1939-rich-content-compat

Conversation

@zrmarley

@zrmarley zrmarley commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Adds a bounded cross-client rich-content compatibility matrix for old/new message shapes using synthetic in-memory events.
  • Preserves attachment metadata on receive by folding authorized edit imeta when present, while preserving original attachments for historical/text-only edits that carry no imeta.
  • Limits the implementation to the relay service edit/receive fold path; it does not add outgoing message-edit UI/caller support.
  • Documents current main behavior, not branch-added features: spoiler markup renders literally/no reveal interaction; kind 40008 diff rows are not admitted into channel timelines.

Latest head update

  • Fresh head: 56dcae7c5358d53c77d1a97272474a27891af6a6.
  • Retains the reviewed fixture compatibility adjustment and upstream main fixes.
  • This remains limited to mechanical harness compatibility for the current rich editor / ProseMirror test fixtures, including required onOpenLink wiring, incidental space-query setup, and Escape handling. It does not weaken assertions.
  • Kept existing video controls, review layout, and error fallback behavior intact. No real media/assets/binary fixtures added.
  • Exact-head hosted CI completed successfully for 56dcae7c5358d53c77d1a97272474a27891af6a6: https://github.com/block/buzz-app/actions/runs/36026504636

Validation

  • bin/pnpm exec tsc --noEmit --pretty false
  • bin/pnpm exec vitest run src/features/relay/cross-client.test.ts src/features/relay/fold.test.ts src/features/relay/outbox.test.ts src/features/relay/traffic.integration.test.ts (4 files, 121 tests)
  • bin/pnpm exec biome check src/features/relay/cross-client.test.ts src/features/relay/fold.ts src/features/relay/messages.ts docs/channels.md
  • git diff --check
  • Previous full validation at 1b21453f: passed.
  • Exact main-baseline comparison recorded before the fixture compatibility commit: same 3-file browser failure on main and branch (22 failing assertions / 315 errors), then branch passed after the reviewed fixture-only compatibility adjustment.
  • Pre-push hook on push to 56dcae7c5358d53c77d1a97272474a27891af6a6: TypeScript + related unit tests (80 files, 1256 tests) and design-system guards passed.
  • DCO Check passed for 56dcae7c5358d53c77d1a97272474a27891af6a6.
  • User-reported manual old-client → new-client receive verification passed for the bounded receive/fold path on an older head only; this was not independently reproduced by the agent or re-run on 56dcae7c5358d53c77d1a97272474a27891af6a6.

Review notes

  • Automated refreshed-diff/general review passed for the fresh head.
  • Slopaganda Panda review verdict after fix loop: 2/10 smell, no blockers.
  • No spoiler reveal UI or kind 40008 diff renderer added; those remain documented follow-ups/current main behavior.
  • No outgoing message-edit UI/caller support added, and the dev broker does not advertise kind 40003.
  • Fresh actual-component render illustration for 56dcae7c5358d53c77d1a97272474a27891af6a6 is linked in Preserve rich content across client edits #165 (comment). Scope: real MessageRow/AttachmentImage render from foldMessages receive/fold behavior only; it is not edit UI, outgoing broker, or send proof. The illustration uses synthetic caption/artwork and a generic profile, with external requests blocked, and was privacy-inspected. Historical earlier-head capture remains in Preserve rich content across client edits #165 (comment).

Linear: BOT-1939

Signed-off-by: Zach Marley <zmarley@squareup.com>
@zrmarley

zrmarley commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Correction: the images previously attached here were hand-built HTML/CSS mockups, not screenshots of the actual application or its component fixtures at the cited commit. The previous fixture/head evidence claim was incorrect. Those mockups do not satisfy the PR screenshot requirement and have been removed from this comment. Genuine isolated app/component-fixture screenshots are still required before readiness. No live user data was used.

@zrmarley

Copy link
Copy Markdown
Contributor Author

🤖 Genuine replacement capture at b4f444b. Actual MessageRow and AttachmentImage rendered from foldMessages(original kind 9 plus authorized kind 40003 edit). Receive/render illustration only: no edit UI or outgoing broker capability is shown or claimed.

Mounted real PR components/styles in an isolated fixture with synthetic data and generic fictional profiles; no hand-built replacement UI. I visually inspected this image: no real identities, conversations, keys, credentials, private URLs or local paths are displayed. Inline synthetic artwork only; no live app/media capture. No production edits or commits. This replaces the invalid mockup previously posted.

Actual PR165 components with synthetic fixture data

@zrmarley
zrmarley marked this pull request as ready for review September 24, 2026 01:59
@zrmarley
zrmarley requested review from a team, comp615 and wesbillman as code owners September 24, 2026 01:59

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

No actionable defect found in the bounded receive/fold change at b4f444b7179ce24583aad7c9de6243693fc0ba89.

Reviewed the four-file PR delta from merge-base 60ed428b016ea67cfadbff03c56b812990e170a9, with guidance and relevant integration checked against pinned base 5677876408ad1e9920c64f3ab7f583bcf1e8e6a4. The latest authorized edit’s imeta supplies attachment metadata; an edit without it preserves original imeta. Markdown attachments remain part of the replacement body. Shared receive/render paths and the service-level edit helper were traced, with an independent compatibility pass.

Existing exact-head CI and DCO passed; Windows native validation was skipped. This review was source-only, with no builds, tests, or live workflow executed. Actual legacy-client wire compatibility and integrated producer-to-consumer, thread/40002, multi-edit and incremental-refold attachment coverage remain validation gaps; synthetic fold fixtures do not establish them. Outgoing edit UI/broker capability, spoiler reveal, and kind 40008 rendering remain explicit non-goals.

GitHub currently reports merge conflicts; resolve against the target branch and validate the resulting head. This comment is not an approval or a mergeability certification.

@zrmarley
zrmarley marked this pull request as draft September 24, 2026 13:58
…-content-compat

* origin/main: (38 commits)
  Fix diff content fallback, keyboard scrolling and edit selection (#205)
  Standardize form controls and field feedback across Buzz (#174)
  Keep image review downloads and external opens distinct (#144)
  Verify media review comments (#166)
  Follow system appearance (#210)
  Add rich composer formatting and spoiler rendering (#203)
  feat: show roster-backed channels and managed instances in profiles (#188)
  Add new direct message flow (#156)
  Remove Home, start in Messages, and keep Channels enabled (#194)
  fix: restore avatar presence controls and active-input sensing (#198)
  Add legacy diff messages with inline and expanded viewing (#202)
  Edit the latest own message with Up in the existing composer (#192)
  Add complete reaction toggles to the message menu (#185)
  feat: add persistent community navigation rail (#191)
  test: add margin to warm-switch performance gate (#195)
  Add composer attachments and compatible media preparation (#183)
  Add reply and copying to the shared message menu (#182)
  fix: avoid idle workspace re-renders from activity and label churn (#186)
  feat: add devtools trace capture to web profiling (#180)
  Add optional channel templates, teams and personal group defaults (#181)
  ...

Signed-off-by: Zach Marley <zmarley@squareup.com>

# Conflicts:
#	docs/channels.md
Signed-off-by: Zach Marley <zmarley@squareup.com>
Signed-off-by: Zach Marley <zmarley@squareup.com>
Signed-off-by: Zach Marley <zmarley@squareup.com>
…-content-compat

* origin/main:
  Add Messages design gallery and tighten message layout (#158)

Signed-off-by: Zach Marley <zmarley@squareup.com>

# Conflicts:
#	src/features/direct-messages/NewMessage.recovery.test.tsx
@zrmarley

Copy link
Copy Markdown
Contributor Author

🤖 Fresh actual-component illustration at 56dcae7: real MessageRow/AttachmentImage rendered from foldMessages(original kind 9 plus authorized kind 40003 edit). Isolated Vite configFile:false/envFile:false, fresh Chromium context, synthetic caption/artwork and generic Sender profile; external requests blocked. Visually privacy-inspected. This is receive/render illustration, not a new live edit/publication trace. Prior user manual receive-direction pass remains historical. Exact-head CI/DCO green and refreshed-diff review PASS.

Actual folded edited message retaining synthetic image attachment

@zrmarley
zrmarley marked this pull request as ready for review September 24, 2026 16:35

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Changes requested: one P2 attachment-state round-trip defect, detailed inline. Fix both receive fallback and outgoing re-edit metadata, with a multi-edit regression test.

  • Reviewed head 56dcae7c5358d53c77d1a97272474a27891af6a6 against merge-base e02fe33220fa497a2e7ee780c8295517b4f967fa; also inspected integration with current main f6caa83f724253ca11fb83481e7b60f091b4cf7a. The synthetic merge is clean and preserves main’s MessageComposer, RichComposerInput, and useMessageEdit unchanged. No separate regression found in rich serialization, mentions, paste/send, spoiler/diff rendering, or DM recovery within the reviewed changes.
  • Existing hosted CI is green for this head; Windows native validation was skipped. This review was source-only, with independent composer and fold review lanes. No local tests, live cross-client workflow, or runtime validation of the synthetic latest-main merge was performed. The added tests exercise single edits, not the failing re-edit sequence.
  • Non-blocking: the PR description still describes edit UI/broker support, spoiler reveal, and diff admission as unavailable, although they exist in this head. Please refresh that narrative; it is not the reason for requesting changes.

Comment thread src/features/relay/messages.ts Outdated
tags: [
["h", channelId],
["e", messageId],
...original.tags.filter((tag) => tag[0] === "imeta"),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Preserve the current attachment state when re-editing

After an authorized cross-client edit replaces attachment A with B, this PR correctly displays B. But changing only the caption in buzz-app publishes A’s original imeta here: session.ts:1136–1142 supplies the immutable original event to find, while useMessageEdit loads the latest folded sourceContent. The next fold therefore restores A. If the body retains ![image](B), parseAttachments also extracts B, so the message now displays both the obsolete A and a metadata-stripped B. This is reachable through the existing ArrowUp edit UI, including thread/media-review composers; adding attachments in this UI is not required.

There is a second entry into the same state-loss defect at fold.ts:257–260: original A → authorized edit with B imeta → later text-only edit without imeta falls straight back to A instead of retaining B.

Use the current authorized attachment state consistently for receive fallback and outgoing text edits; copying the original tags is only correct before any attachment-bearing edit. Add a three-event regression covering both a later no-imeta edit and a real session/composer re-edit, asserting the final folded attachments as well as published tags. An incremental arrival should preserve the same result. This does not require changing the pre-existing ambiguity around explicitly removing all attachments.

Signed-off-by: Carl <32a2e2c9d428ee08902cab75d956da2c1d235a22d4766b0dd4138bf6e2e5db1d@buzz.block.builderlab.xyz>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Approved at 3cf27245c1d6d763a357dd0f32b8c22e9c992f54 against base e02fe33220fa497a2e7ee780c8295517b4f967fa. The prior P2 attachment-state round-trip blocker is resolved; no remaining blocker in the reviewed changes.

  • Fold now selects the newest surviving authorized attachment-bearing edit; composer saves pass current folded provenance, and outgoing edits reject unavailable or mismatched source evidence instead of restoring original attachments. I implemented this fix; Mongo independently reviewed the changed contracts without finding a blocker. The final amend only adds the required media-viewer test prop.
  • Full Vitest on the patched working tree before that fixture typing correction: 268 files / 2,800 tests passed. Restoring the original production implementation made six new regression assertions fail. Final-head push hooks passed TypeScript, design checks and 89 files / 1,386 related tests. Hosted JavaScript, browser measurements, security and DCO checks have passed.
  • Remaining merge gate: hosted Rust and browser journeys were still running at the latest check; Windows validation was skipped. No local browser/native or live cross-client validation. Retained attachment-source lookup after actual shared-cache eviction was source-reviewed, not integration-tested. These limits do not reopen the resolved code blocker; merge only once required checks pass.

@wesbillman
wesbillman merged commit d6b01e6 into main Sep 24, 2026
12 checks passed
@wesbillman
wesbillman deleted the zmarley/bot-1939-rich-content-compat branch September 24, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants