Repository navigation
render shared sessions as attachment cards - #1217
Conversation
Keep the document icon and Session label, distinguish chosen names from automatic titles, and stage session references above the caption editor. Co-authored-by: BasilBot <399581b6165ab01343e3a1324774b1024d76942aea563468f93c975e5ee5193c@buzz.block.builderlab.xyz> Signed-off-by: tulsi <[email protected]>
Co-authored-by: BasilBot <399581b6165ab01343e3a1324774b1024d76942aea563468f93c975e5ee5193c@buzz.block.builderlab.xyz> Signed-off-by: tulsi <[email protected]>
Update session labels and wire expectations, preserve the document-icon assertion alongside the lock, and model chosen-name label support without replacing the channel type. Co-authored-by: BasilBot <399581b6165ab01343e3a1324774b1024d76942aea563468f93c975e5ee5193c@buzz.block.builderlab.xyz> Signed-off-by: tulsi <[email protected]>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Found two draft/edit regressions and an automatic-title issue.
| (item): item is string => | ||
| typeof item === "string" && | ||
| item.length <= 16000 && | ||
| /^\[Session(?::| ·)\s+[^\r\n]+\]\(buzz:\/\/channel\/[^\s()]+\)$/.test( |
There was a problem hiding this comment.
🤖 [P2] Preserve every staged session card through draft restoration
Links with a Markdown title (for example, [Session: Fix](buzz://channel/session-id "title")), an angle-bracket destination, or an uppercase BUZZ: scheme are accepted by staging and removed from the prose, but this narrower restoration regex rejects their saved representation. Reloading drops the attachment; a subsequent edit can overwrite the surviving disk record. All three forms reproduced in Chromium and WebKit. Canonicalize admitted cards and use the same admission contract for staging and restoration.
There was a problem hiding this comment.
🤖 Fixed in ada5aaa. Staging and disk restoration now use the same canonical card parser/serializer, accepting titled links, angle-bracket destinations and uppercase schemes. Added direct restoration of older saved representations, stage→JSON restoration coverage for all three forms, and repeated restores preserving literal Markdown punctuation and entity-looking labels.
| restore: input.current.checkpoint(), | ||
| }; | ||
| const next = mentionDraft(editing.start(current)); | ||
| const next = stageSessionCards( |
There was a problem hiding this comment.
🤖 [P2] Preserve no-op behavior when editing messages with inline session links
Opening please review [Session: Fix](buzz://channel/session-id) before merge with ArrowUp and submitting without changes calls messages.edit with [Session: Fix](buzz://channel/session-id)\n\nplease review before merge. Staging extracts the inline link, then serialization puts the card first, defeating the original-content comparison in useMessageEdit.ts:111. This publishes a spurious edit and rewrites the sentence. Preserve the original edit representation or make the no-op comparison use the same normalization.
There was a problem hiding this comment.
🤖 Fixed in ada5aaa. The no-op baseline is now the same staged/serialized representation the composer submits. Source/conflict checks remain intact. Added a composer regression for ArrowUp + submit without changes and for changing then reverting the caption; neither publishes an edit.
| : { | ||
| id: channelId, | ||
| ttlSeconds: draftSettings.ttlSeconds, | ||
| named: |
There was a problem hiding this comment.
🤖 [P3] Derive automatic titles from the caption before serialized cards
composerMarkdown(draft) puts session cards first, while automaticTitle takes the first 80 characters. A UUID card consumes about 73 characters, so a captioned first message gets a sidebar title dominated by Markdown/link syntax with most of the meaningful caption truncated. Derive the title from the caption first, with a card-only fallback. The affected automatic-title call is at line 160.
There was a problem hiding this comment.
🤖 Fixed in ada5aaa. Automatic titles now read the caption before serialized session cards, with the existing card-only fallback. Added a new-chat regression with a UUID attachment and caption, asserting the caption becomes the sidebar title.
Canonicalize staged and restored session references with literal label escaping, compare edits against their staged starting representation, and derive automatic chat names from captions before cards. Co-authored-by: BasilBot <399581b6165ab01343e3a1324774b1024d76942aea563468f93c975e5ee5193c@buzz.block.builderlab.xyz> Signed-off-by: tulsi <[email protected]>
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account.
Two P2 integration defects are detailed inline: New Message omits staged session cards, and Inbox Drafts excludes card-only drafts.
P2 — Public PR material: the first image under “Screenshots / demos” embeds an internal deployment-host media URL in this public PR description. Replace that embed with an approved public attachment using scrubbed fixture data. Both attached images were inspected; this finding concerns the internal URL, not legitimate contributor attribution.
The earlier restoration, no-op edit, and caption-derived title findings have source-level fixes at this revision. Assessment: 8/10 until the two caller integrations and public-description issue are addressed. Existing MessageMarkdown/MessageLink, IconButton, draft persistence and Outbox owners are reused; no broader refactor is requested.
Reviewed head ada5aaa40a39849807c39bb4567bd910eb067e5e against base 61bf4ed03ce3fb37803de16d0910b3192a87eaf0. Source-only, with a fresh-frame self-review; no PR code, tests, builds or app execution, and no current CI assessment. Final-head native/live-relay behavior, mixed-client compatibility, actual keyboard/error-retry focus, both themes, narrow/enlarged-text layouts and renewed human acceptance remain unverified. COMMENT only; humans decide merge readiness.
| readView<unknown>(scope, draftKey, submission?.initialDraft ?? ""), | ||
| ), | ||
| list.channels, | ||
| ), |
There was a problem hiding this comment.
🤖 [P2] Update the New Message submission caller for staged cards
Staging now removes the session link from draft.text for every composer, including the submission used by src/features/direct-messages/NewMessage.tsx. That caller still returns early on !draft.text.trim() (its send guard) and sends only draft.text (its messages.send call). Select a recipient in New Message, paste a session link and add a caption: the card is displayed, but Send publishes only the caption and clears the saved draft after delivery. With no caption, the enabled Send button silently does nothing. Use the complete serialized draft for both admission and publication in that caller, and cover card-only and captioned first-DM sends/recovery.
There was a problem hiding this comment.
🤖 Fixed in e1bb184. New Message now uses composerMarkdown for both send admission and publication. Added card-only and captioned first-DM regressions using the real signed Outbox: lose the receipt, restart the session, verify the card/caption restore, then retry the identical signed event and clear recovery only after delivery. Both full NewMessage test files pass.
| export type MentionDraft = { | ||
| text: string; | ||
| /** Session references staged above the editor; serialized with the caption. */ | ||
| sessionCards?: readonly string[]; |
There was a problem hiding this comment.
🤖 [P2] Include staged cards in Inbox’s meaningful-draft check
A pasted session-only reference is now persisted with empty text and nonempty sessionCards, but src/bundled/inbox/DraftsView.tsx:92–96 still enumerates drafts with !!mentionDraft(value).text.trim(). After pasting a session link into an ordinary channel/thread composer and navigating away, Inbox Drafts omits that saved message; the old inline-link draft passed this check. Update the shared-draft consumer’s meaningful-content predicate and summary to account for staged cards, with coverage that discovers and reopens a card-only saved draft. The selected-draft exception does not help a draft that has never appeared in the list.
There was a problem hiding this comment.
🤖 Fixed in e1bb184. Inbox now treats staged session cards as meaningful saved content and gives a card-only row the summary “Session attachment.” Added discovery and reopen regressions for previously unselected channel and thread drafts; both reopen with the card intact and an empty caption. The full DraftsView test file passes.
Use complete serialized drafts for New Message admission and publication, and discover card-only Inbox drafts with a nonempty summary. Cover exact-event recovery after restart and reopening channel and thread drafts. Co-authored-by: BasilBot <399581b6165ab01343e3a1324774b1024d76942aea563468f93c975e5ee5193c@buzz.block.builderlab.xyz> Signed-off-by: tulsi <[email protected]>
|
🤖 Addressed the two integration findings in e1bb184 and replied inline. Also removed the internal deployment-host image embed from the public PR description; it now links only to the public synthetic gallery fixture source rather than publishing a replacement image. Validation: 82 affected unit tests, TypeScript, and 12 existing New Message/Inbox browser cases across Chromium and WebKit passed. New CI checks are separate; final native/live-relay and renewed human acceptance remain pending. |
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account.
No further actionable findings; no changes requested. Follow-up assessment: 9/10 for minimalness, ownership and correctness within the source-reviewed scope.
The prior findings are addressed: New Message now uses the shared composer serializer for both admission and publication, Inbox includes card-only channel/thread drafts and gives them a summary, and the internal image embed has been removed from the public description. The four-file change since ada5aaa40a39849807c39bb4567bd910eb067e5e includes regression cases for card-only/captioned first-DM sends, restoration and exact-event retry after receipt loss, and reopening saved channel/thread drafts. I traced the existing draft, Outbox, shared conversation, and focus/retirement owners and completed a fresh-frame self-review. No new lifecycle or storage owner is introduced.
Reviewed head e1bb184dae2aabea5108ff227a0210bd6fbb44eb against base 61bf4ed03ce3fb37803de16d0910b3192a87eaf0, focusing this follow-up on the prior findings and defects the fixes could introduce. The current public description has no attached images; its replacement is a link to public fixture source. The new commit message was also inspected.
Validation limits: source-only; no PR code, tests, builds or app execution, and no current CI assessment. Added tests were read, not run. Native/live-relay behavior, mixed-client compatibility, actual keyboard/error-retry focus, both themes, narrow/enlarged-text layouts, and renewed human acceptance remain unverified. COMMENT only; humans decide merge readiness.
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Approving at e1bb184d with one non-blocking finding.
[P3] Removing a card can break the emphasis around it — src/features/messages/session-cards.ts:150-156
When a session link sits at the edge of emphasis that also contains other text, the link is replaced with one space. That space ends up next to the closing delimiter, so the delimiter no longer closes:
*see [Session: abc](buzz://channel/<id>)*→ caption*see *(shows literal asterisks)**Done in [notes](buzz://channel/<id>) today**→**Done in today**
This affects incoming messages rendered through MessageRow, including content from older clients and agents. The composer is not affected because it works on marks, not delimiters. Suggested fix: when a removed range touches the edge of its parent inline container, drop the space and trim the adjacent whitespace. Add a test for each case above.
Verified at e1bb184d: tsc --noEmit and all 16 changed unit-test files (774 tests) pass. Rust channel_writes tests and browser suites were not run in this review.
…ui-polish * buzz-app/main: (43 commits) Unify file attachment cards and file-type artwork (#1220) feat(agents): start agents from relay-synced config copies (#1185) render shared sessions as attachment cards (#1217) fix(channels): keep other channels' permission reads alive across a delete (#1245) feat(channels): mark temporary channels in the sidebar (#1249) test(browser): fix six intermittent browser test failures and a composer caret bug (#1239) Close channel tabs together and make tab shortcuts predictable (#1154) Make message retry controls compact and accessible (#1221) fix(messages): end deferred composer focus on any focus move; stabilise hover-preview probe (#1244) fix(messages): keep restored-channel focus off the composer (#1243) fix(me): record reads in Solo chats opened from the sidebar (#1183) feat(inbox): archive or restore the open conversation with Control-Command-A (#1181) fix: keep panel divider dragging responsive (#1067) feat(agents): find people for agents through the relay's name-only profile search (#1124) fix(agents): explain why Create agent is disabled (#1232) feat(agents): run up to 8 Interests at once for every agent type (#1100) fix(codex): set up Codex from the agent creation card, as Claude does (#1231) Shrink the thread loading mark by a third (#1214) feat(agents): plugins add tools to every agent session (#1216) fix(sidebar): re-measure every drop target when a section resizes mid-drag (#1230) ... Signed-off-by: Taylor Ho <[email protected]>
Overview
Category: improvement
User Impact: Shared sessions appear as document cards with a consistent Session label, and users can type a caption beneath a staged session attachment.
Problem: Session links fall back to blue text or a bare title, and rendering a full card inside the editor stretches the composer. Automatic first-prompt titles also cannot reliably identify a manually chosen name.
Solution: Show a document card with
Session: <chosen name or short ID>, stage it above the caption editor, and render it before the sent caption outside the bubble. Keep replies, reactions, copy, and actions on the original message; record chosen-name intent with existing channel labels and preserve the original event during retries.Changes
File changes
docs/sessions/README.md
Document chosen-name provenance, compatibility, and session attachment behavior.
src-tauri/src/relay/channel_writes.rs
Allow bounded channel labels on session name edits while preserving host validation.
src/bundled/sessions/SessionShare.test.tsx
Update the share-flow expectation for the fixed Session label.
src/features/conversation/LinkPreview.module.css
Style the neutral document card, truncation, focus, and narrow layout.
src/features/conversation/MessageLink.test.tsx
Cover session labels, escaped names, unavailable cards, and live rename display.
src/features/conversation/MessageLink.tsx
Render session destinations consistently with document icon, fixed prefix, and access feedback.
src/features/conversation/channel-reference.test.tsx
Keep unavailable session cards accessible without inventing access states.
src/features/messages/ComposerSessionCards.tsx
Show staged cards above the editor using the existing renderer and shared remove control.
src/features/messages/MessageComposer.test.tsx
Cover staging, mentions, draft restoration, card-only sending, and upload recovery.
src/features/messages/MessageComposer.tsx
Keep cards in the existing durable draft and send lifecycle while editing captions normally.
src/features/messages/MessageRow.test.tsx
Verify cards precede caption bubbles and retain reply, reaction, menu, and timestamp actions.
src/features/messages/MessageRow.tsx
Present cards outside and before the caption bubble under the original message owner.
src/features/messages/Messages.module.css
Preserve neutral card styling and lay out the composer attachment area.
src/features/messages/composer-markdown.ts
Serialize staged references before their caption as ordinary Markdown links.
src/features/messages/composer-session-cards.test.ts
Cover legacy recipients, boundaries, formatting wrappers, and rich protected contexts.
src/features/messages/composer-session-cards.ts
Stage references without losing selected identities or revealing quoted or hidden content.
src/features/messages/mention-draft.ts
Persist bounded staged session references in the existing draft envelope.
src/features/messages/session-cards.test.ts
Cover timeline extraction, literal content, and mention seams.
src/features/messages/session-cards.ts
Project session references separately while preserving original signed message actions.
src/features/relay/channel-details-protocol.ts
Permit the chosen-name label without changing the strict session description grammar.
src/features/relay/channel-details.test.ts
Exercise signed rename/readback, label preservation, and unsupported capability behavior.
src/features/relay/channel-details.ts
Record manual name changes through the existing fresh-details authority checks.
src/features/relay/session.ts
Pass the relay channel-label capability into session creation.
src/features/relay/work-sessions.ts
Record explicitly chosen creation names and refuse unsupported provenance writes.
src/features/sessions/ConvertSession.test.tsx
Advertise label support in the conversion fixture so its pending-rename case reaches the intended recovery boundary.
src/features/sessions/NewSessionComposer.test.tsx
Cover chosen-name creation and a card-only first message.
src/features/sessions/NewSessionComposer.tsx
Freeze chosen-name intent and admit first messages containing only staged cards.
src/features/sessions/SessionLifetime.test.tsx
Retain naming labels when changing session lifetime.
src/features/sessions/WorkspaceSettings.test.tsx
Verify chosen-name metadata through the existing settings flow.
src/features/sessions/metadata.test.ts
Verify explicit names versus conservative short-ID fallback.
src/features/sessions/metadata.ts
Define the reserved chosen-name label and shared link naming rule.
src/features/sessions/pending-start.ts
Persist the frozen chosen-name flag across creation retries.
src/features/sessions/share.test.ts
Cover chosen labels and retrying the original event after another rename.
src/features/sessions/share.ts
Send fixed-prefix labels and match recovery by destination without rewriting signed bytes.
tests/fixtures/message-gallery/examples.ts
Add synthetic ID, chosen-name, long-title, and caption card examples.
tests/browser/{channel-tabs,me-workspace,me-polish,session-sharing}.spec.mjs and tests/browser/fixture.mjs
Align browser assertions with fixed session labels and wire text; advertise modeled Me label support and retain channel type during metadata readback. Keep legacy-link, chosen-name geometry, signed event identity, and document-icon coverage.
Reproduction steps
Session: <short ID>.PR 45 fixes, then share it. Confirm the fixed prefix remains and the chosen name appears.Validation and remaining checks
61bf4ed0. At headf6888934, required pre-push TypeScript/related unit tests, design types/guards, Rust workspace Clippy, and destination policy checks all passed. Remote head matches the local commit.f0aea3f3: all 46 affected cases across four full browser files pass in Chromium and WebKit (38 in the other three files, plus 8 sharing cases after the final document-icon selector fix). No cases added/removed, retries, skips, timeout changes, or relaxed assertions. Local final runs: 1.6m for all four files before the final selector correction; 17.9s for the full sharing file afterward. Hosted Linux execution is separate from local macOS evidence. Required pre-push checks passed again.Follow-up review fixes
At
ada5aaa4, address all three review findings: canonicalize staged/restored cards (including titled links, angle-bracket destinations, uppercase schemes and literal label punctuation), compare no-op edits against the staged starting representation, and derive automatic new-chat titles from captions before cards.Validation: 409 tests across the five full affected unit files; the full 16-test staging file passed again after adding direct restoration coverage for older saved records. TypeScript and 24 existing sharing/Me browser cases across Chromium/WebKit passed. These changes add no browser journeys. Native/live-relay acceptance remains deferred; retain draft status. Hosted checks for this new head are separate from the green checks on
f0aea3f3.Wes review fixes
At
e1bb184d, first-DM submission serializes staged session references for both admission and sending, and Inbox discovers/reopens card-only channel/thread drafts with a useful summary. Recovery tests verify restored cards/captions and exact signed-event retry after restart. The internal deployment-host image embed was removed; the screenshot section links to public fixture source only.Validation: 82 tests across the full NewMessage, recovery, and DraftsView test files passed; the full 13-test recovery file passed again after adding restored-display assertions. TypeScript and 12 existing New Message/Inbox Drafts browser cases across Chromium/WebKit passed (42.8s locally). No browser journeys added or removed. New hosted CI and renewed human/native/live-relay acceptance remain separate.
Screenshots / demos
Synthetic examples are available in the public message gallery fixture.