Repository navigation
feat(inbox): preview recent Inbox activity when hovering the sidebar row - #2347
Merged
Merged
Conversation
Resting a hover pointer on the sidebar Inbox row opens a card with the newest Inbox conversations, an unread summary and an Unread only switch that is separate from the Inbox page's filters. Clicking a row opens its conversation directly; Open Inbox goes to the page. The card is not shown while the Inbox page is selected. The shell owns the trigger, hover timing, placement and dismissal through a new optional page `preview` contribution; Inbox supplies only the content. Inbox rows are shared between the page and the card. Co-authored-by: Claude <[email protected]> Signed-off-by: Gil Birman <[email protected]>
- Re-ensure the card's reads after a discovery revision retires a feed attempt, as the Inbox page does; the card could otherwise stay idle. - Include read-state sync failures in the card's failure and retry sync after refreshing, as the page does. - Show "Nothing unread" and the empty states only once activity was checked, not while it is idle. - Mark the shell's hover trigger as a transient preview so it does not hold back a conversation's default composer focus. - Cover the press/focus guard, focus handoff, the full conversation target, page filter independence, activity/connection retry and the idle state; wait for the open transition before measuring placement. Validation: tsc; vitest src/app/shell src/bundled/inbox src/features/pages src/plugins/author.test.mjs (542 passed); playwright inbox-preview.spec chromium+webkit --repeat-each 3; each new assertion fails with its fix reverted. Co-authored-by: Claude <[email protected]> Signed-off-by: Gil Birman <[email protected]>
Base UI popover triggers never open on focus, so drop the dead trigger-focus guard and the focus step that tested nothing. Cover the card's read-state sync failure and retry with a fixture hook, so dropping sync.error from the card fails the test. Validation: tsc; biome; vitest src/app/shell src/bundled/inbox src/features/pages src/plugins/author.test.mjs (542 passed); mutation check on sync.error. Co-authored-by: Claude <[email protected]> Signed-off-by: Gil Birman <[email protected]>
Return the toolbar button first, as before this branch, so toolbar pages no longer build and discard a sidebar row. Behavior is unchanged. Validation: tsc; vitest src/app/shell. Co-authored-by: Claude <[email protected]> Signed-off-by: Gil Birman <[email protected]>
gilgtm
marked this pull request as ready for review
November 4, 2026 01:51
kazemek21
approved these changes
Nov 4, 2026
kazemek21
left a comment
Contributor
There was a problem hiding this comment.
Kyle reviewed this PR and the Nexus review-tracker notes. Approved with the two non-blocking retry comments below.
Posted by Codex (gpt-6.1-sol) on behalf of kylez
gilgtm
marked this pull request as draft
November 4, 2026 12:23
A roster Retry now also refreshes activity that failed meanwhile, so one Retry clears both errors. When a focused Retry recovers and leaves the card, focus moves to the Unread only switch instead of the body. Co-authored-by: Claude <[email protected]> Signed-off-by: Gil Birman <[email protected]>
* origin/main: (52 commits) feat(agents): give plugin agent types the Buzz side of a turn (#2364) feat(plugins): pin buzz://plugin-install links to a path and commit (#2315) feat(plugins): tint currentColor SVG page icons like host icons (#2314) feat(notifications): add a soft notification sound (#1536) feat(agents): let agents propose a profile picture (#2267) fix(plugins): default reminders and workflows off for fresh installs (#2291) Show all reactors in compact, separate emoji capsules (#2179) fix(panels): remember page split widths per workspace (#2264) feat(search): browse open channels from a Channels tab in search (#2164) perf(relay): page combined replay filters after a reconnect (#2308) fix(composer): make native Mac text shortcuts work past link chips (#2390) perf(relay): read creator proofs for many channels per filter (#2312) fix(channels): let published leave and delete confirm through access loss (#2357) fix(media): save native context menu media downloads and hide loopback links on macOS (#2131) fix(links): say why a message preview is unavailable, and preview unjoined public channels (#2136) test(browser): serve emoji artwork in the reaction hit-area journey (#2138) test(browser): click a reply link only after its row settles (#2358) fix(agents): restore delegated workflow mentions (#2399) feat(identity): always back up keys in managed builds (#2398) test(threads): render before checking the reader across activity resizes (#2389) ... Signed-off-by: Gil Birman <[email protected]> Co-authored-by: Claude <[email protected]> # Conflicts: # src/plugins/author.test.mjs
gilgtm
marked this pull request as ready for review
November 4, 2026 19:57
* origin/main: (22 commits) feat(mentions): quieter mention menu that marks agents and their owners (#2328) feat: add a Canvas View tab, History diffs and a 256 KiB limit (#2318) feat(plugins): let local agents write and reload plugins (#2435) feat(onboarding): offer Create a community after public Builderlab sign-in (#2397) Open any Inbox filter view by route (#2394) fix(bestie): deleting an agent saves no Bestie record where there was none (#2420) fix(unread): never treat agents-audience messages as unread (#1552) feat(focus): add an optional Focus plugin that quiets everything except Solo chats (#2277) [5/5] Add protection to the Goose harness plugin (#839) feat(agents): identify plugins in native hook output (#2299) [4/5] Add protection to the Codex harness plugin (#1879) feat(search): show member counts on channel results (#2333) Fix the mute icon flashing when selecting a channel (#2287) feat(agents): open a working agent's transcript from its activity (#2276) test(agents): refuse a real relay workflow mention in the harness kit (#2444) fix(agents): catch up every event watch on the kinds it watches (#1852) Keep local artifact collections current (#1507) feat(members): add several people to a chat in one write (#2010) feat(solo): let viewers join read-only spaces (#2301) [3/5] Add protection to the Claude harness plugin (#1878) ... Signed-off-by: Gil Birman <[email protected]> Co-authored-by: Claude <[email protected]>
* origin/main: fix: exclude muted channels from sidebar unread scroll indicators (#2335) fix(claude-code): open long Claude transcripts a page at a time (#2428) feat(solo): share chats as view only (#2375) fix(inbox): show Solo responses under All, read live replies in the open conversation, describe toolbar badges (#2275) AIDA-2434: Show saved teams in mentions (#2339) AIDA-2455: Restore channel scrollbar dragging beside threads (#2436) feat(agent-protection): show the owner why a protection provider denied input (#2105) fix(search): show slow lookups beside their section headings (#2442) Align Bestie DM layout and unread state; speed up thinking shimmer (#2418) Send Claude, Pi and Goose history as exact records (#2088) fix(agent-activity): align the stopped note and show it after the agent's reply (#2441) fix(agents): stop orphaned Attention commands and prevent duplicate runs (#2448) Signed-off-by: Gil Birman <[email protected]> Co-authored-by: Claude <[email protected]> # Conflicts: # src/app/shell/PageNavigation.tsx
wpfleger96
added a commit
that referenced
this pull request
Nov 4, 2026
…-nip-fi * origin/main: feat(inbox): preview recent Inbox activity when hovering the sidebar row (#2347) Add collapsible Solo and Team sidebar sections (#2296) fix(codex): open long Codex transcripts a page of items at a time (#2259) Keep Solo model and effort choices per chat (#2342) feat(sidebar): smooth channel reordering with bounded motion (#2108) Connect legacy agents from DMs and channel mentions (#2423) fix: exclude muted channels from sidebar unread scroll indicators (#2335) fix(claude-code): open long Claude transcripts a page at a time (#2428) feat(solo): share chats as view only (#2375) # Conflicts: # src/app/shell/PrimarySidebar.tsx
damienrj
added a commit
to damienrj/buzz-app
that referenced
this pull request
Nov 4, 2026
…-clone-auth-ab8b97 * origin/main: (38 commits) feat(identity): decide a missing backup choice from community membership (block#2378) Offer Builderlab decisions in FI builds (block#2227) feat(inbox): preview recent Inbox activity when hovering the sidebar row (block#2347) Add collapsible Solo and Team sidebar sections (block#2296) fix(codex): open long Codex transcripts a page of items at a time (block#2259) Keep Solo model and effort choices per chat (block#2342) feat(sidebar): smooth channel reordering with bounded motion (block#2108) Connect legacy agents from DMs and channel mentions (block#2423) fix: exclude muted channels from sidebar unread scroll indicators (block#2335) fix(claude-code): open long Claude transcripts a page at a time (block#2428) feat(solo): share chats as view only (block#2375) fix(inbox): show Solo responses under All, read live replies in the open conversation, describe toolbar badges (block#2275) AIDA-2434: Show saved teams in mentions (block#2339) AIDA-2455: Restore channel scrollbar dragging beside threads (block#2436) feat(agent-protection): show the owner why a protection provider denied input (block#2105) fix(search): show slow lookups beside their section headings (block#2442) Align Bestie DM layout and unread state; speed up thinking shimmer (block#2418) Send Claude, Pi and Goose history as exact records (block#2088) fix(agent-activity): align the stopped note and show it after the agent's reply (block#2441) fix(agents): stop orphaned Attention commands and prevent duplicate runs (block#2448) ... Signed-off-by: damienrj <[email protected]>
matt2e
added a commit
that referenced
this pull request
Nov 4, 2026
…2395) ## What users see Someone mentions you in a channel you haven't opened this session, and their profile hasn't loaded yet. You leave any channel and open the **Inbox**. The row shows a shortened key (`npub…srl`) and a letter avatar instead of their name. It stays that way while the Inbox is open, and nothing asks again. Their name appears only after you open their channel. This is a regression from #2269 ("reserve profile room for an open channel's roster", by Logan Johnson, `loganj`). A bisect over 248 commits, with no skips, found its merge commit `fe6eaa222` as the first bad one. Its parent `589c2a489` names the author right away. The channel being left doesn't need to be large: in the repro, #Alpha has one member. https://github.com/user-attachments/assets/e1e24cfb-14c1-4a4c-ba65-993443e28b5c Left: the branch base 8668dbd. Right: this branch at b3d1f09. Both sides click Inbox on the same frame. On the left, the Inbox's read for Priya is cancelled 6 ms after it's sent and the row stays `npub…srl`. On the right, the read returns 200 in 16 ms and the row shows "Priya Shah" from the first Inbox frame.  ## Cause 1. An open channel reserves profile-cache room for its roster (`Conversation.tsx`, a layout effect). Leaving releases that reservation, and the release schedules the shrink one task later (`shrinking ??= setTimeout(resize)`). 2. In the same commit, the Inbox's mount effect asks for the names it shows, as a background read. 3. When `resize()` runs, it treats the shrink (1025 → 1024 in the repro) as a reason to cancel **every** pending background read that isn't a reconnect refresh. That includes the read the Inbox just started. 4. The cancel is silent: `ensure()` resolves normally, and only `evictions()` moves. The mention menu is the only consumer of `evictions()`. The Inbox's effect has no dependency that changes, so it never asks again. The cancel in #2269 was right for the departing view's reads, for example the mention menu's 500-author roster pages, which would otherwise land late and push the next view's names out of the 1,024-entry cache. It was wrong for reads the **next** view started while the shrink was waiting. ## The fix The fix is in one production file, `src/features/relay/profile-directory.ts` (+28/−8): - **Stamp at creation.** A counter goes up each time a reservation is released. A read records that count when it is created, and the stamp never changes (`readonly releases`). - **One predicate.** `shrinkCancels(batch)` is true for a background read that isn't a reconnect refresh and was created before the latest release. `resize()` uses it to choose what to cancel. `ensure()` uses it to decide whether a request may join a pending read. - **No joining a read that's about to be cancelled.** While a shrink is waiting, a request doesn't join a pending read that the shrink would cancel. That name gets its own read, and the shrink still cancels the rest of the departing page. Joins on foreground and refresh reads, and any join while no shrink is waiting, work as before. - A remount or a roster-count change is unaffected. `reserve()` clears the waiting shrink before the children's effects ask for names. - The `evictions()` doc comment, the `resize()` comment and one line of `docs/channels.md` now describe the narrower cancel. `docs/buzz-help.md` is unchanged, because this restores the earlier behaviour. **Why the stamp isn't updated on a join.** The first commit (8429c27) updated a pending read's stamp whenever a later request joined it. Review showed that this kept a whole departing roster page alive for the sake of one shared author. The reader runs one background job at a time, so those pages also landed before the Inbox's own read. In a 9,000-member scenario, 3 joined pages loaded 1,500 roster profiles into the 1,024-entry cache. That pushed out 5 names the Inbox had already shown, and those rows went back to `npub…`, which is the case #2269 was written to prevent. With the creation-time stamp and the join skip, the same scenario cancels 19 pages and keeps all the Inbox's names and all 200 earlier names, with the same 20 reads. **Rejected alternatives** - **Make the Inbox re-read when `evictions()` moves.** That fixes one page, and every switch from a channel to the Inbox would send the read, cancel it and send it again. - **Bump `generation()` when a shrink cancels reads.** That changes what `generation()` means: it marks a full cache purge, which other code keys on. - **Drop the cancel, or skip it for small shrinks.** Either one brings back the eviction case #2269 fixed. **Accepted costs.** These were noted in review and don't block: - A release that leaves a larger reservation open can split a join into a second, redundant read until the next task. - If the next view asks again for every author on a departing page, that page isn't cancelled. It loads only names the next view asked for, so the cost is one redundant read and no names are pushed out. ## Surfaces covered The directory change covers every page that replaces a channel and asks for names in its mount effect without watching `evictions()`: - the Inbox (tested and recorded); - Drafts, opened straight from a channel (`DraftsView.tsx`); - Reminders (`RemindersPage.tsx`); - Workflows owner names (`WorkflowLanding.tsx`); - Agents → Watching (`watching/Tab.tsx`); - the Inbox hover preview in open PR #2347, which copies the Inbox's effect. These were found by reading the code. Only the Inbox has a browser case or a recording. The others use the same directory rule, which the unit test covers. **Out of scope.** Views that stay mounted when you leave a channel are still exposed if their read happens to be in flight at that moment: - sidebar DM labels (`useChannelLabels.ts`); - Inbox names for edited-message authors (`unread.ts`); - channel previews loaded in the background (`store.ts`), which are re-read when the channel opens. The window is one relay round trip at the moment you leave. None of these was reproduced, so a follow-up is warranted only if one is. ## Tests ### Unit test (Vitest), `src/features/relay/profile-details.test.ts` The new test, "keeps background reads asked for after a release when the shrink runs", sits next to #2269's cancellation test, which is unchanged. - **Setup:** reserve room. Start two departing background reads: one for a `stale` author, and one page holding `joined` and `other`. Release. Before the timer fires, the next view asks for `fresh` and `joined`. - **Assertions:** - how each read is split: `[stale]`, `[joined, other]`, `[fresh, joined]`; - `evictions()` moves by exactly 2, because both departing reads are cancelled; - every read is answered with all four profiles, and only `fresh` and `joined` end up in the cache. - **Mutants:** in the round 2 review, four mutants were run against this test at b01fe78, and each failed: 1. the first commit's stamp update on join: evictions +1, and `other` is named; 2. no join skip: `joined` stays unnamed; 3. a shrink that never cancels: evictions +0, and `stale` and `other` are named; 4. main's behaviour: `fresh` and `joined` stay unnamed, with evictions +3. Mutants 1 and 2 issued 3 reads either way, so b3d1f09 added the read-split assertion. With the join skip removed, the third read holds only `fresh`, and the test now fails on the split too. ### Browser case, `tests/browser/inbox.spec.mjs` One case was added, "Inbox names after leaving a channel › names an author seen only in the Inbox", and none were removed. - **The flow:** open on #Alpha, click Inbox, and expect the row for an author seen only in #Launch to contain "Priya Shah". Also expect exactly one kind-0 query naming her. - **Why it needs a browser:** the bug depends on ordering across two surfaces: the channel's layout-effect release, then the Inbox's mount-effect read, then the deferred shrink. The unit test proves the directory rule, not that the real Inbox's read starts after the release and before the shrink. - **Fail, then pass:** it fails without the fix in both Chromium and WebKit, where the row shows `npub…`. It passed 5/5 per engine at 8429c27 and passed again in both engines after the join change. Production code hasn't changed since then; b3d1f09 changes only the unit test and a comment. - **Why CI missed this:** no journey checked the name of an author seen only in the Inbox. ### Other checks during development These were not re-run for this push: - `profile-details.test.ts`: 25/25 pass. - The 16 unit test files that import the profile directory: 630/630 pass. - `profile-roster-scale.spec.mjs`, #2269's 9,000-member check: passes in both measurement projects. - `typecheck`, `lint` and `git diff --check`: clean. - Pre-commit hooks: passed on each commit. Pre-push hooks were skipped for this push (`--no-verify`). ## Review rounds - **Round 1 (8429c27):** one blocker. Updating the stamp on a join kept departing roster pages alive (the 9,000-member scenario above). Fixed in b01fe78, along with the optional items: a clearer field comment, a `stale` assertion that can actually fail (the test now answers every read with all profiles), and a minimal `docs/channels.md` diff. - **Round 2 (b01fe78):** the blocker is fixed, with no new defects, and the change was judged at the 9/10 bar. Its optional items, asserting how each read splits and a comment wording, are in b3d1f09. ## Status This is a draft until a human tries it in the app (AGENTS.md "Before opening a PR", step 3). To test: open the app on a channel, then click **Inbox**. An author who mentioned you in a channel you haven't opened this session should show their name and avatar right away, without opening their channel. Deferred: - the human test above; - hosted CI on this head; - a WebKit recording (the browser case covers WebKit); - recordings of the other covered pages. Logan Johnson (`loganj`): this narrows #2269's cancel-on-shrink and changes the `evictions()` contract wording. Your review is welcome. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Matt Toohey <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
JonForest
added a commit
to JonForest/buzz-app
that referenced
this pull request
Nov 4, 2026
Resolve conflicts with block#2347, which moved hasUnread into InboxRow.tsx, and give its new inbox-preview browser journey the shared INBOX_BUTTON locator. Co-authored-by: DeviousMachine <8aa903583ddc111fb259d28d298a0b05685db29a3082a57a99c98522ae044622@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Co-authored-by: Jonathan Hollingsworth <[email protected]> Signed-off-by: Jonathan Hollingsworth <[email protected]>
johnmatthewtennant
added a commit
that referenced
this pull request
Nov 4, 2026
* origin/main: (38 commits) fix(browser): load scheme-less address input over https, falling back to http (#2467) fix(identity): stop one-click key unlinks and show the linked backed-up key (#2486) fix(test): observe coordination transition events (#2297) fix(profiles): keep the next view's profile reads through a shrink (#2395) fix(channels): show Add and Send message errors above the Manage members list (#2421) fix(threads): keep reply hooks off agent activity bubbles (#2422) fix(channels): offer only Copy link in a not-joined preview's sidebar actions (#2425) test: scope row menu placement checks to active section rows (#2493) feat(relay): detach channel windows to a point in history (#2042) feat(identity): decide a missing backup choice from community membership (#2378) Offer Builderlab decisions in FI builds (#2227) feat(inbox): preview recent Inbox activity when hovering the sidebar row (#2347) Add collapsible Solo and Team sidebar sections (#2296) fix(codex): open long Codex transcripts a page of items at a time (#2259) Keep Solo model and effort choices per chat (#2342) feat(sidebar): smooth channel reordering with bounded motion (#2108) Connect legacy agents from DMs and channel mentions (#2423) fix: exclude muted channels from sidebar unread scroll indicators (#2335) fix(claude-code): open long Claude transcripts a page at a time (#2428) feat(solo): share chats as view only (#2375) ...
wpfleger96
added a commit
that referenced
this pull request
Nov 4, 2026
…r-load-perf * origin/main: (31 commits) test: fix invitation and coordination checks on main (#2517) perf(search): name searched people from the profile search response (#2353) Use the merge queue for pull requests that require it (#2452) fix(browser): load scheme-less address input over https, falling back to http (#2467) fix(identity): stop one-click key unlinks and show the linked backed-up key (#2486) fix(test): observe coordination transition events (#2297) fix(profiles): keep the next view's profile reads through a shrink (#2395) fix(channels): show Add and Send message errors above the Manage members list (#2421) fix(threads): keep reply hooks off agent activity bubbles (#2422) fix(channels): offer only Copy link in a not-joined preview's sidebar actions (#2425) test: scope row menu placement checks to active section rows (#2493) feat(relay): detach channel windows to a point in history (#2042) feat(identity): decide a missing backup choice from community membership (#2378) Offer Builderlab decisions in FI builds (#2227) feat(inbox): preview recent Inbox activity when hovering the sidebar row (#2347) Add collapsible Solo and Team sidebar sections (#2296) fix(codex): open long Codex transcripts a page of items at a time (#2259) Keep Solo model and effort choices per chat (#2342) feat(sidebar): smooth channel reordering with bounded motion (#2108) Connect legacy agents from DMs and channel mentions (#2423) ...
michaelneale
added a commit
that referenced
this pull request
Nov 4, 2026
* origin/main: (31 commits) test: fix invitation and coordination checks on main (#2517) perf(search): name searched people from the profile search response (#2353) Use the merge queue for pull requests that require it (#2452) fix(browser): load scheme-less address input over https, falling back to http (#2467) fix(identity): stop one-click key unlinks and show the linked backed-up key (#2486) fix(test): observe coordination transition events (#2297) fix(profiles): keep the next view's profile reads through a shrink (#2395) fix(channels): show Add and Send message errors above the Manage members list (#2421) fix(threads): keep reply hooks off agent activity bubbles (#2422) fix(channels): offer only Copy link in a not-joined preview's sidebar actions (#2425) test: scope row menu placement checks to active section rows (#2493) feat(relay): detach channel windows to a point in history (#2042) feat(identity): decide a missing backup choice from community membership (#2378) Offer Builderlab decisions in FI builds (#2227) feat(inbox): preview recent Inbox activity when hovering the sidebar row (#2347) Add collapsible Solo and Team sidebar sections (#2296) fix(codex): open long Codex transcripts a page of items at a time (#2259) Keep Solo model and effort choices per chat (#2342) feat(sidebar): smooth channel reordering with bounded motion (#2108) Connect legacy agents from DMs and channel mentions (#2423) ... Signed-off-by: Michael Neale <[email protected]>
tulsi-builder
added a commit
that referenced
this pull request
Nov 5, 2026
## Why
People said Inbox's filter bar was crowded and Archive didn't make
sense. They liked the tabs and the Unread toggle, and they wanted the
page called **Activity**, like Slack's. This PR keeps those parts and
removes the rest, so the toolbar fits on one row for as long as
possible.
## What
- **Rename:** Inbox is now **Activity**, in the page title, the sidebar
row, the shortcut titles ("Open … in Activity") and the help docs. The
bell icon stays. Plugin id `buzz.inbox`, page id `inbox` and storage
keys are unchanged.
- **Toolbar:** one left-aligned row.
- Type tabs come first: All, Threads, Mentions, DMs. The first tab lines
up with the title-bar bell.
- A text-only **From** menu (Anyone / People / Agents) follows the tabs.
It gets a subtle fill while it's narrowing the list.
- The **Unread** switch sits right after From, so it stays in view on a
full-width page.
- When the window is too narrow, Unread wraps to the next line first,
then From.
- **Archive removed:** every conversation stays in the list. The row ✓
is now **Mark as read**. It only shows on unread rows.
- With Unread on, the row leaves the list and an **Undo** toast appears.
- When nothing unread is left, the list says **All caught up** and
offers **Show all**.
- **Drafts removed:** a draft stays in the conversation where it was
written.
- **Focus:** after Mark as read, focus moves to the next row only if
focus is still in the list. If someone moves to the composer while the
read is still saving, their cursor stays where they put it.
- **Sidebar hover card (#2347):** now titled Activity, with an **Open
Activity** button. It no longer hides conversations that were archived
before, so it lists the same conversations as the page.
- **Filter routes (#2394):** the route contract drops `show` and
`drafts`. Older links that still carry them open the page with its saved
filters instead of failing: `show` is ignored, and `{ drafts: true }`
alone opens the saved filters.
## Screenshots
<!-- Default toolbar · From menu · From: People · Marked as read + Undo
· All caught up · Narrow (560px) · Hover card -->
## Not in this PR
- The Inbox badge and bold label: #2337.
- Which items count as unread: #2401.
- The unread logic from #2275.
- "Retry inbox" and "Inbox history unavailable" in
`src/features/relay/session.ts` and `inbox-feed.ts`. Those files are
shared relay code, so the strings are unchanged.
- `archive.ts` no longer has a caller in the page or the card. Removing
it is a follow-up, so this PR doesn't touch the files #2275 edited.
## Testing
- **Unit:** `vitest run src/bundled/inbox src/app src/features/pages
src/plugins` passes, 1347 tests after the latest rebase.
- New: Mark as read via the ✓ and via the context menu, each when the
save succeeds and when it fails. In all four, focus stays in the
composer the user moved to. All four fail without the fix.
- New: route cases for sender-only routes and links that still carry
`show` or `drafts`.
- **Browser, Chromium and WebKit:** `tests/browser/inbox*` and
`sidenav-polish` pass, 74 tests after the latest rebase.
- New `inbox-mark-read.spec.mjs` covers the one-row toolbar layout, bell
alignment, Mark as read with Undo, and All caught up.
- **Static checks:** `tsc`, `lint` and `design:check` are clean.
- **Agent review:** Crack Catcher's blocking finding was a focus jump
during a pending read. It's fixed, and Crack Catcher confirmed it.
- **Human testing:** tulsi tried it in the desktop dev app and confirmed
it all works.
buzz-review-completed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<img width="1280" height="800" alt="1 Default toolbar"
src="https://github.com/user-attachments/assets/4e3d23ac-5529-48b6-ab91-594ce3933e52"
/>
<img width="1280" height="800" alt="2 From menu open"
src="https://github.com/user-attachments/assets/7e2c86df-998a-467d-9ae8-10ea8c73bcbc"
/>
<img width="1280" height="800" alt="3 From People (dark)"
src="https://github.com/user-attachments/assets/3dd58da4-204b-46de-b4e5-cc531f7bd580"
/>
<img width="1280" height="800" alt="4 Marked as read with Undo"
src="https://github.com/user-attachments/assets/d54214a4-2990-4080-bf1d-15d6cacfd4fc"
/>
<img width="1280" height="800" alt="5 All caught up"
src="https://github.com/user-attachments/assets/215850bb-8ed3-49c4-a4a7-a7cf6e2530ff"
/>
<img width="560" height="800" alt="6 Narrow window"
src="https://github.com/user-attachments/assets/e4a1fa0c-a19e-45de-b082-43c5295f7cba"
/>
<img width="1280" height="800" alt="7 Hover card"
src="https://github.com/user-attachments/assets/63947445-59ae-4c49-97b4-d04ae12c6875"
/>
---------
Signed-off-by: tulsi <[email protected]>
Co-authored-by: BasilBot <399581b6165ab01343e3a1324774b1024d76942aea563468f93c975e5ee5193c@buzz.block.builderlab.xyz>
Co-authored-by: Claude Opus 5.5 <[email protected]>
tulsi-builder
added a commit
that referenced
this pull request
Nov 9, 2026
Activity moves out of the dock and back into a row at the top of the Messages sidebar, where it was before #2626. Drafts & sent sits below it when that plugin is on. - **Hover preview:** resting the pointer on the row opens the same Activity card as before (#2347). The shell already supports previews on sidebar rows, so the card works unchanged. - **Reaction emoji:** the row's bell swaps for the latest reaction emoji, as the dock tile did. `ActivityNavigationIcon` is now sized for the row's 16px icon slot, and the dock's Activity-only icon code is gone. - **Selection:** opening Activity keeps Messages selected in the dock and keeps its sidebar, like other pages listed there (#2779). The change is host policy in `pagePlacement()` (`src/app/shell/presentation.ts`): `buzz.inbox/inbox` resolves to `"sidebar"` whatever placement it registers, and it's dropped from the dock order. No FOUNDATION files are touched. Docs (`docs/inbox.md`, `docs/buzz-help.md`, `docs/shell-design.md`, the Activity README) and Inbox code comments now say "Messages sidebar" where they said "app dock". ## Tradeoffs - **Fewer places to see it.** The row lives in the Messages sidebar. With another dock app open, the sidebar collapsed (below 650px), or a plugin narrowing the sidebar, Activity takes an extra step (Messages, Show navigation, or Search/shortcut), and the reaction-emoji swap isn't visible until the sidebar is. - Activity is no longer a dock tab. This reverses that part of #2626, so the dock's owner should sign off. ## Screenshots Synthetic browser-fixture data only. Hovering the Activity row, light:  Dark:  The row's bell swapped for a new reaction (✅):  ## Tests - New `PageNavigation.test.tsx`: the sidebar Activity row swaps its bell for the emoji and keeps its accessible name. - `presentation.test.ts`: bundled Activity resolves to the sidebar whatever placement it registers. - `navigation-owner.test.ts`: Activity now belongs to Messages. - `entity-navigation.test.tsx` also checks that Activity has no dock tab. - AppShell and entity-navigation tests that used Activity as an example dock app now use Bestie, Reminders or Workflows. Entity-navigation tests find the Activity row only after the sidebar's one startup remount, so they never click a detached row. - Browser specs find Activity with a shared `activityRow()` helper in `tests/browser/navigation.mjs`. No browser cases were added or removed. `inbox-preview.spec.mjs` now covers hovering the sidebar row; on a selected row it checks for the row's title hint where it used to check for the dock's tooltip. `inbox-tabs.spec.mjs` expects the 16px row emoji instead of the 18px dock one. Validation on this branch: - `pnpm check` (biome, typecheck, design checks) passed. - Full `vitest run`: 20,129 passed, 1 failed. The failure, `MemoryPanel.test.tsx > copies a memory from its context menu`, passes when run on its own on both this branch and main. - Chromium browser specs (`--project chromium`) covering Activity or the dock (41 files): after the fixes, every case touched passes. Three cases fail identically on the base commit without this change, so they're out of scope here: `layout.spec.mjs` "Alt+ArrowUp from a message link preserves native scroll ownership", and both `typing.spec.mjs` "a growing … composer lifts history" cases (React error #185). - **Narrow windows:** below 650px the Messages sidebar is collapsed, so getting to Activity takes Show navigation or Search. `inbox.spec.mjs`'s 390px case opens Activity through Show navigation and checks that the drawer closes. - After review fixes (`916e24d3e`): the vitest files touched (30 files, 689 tests) and `tsc` pass; the Chromium specs rerun with 45 passed and 1 failed, the Alt+ArrowUp case that also fails on main. `layout.spec.mjs` now uses Workflows as its non-Messages dock destination. - tulsi tried the running desktop app: the row, hover preview and emoji swap all work. Not run locally: WebKit browser projects and native builds. CI covers those. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: tulsi <[email protected]> Co-authored-by: BasilBot <399581b6165ab01343e3a1324774b1024d76942aea563468f93c975e5ee5193c@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hovering the Inbox row in the desktop sidebar now opens a small card with your most recent Inbox conversations, so you can check what's waiting without leaving the conversation you're in. The card lists up to 50 recent conversations with sender, place, time and unread state. It has its own Unread only switch, which never changes the Inbox page's saved filters. Clicking a row opens that conversation directly, and Open Inbox opens the full page. The card opens on hover with a fine pointer only. Pressing or keyboard-activating the row still selects the page, and the card is not shown while the Inbox page is already selected.
The shell owns the trigger, hover timing, placement and dismissal through a new optional
previewslot on registered pages (PagePreviewPropsinsrc/features/pages/service.ts, a FOUNDATION file, edited with approval). The Inbox plugin supplies only the content (InboxPreview). It reuses the page's unread, feed, profile and archive state, andInboxRowis extracted so the page and card render rows the same way. The card sits 6px to the right of the row's hover background, with the line under its header level with the row's top.EmptyStategains aframe="none"option for empty states inside a card. Failure, retry, loading and empty handling match the page: connection, activity and read-state sync errors show with Retry, and an empty result shows only after activity was checked.Browser coverage
tests/browser/inbox-preview.spec.mjs(one case, Chromium and WebKit). It covers what jsdom cannot: real hover-intent timing, Base UI positioning against the rendered row, and the card's measured placement. At widths of 1280px and above it asserts the 6px gap and header alignment, measured after the open animation finishes. Narrower layouts must place the card beside or below the row. Hover behavior, focus handoff, press/focus guards, filter isolation, open targets, and failure/retry paths are covered in Vitest (AppShell.test.tsx,InboxPage.test.tsx,service.test.ts). No browser cases were removed. Each new assertion was checked to fail with its fix reverted.Testing
main. A separate PR will fix it.buzz-review-completed