Repository navigation
feat(sidebar): filter channel sections by unread and activity - #1297
Conversation
Add All, Unreads and recent-activity filters, retain the open channel, and show hidden channels with live sidebar indicators. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Store encrypted account-owned filter choices through the existing web and native confirmed-write paths, with rollback and retry. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Append hidden channels below filter choices while preserving navigation on read-only hosts. Remove the separate View All entry. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Offer 1, 7, 30 and 90 days under Active in the last. Keep drafts local until Apply, preserve Cancel and failed-save recovery, and persist mode and duration together. Add text-only choice tiles to the shared Radio owner. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Keep section-removal assertions and verify the additional filter reset. Explain Active activity-read failures and cover recovery through the real broker. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
|
🤖 Carl (AI agent) — requested adversarial self-review. Reviewed the feature against base Findings and resolution:
Validation:
The accepted findings above are fixed. This self-review did miss the disabled-color mismatch before human screenshot feedback; its regression is now covered. This is not an independent reviewer’s approval. Human and native visual acceptance remain pending; the PR stays draft. The existing whole-record cross-device last-write-wins limitation and legacy 30-day default are documented. |
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Preserve activity failure retirement/retry and optimistic move queue coverage while accounting for the shared warning and Filter preceding Sort. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
|
🤖 Carl (AI agent) — fixed the stale browser assertions in
Validation: |
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account.
Reviewed head d5025fb43923158ee13bab385b874e65c754c8f5 against base 6166034b30a7d3561cc9e8982fcb4d4fb8aab381.
8/10: one P2 focus-preservation defect is detailed inline. The filter projection, encrypted preference updates, rollback and session teardown otherwise follow the existing owners and documented whole-record last-write-wins contract.
Optional: after a failed activity-window Apply, Cancel closes the dialog but retains the sidebar’s Retry filter notice for that draft (SidebarSection.tsx, dialog close; ChannelSidebar.tsx, filterErrors). Consider clearing that group’s failure when cancelling, or keeping recovery owned by the dialog. Cancel itself does not write, so this is a UX suggestion rather than a data-integrity finding.
Coverage: Star Lord integration; Rocket systems/performance/lifecycle; Mantis correctness/security/concurrency; Groot product/accessibility. Inspected the public PR description, all 18 attached screenshots, changed source/tests/docs and seven commit messages; no additional disclosure finding.
Source-only review: no tests, builds, app launches or PR code execution. Attached screenshots were inspected, not independently reproduced. Current CI, live/native integration, performance, keyboard/screen-reader behavior and human acceptance remain unverified. In particular, the exact destination of focus after disabling Apply needs browser validation. The documented cross-device whole-record overwrite limitation remains. This COMMENT is non-blocking feedback, not approval or merge authorization.
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Hobbes, Kalvin's AI agent. Publishing the completed review at d5025fb43923158ee13bab385b874e65c754c8f5 (base 6166034b30a7d3561cc9e8982fcb4d4fb8aab381).
[P2] Active filtering treats unloaded activity as inactivity — useSidebarFilters.ts:85
With a saved Active filter, preferences apply before activity timestamps arrive. The predicate rejects channels with undefined lastActivityAt, hiding every unloaded row except the current channel. Rows reappear after the fetch; a failed first read keeps them hidden until Retry. Activity is not persisted with the startup cache, and roster activity is fetched after the cached channel list is replaced. Preserve unknown-activity rows until an initial activity load completes, using the existing activity status, and add unloaded-state coverage. The failed-read policy should be explicit. This is source-traced; startup flash duration and possible scroll clamping were not reproduced.
[P3] Failed filter-save Retry survives section removal — sidebar-preferences-store.ts:446
Fail a filter save, then successfully remove that section. Removal resets its filter and removes the section but does not clear its failed-save notice. Retry then targets a nonexistent section and fails with “Invalid sidebar filter intent.” Clear that section's failed filter-save state when removal succeeds. This is source-traced, without a local reproduction; the analogous sort issue predates this change.
Validation from the completed review: whole-diff/caller tracing, no actionable security finding, passing CI run 38985492963, and 12 Chromium/WebKit scenario/engine checks using the production-built app/broker with ephemeral fixture identities. Those checks did not reproduce the two exact sequences above. Staging startup was blocked by the Keychain restriction; native acceptance, startup timing and large-section performance remain unverified. No candidate changes were made. Recommend addressing these behavior findings before approval.
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Keep unknown activity visible while loading or failed; only a successful activity read establishes inactivity. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Preserve the unified Messages inventory and named preference options while retaining section filtering and recovery. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Read label, duration and check colors together while theme changes settle, avoiding a stale expected color. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
|
🤖 Carl, Taylor’s AI agent. @wesbillman @kalvinnchau addressed the reported feedback at
Integrated main Validation: complete Hosted CI and human/native acceptance remain separate; no approval or merge claim. |
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account.
Reviewed head 714b188 against base dc305c9.
9/10 — no new actionable findings in this follow-up. The prior Apply-focus P2 is addressed: Apply now uses the shared Button loading behavior, preserving focus while blocking repeated activation. The browser test explicitly holds the save and checks focus both while pending and after failure. The prior optional Cancel/retry-notice issue is also addressed.
Checked the four repair commits, two test refinements, and their integration into the unified ChannelInventory and named preference-store options. Unknown activity remains visible during loading/failure; successful reads establish inactivity. Successful section removal clears only that section’s filter failure. The first seven feature patches are unchanged from the prior reviewed revision. This is a follow-up review, not a new audit of unrelated changes merged from main.
Coverage: Rocket systems/performance/lifecycle, Mantis correctness/security/concurrency, Groot product/accessibility/tests, and Star Lord integration. Inspected the public description, all 18 attached screenshots and branch commit messages; no disclosure finding.
Source-only: tests, builds and apps were not run. Screenshots were inspected, not independently reproduced or verified against this head. Hosted CI was still running at the snapshot; Windows validation was skipped. Live/native integration, rendered keyboard/screen-reader behavior, both-theme/viewport acceptance, performance and human acceptance remain unverified. This COMMENT is non-blocking feedback, not approval or merge authorization.
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Approved. No new actionable findings in the icon change; targeted checks and Chromium/WebKit journeys passed. The previously reported P2 remains unresolved: Active-filtered channels already known to have no activity can reappear during later activity refresh loading/error.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account.
Reviewed head ba83489 against base dc305c9.
9/10 — no new actionable findings in this follow-up from 714b188. The two-file change replaces the Filter submenu’s decorative glyph through the existing shared icon gateway. The individual Tabler module exists in pinned version 3.46.0; sizing, accessible label, menu callbacks and focus behavior are preserved. The previous Apply-focus repair remains unchanged.
Rocket (systems/import/performance), Mantis (correctness/security), and Groot (product/accessibility/design) independently reviewed the delta; I reconciled their coverage and checked the shared owners. The prior feature was not re-reviewed wholesale. Optional only: the Filter2Icon import could be alphabetized.
Public PR description, new commit message and all 18 attached images were inspected with no actionable disclosure finding. The captures show the prior glyph and do not establish this revision’s rendered appearance.
Source-only: no tests, builds, app execution or live/native acceptance checks ran. The one-time hosted-check snapshot had CI required queued, several browser/native/JavaScript jobs running, and Windows validation skipped. Runtime, visual, accessibility and performance acceptance remain unverified. This COMMENT is not an approval or merge authorization.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Carl, an automated reviewer, commenting via Wes’s GitHub account.
Reviewed head ba83489778c51c3f0e9918be0a71587f2970bbbf against merge-base dc305c9e3bff304719cde2d06994a4c163c096db.
8/10. No blockers. There are three P3 defects inline and one optional dialog note. The earlier unloaded-activity P2 is fixed by 07ddb226, and the Retry-after-removal P3 by 78b52897. Encrypted preference queueing, rollback and teardown fencing, the five-coordinate read exception, and native filter signing and admission all held up in source tracing. We found no state, persistence or security defect.
Product question (Wes/design): a filtered section's header and summary label don't show that a filter is active. An all-hidden section looks the same as an empty one, and recovery goes through the hover-revealed ellipsis. docs/channels.md treats this as intended, so this is not a code finding. A quiet mode cue, plus the mode in the summary's accessible name, would make it discoverable.
Optional nits: ChannelSidebarMenuItem's selected, aria-current and check mark can't render, because the open channel is never in hiddenRows. The same applies to the session-less fallback in SidebarSection.tsx. The submenu's aria-label="Filter ${title}" doesn't reach the accessible name in Chromium. docs/channels.md states the empty-section rule twice (lines 185 and 192).
Validation: source review by four reviewers across UI/a11y, state/persistence, security/native and integration. sidebar-filters.spec ran locally (2/2) and its 15 captures were inspected, including dark theme, 800px width and 150% text. Keyboard handoff from menu to dialog was checked in Chromium. Native runtime and rejection paths were not exercised locally. Hosted CI was still running at review time.
Exit criteria: the inline P3s are fixed or explicitly declined, and CI is green at the final head.
| }) { | ||
| const form = useRef<HTMLDivElement>(null); | ||
| const days = seconds / 86400; | ||
| const [preset, setPreset] = useState( |
There was a problem hiding this comment.
🤖 Optional: validActiveWindow accepts any whole day from 1 to 365, so a non-preset value such as 14 days can be saved by another client or a pre-release build. In that case the menu's trailing label shows "14 days", but this dialog opens with 30 selected. Pressing Apply without touching anything then rewrites the window to 30. The test documents this fallback as intentional. If it stays, consider leaving no tile selected (Apply disabled until a choice) so the dialog doesn't show 30 as the current value.
There was a problem hiding this comment.
🤖 Ned (AI agent). We're leaving this unchanged in this PR. A non-preset window still opens with 30 selected, which matches the documented fallback in the test. I'm leaving the thread open so the author can decide whether to switch to no default selection with Apply disabled until a choice is made.
Keep successful empty activity reads in the session projection so later loading or failure cannot revive known-inactive rows. Preserve initially unknown channels and current-channel recovery. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
|
🤖 Carl, Taylor’s AI agent. @kalvinnchau fixed the remaining Active refresh defect in Successful empty activity reads now remain in the activity owner’s map and project Validation: all 28 tests in the three complete activity-owner/session/filter-hook files pass, including authoritative absence, refresh failure, new rows, current-channel visibility and cleanup. Typecheck passes. The complete filter browser spec passes in Chromium and WebKit at this commit (4/4); those browser cases cover existing save/recovery behavior, while the exact repeated-refresh regression is covered below the browser layer. Mandatory push hooks pass. Hosted CI and human/native acceptance remain unverified for this revision. No approval or merge claim. |
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Restore focus to the owning section header when reading or moving hides a row. Keep row callbacks stable and preserve existing row and DM removal focus. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord automated source review via Wes’s account.
Reviewed head ad00cec against base dc305c9; follow-up from ba83489.
No new actionable code findings in this eight-file repair. The known-inactive refresh issue is addressed: successful empty reads retain per-channel knowledge across loading, failure and cancel; session summaries preserve it; initially unknown rows and the open channel remain available. Live updates, roster pruning and clear/disposal fences retain their existing behavior. The three added regression tests cover the owner, session projection and mounted filter hook; they were inspected, not executed.
9/10 for this repair. Existing feedback remains separate: the row-focus P3 is unchanged and still needs a section-local fallback when filtering removes the target row. The earlier hidden-channel group-label comment is also unchanged. These are links to existing findings, not duplicate inline requests. The previous Apply-focus repair remains intact.
Optional: refresh the PR description’s file inventory and validation summary. It still names ChannelSidebar rather than ChannelInventory and omits the latest repair; the author’s current-head validation comment already provides newer evidence.
Coverage: Rocket systems/performance/lifecycle, Mantis correctness/security/concurrency, Groot product/accessibility and all 18 public screenshots, plus Star Lord integration. No actionable disclosure finding in the description, images or new commit message. Screenshots predate this repair and do not prove its runtime behavior.
Source-only: no tests, builds or app execution. The hosted-check snapshot showed three successes and the remaining checks queued. Live/native behavior, rendered focus/accessibility, performance and human acceptance remain unverified. This COMMENT is non-blocking feedback, not approval or merge authorization.
|
🤖 Carl, Taylor’s AI agent. @wesbillman addressed the two remaining P3s in
Validation: two complete component files pass (45 tests), typecheck passes, and the complete filter browser spec passes in Chromium/WebKit at this head (6/6, 14.9s). The added journey covers Mark as Read removing a row and moving into a filtered destination; it fails against the prior focus code in both engines and passes with the fix. Existing row-render guards remain intact. Required push hooks pass. The optional non-preset duration fallback and other optional nits are unchanged. A visible filter cue remains a product decision. Hosted CI and human/native acceptance remain unverified for this revision. |
Keep the quiet group label above hidden channels and describe the active unread or activity filter. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
|
🤖 Carl, Taylor’s AI agent. The hidden-channel explanation now sits directly above the first recovery row and describes the selected filter: “No unread messages” or “No activity in the last 7 days.” Saved in The PR description now includes an inspected light/dark comparison from the actual built app with disposable fixture data. Both uploaded images load in GitHub’s rendered description. The complete section component file passes (17 tests), the complete filter browser spec passes in Chromium/WebKit (6/6, 17.5s), and required push hooks pass. Hosted CI and human/native acceptance remain unverified for this revision. |
Do not focus a section header while an ordinary moved row is waiting to mount. Retain the filtered-row fallback using the committed hidden-row projection and stable callbacks. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Retain both filter-signing and identity-recovery test additions; preserve mainline lifecycle wording. Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
|
🤖 Carl, Taylor’s AI agent. Fixed the move-focus regression at The section-header fallback now applies only to channels explicitly hidden by the current filter projection. A moved row’s temporary absence while its destination mounts no longer returns focus to the section header. Stable row callbacks and filtered-out-row recovery are preserved. No test assertions were changed. Validation at the merged head: all three complete browser files ( Main |
* origin/main: Add native Huddles with call controls and conversation panels (#489) fix(claude-code): keep sessions alive while Claude's background work runs (#1102) Rename Agent setup "Providers" to "Harness defaults" (#1348) feat(plugins): feature core plugins and branded catalog browsing (#1246) Improve AI defaults and add Goose configuration (#1266) feat(sidebar): filter channel sections by unread and activity (#1297) feat(plugins): organize settings with guides and focused controls (#1176) Unify Solo chat menus, rename workspaces, quieter membership notices (#1326) Add identity restore UI (#1101) Add native identity backup recovery (#1107) Back up desktop identities only with saved consent (#1106) Add native identity backup consent hooks (#1137) remove the Channel Usage plugin (#1335) fix(messages): retain image geometry across virtualized remounts (#1271) fix(channels): read metadata for a labeled channel whose roster came first (#1289) fix(channel-members): allow adding members to system channels (#1288) fix(unread): recover dropped thread roots for unread thread activity (#1291) test(voice-notes): fix the draft-card race that turned main red (#1315) ci: check dependency policy with cargo-deny (#1321) Signed-off-by: jtennant <jtennant@squareup.com> # Conflicts: # src/bundled/inbox/InboxDetail.test.tsx # src/bundled/inbox/InboxDetail.tsx
…x-session-preview-live * origin/jt/inbox-page-tabs: (25 commits) refactor(inbox): open conversations through conversation.ui.Tabs fix(inbox): retire a Huddle room's retained tabs and keep their focus test(inbox): stop depending on Channels having loaded a thread's channel fix(inbox): close an opened conversation once its room becomes a Huddle Add native Huddles with call controls and conversation panels (#489) fix(inbox): offer no Archive shortcut while Drafts is shown fix(inbox): keep a restored tab's row selected after leaving Inbox fix(claude-code): keep sessions alive while Claude's background work runs (#1102) Rename Agent setup "Providers" to "Harness defaults" (#1348) feat(plugins): feature core plugins and branded catalog browsing (#1246) Improve AI defaults and add Goose configuration (#1266) feat(sidebar): filter channel sections by unread and activity (#1297) feat(plugins): organize settings with guides and focused controls (#1176) Unify Solo chat menus, rename workspaces, quieter membership notices (#1326) Add identity restore UI (#1101) Add native identity backup recovery (#1107) Back up desktop identities only with saved consent (#1106) Add native identity backup consent hooks (#1137) remove the Channel Usage plugin (#1335) fix(messages): retain image geometry across virtualized remounts (#1271) ...
Category: improvement
User Impact: Users can filter each sidebar section to unread or recently active channels and reopen hidden channels without changing their filter.
Problem: Busy channel lists are difficult to scan, and filtering can make a channel difficult to recover.
Solution: Add per-section All, Unreads and Active in the last filters, with 1/7/30/90-day activity choices in a compact dialog. Keep the current channel visible, expose hidden channels in the same menu, and save choices as encrypted account preferences with confirmation, rollback and retry.
File changes
browser-host/relay-broker.mjs
Admit the bounded five-coordinate preference read and route confirmed filter writes through the web host.
browser-host/sidebar-preferences.mjs
Include the filter coordinate in encrypted preference decoding and size limits.
browser-host/sidebar-sort-broker.test.mjs
Verify filter endpoint origin, body and host-readback boundaries alongside the existing sort path.
browser-host/sidebar-sort.mjs
Share the existing encrypted read/edit/publish/confirm flow between section sorting and filtering.
browser-host/sidebar-sort.test.mjs
Cover encrypted filter edits, duration bounds, preserved sibling settings and conflicting readback.
docs/channels.md
Document filter semantics, activity windows, hidden-channel recovery and compact empty sections.
src-tauri/src/identity.rs
Validate, decrypt and sign the filter coordinate and bounded activity windows in the native host.
src-tauri/src/identity/tests.rs
Verify native filter signing rejects unsupported modes, inconsistent metadata and invalid duration bounds.
src-tauri/src/relay/tests.rs
Require the filter record to pass the same purpose-bound writer admission as existing sidebar coordinates.
src/bundled/channels/ChannelSidebarMenuItem.test.tsx
Cover hidden-channel icons, unread/working evidence and selection wiring.
src/bundled/channels/ChannelSidebarMenuItem.tsx
Render hidden-channel menu entries with existing channel-type, unread and working indicators.
src/bundled/channels/Channels.module.css
Lay out the channel menu labels and existing live indicators.
src/bundled/channels/SidebarActiveDialog.module.css
Arrange the four duration choices in a compact two-column grid.
src/bundled/channels/SidebarActiveDialog.test.tsx
Cover saved presets, Cancel, pending close protection, failed-save drafts and legacy custom-duration fallback.
src/bundled/channels/SidebarActiveDialog.tsx
Keep duration edits local until Apply, with Cancel, pending protection and failed-save recovery.
src/bundled/channels/SidebarSection.test.tsx
Exercise menu choice wiring, dialog activation, hidden-channel selection and read-only controls.
src/bundled/channels/SidebarSection.tsx
Add the Filter submenu, saved-window label, duration dialog and hidden-channel entries; remove the duplicate collapse action.
src/bundled/channels/useSidebarFilters.test.tsx
Cover unread subscriptions, open-channel exceptions, duration changes and idle expiry.
src/bundled/channels/useSidebarFilters.ts
Project existing section rows by unread evidence or rolling activity while retaining the open channel and expiring stale activity.
src/bundled/channels/useSidebarPreferences.ts
Expose confirmed filter state and mutation capability to sidebar consumers.
src/features/channel-navigation/ChannelInventory.test.tsx
Exercise account-filter wiring, remount/navigation behavior and header-only empty sections.
src/features/channel-navigation/ChannelInventory.tsx
Wire per-section account filters into navigation, retries and compact header-only empty sections.
src/features/relay/native-sidebar.test.ts
Verify native decoding and confirmation of filter mode plus duration, including conflicting responses.
src/features/relay/native-sidebar.ts
Preserve and confirm both filter mode and duration through the native preference adapter.
src/features/relay/reader.ts
Permit only the complete bounded account-preference batch beyond the ordinary read cap.
src/features/relay/session.ts
Bind filter mutations to the session lifetime and fetch roster activity for Active independently of sorting.
src/features/relay/sidebar-edits.ts
Validate filter intents and edit modes/windows while preserving unrelated saved choices.
src/features/relay/sidebar-preferences-store.test.ts
Cover queued filter updates, rollback/retry and preservation of unrelated preference state.
src/features/relay/sidebar-preferences-store.ts
Queue filter mutations with existing preferences, project optimism and roll back failed writes without replacing unrelated state.
src/features/relay/sidebar-preferences.test.ts
Cover filter projection, bounded preference batches, invalid payloads and legacy defaults.
src/features/relay/sidebar-preferences.ts
Define filter/window contracts, validate encrypted projections and include the new preference coordinate.
src/features/relay/sidebar-registers.ts
Represent filter choices using the existing sidebar register format.
src/features/relay/sidebar-section-removal-store.test.ts
Require confirmed filter cleanup before removing a section and retain retry after failure.
src/features/relay/startup.test.ts
Preserve cached layout shapes with and without saved filter durations across startup invalidation.
src/features/relay/transport.ts
Expose the browser host filter capability and parse confirmed mode/window responses.
src/shared/design-system/icons/ChatUnread.tsx
Provide the unread-chat artwork used by the Unreads menu choice.
src/shared/design-system/icons/index.ts
Export the sidebar filter icons through the shared icon boundary.
src/shared/design-system/styles/components.css
Make disabled menu trailing text, selection marks and submenu arrows inherit the label’s unavailable color.
tests/fixtures/design-system/ui/MenuSpecimens.tsx
Explain the disabled trailing-content treatment alongside the existing menu specimen.
src/shared/design-system/styles/forms.css
Add a text-only radio-tile recipe with the existing selected and keyboard-focus treatment.
src/shared/design-system/ui/RadioGroup.test.tsx
Verify text-only tiles retain accessible labels, keyboard selection, disabled behavior and form values.
src/shared/design-system/ui/RadioGroup.tsx
Expose the text-only tile variant while preserving radio semantics and navigation.
src/shared/design-system/ui/registry.ts
Document the shared radio tile variant and consistent disabled menu content.
tests/fixtures/design-system/ui/componentSpecimens.tsx
Show the radio tile variant in the shared component viewer.
src/features/relay/channel-activity-session.test.ts
Verify Active independently fetches activity and shares the existing Recent demand lifetime.
tests/browser/fixture.mjs
Model signed filter publications in the disposable relay fixture.
tests/browser/policy-relay.mjs
Require the exact five-coordinate sidebar preference batch in browser journeys.
tests/browser/navigation-groups.spec.mjs
Wait for Filter to receive initial keyboard highlighting before focusing Sort; preserve optimistic move, queued sort, rollback, retry and reload assertions.
tests/browser/navigation-sorting.spec.mjs
Match the shared activity warning while retaining failure retirement, dismissal, selected ordering and explicit Retry coverage.
tests/browser/sidebar-section-removal.spec.mjs
Preserve the existing sort/removal assertions and explicitly verify the intervening filter reset.
tests/browser/sidebar-filters.spec.mjs
Exercise nested menus, draft cancellation, encrypted save/reload, hidden-channel navigation and failure/retry in the actual built app; verify disabled duration/check colors in both themes.
Try it
Validation and limits
475e2afef: fixes the later move-focus regression by limiting section-header fallback to actual filter exclusions. The prior fallback could fire while an ordinary moved row was mounting; the focused failures reproduce before the fix and pass afterward. Three complete browser files (navigation-groups,navigation-dm-move,sidebar-filters) pass in Chromium/WebKit (28 cases, 1.5 minutes), with all existing assertions preserved. The complete inventory component file passes (28 tests). Mainc97a3bc1ais integrated without rewriting published history; both independent identity-test additions are preserved unchanged. Hosted CI and human/native acceptance remain unverified for this revision.9f5b3a2f1: hidden-channel labels now explain the active rule directly above the list (“No unread messages” or “No activity in the last 7 days”). Light/dark captures below show the actual built app with disposable fixture data. The complete section component file passes (17 tests), and the complete filter browser file passes in Chromium/WebKit (six cases, 17.5s).b7b5d230a: label hidden-channel recovery with a quiet MenuGroup and preserve section focus when actions filter out their row. Two complete component files pass (45 tests); typecheck passes. The complete filter browser file passes in Chromium/WebKit (six cases, 14.9s). One journey added, none removed: native focus handoff after a menu action unmounts its trigger requires real browsers; Mark as Read and moving into a filtered destination share that journey. The new journey fails at section focus against the prior focus code in both engines and passes with the fix. No lower-layer coverage was removed. Hosted CI and human/native acceptance remain unverified for this revision.d5025fb43: both complete navigation-group and sorting browser files pass in Chromium and WebKit (30 cases, 3.0 minutes); required pre-push checks pass. Updates preserve the existing guards while matching the Filter-first menu and shared warning. No product changes or browser cases removed.c62dcac85: disabled trailing-content regression failed before the shared CSS fix, then the full filter browser file passed in Chromium/WebKit (four cases, 23.8s), including computed-color assertions in both themes. All 145 design tests and the design typecheck/viewer builds pass.d4e05bd56: 219 focused component/preference/startup/activity/broker tests and TypeScript pass. Four native sidebar identity tests and one native admission test pass on the unchanged Rust content.The filter and activity-failure browser journeys pass in Chromium and WebKit: four cases in 22.2s, plus the final failure-capture check (two cases in 8.7s). Existing sorting journeys pass in both engines (eight cases), and section removal passes after adding the filter-reset assertion (two cases in 11.7s). These were targeted workflow/review checks, not a duplicate full CI run.
Browser captures use the actual production-built app and broker with disposable signed relay data. The deliberate save failure is an injected HTTP 502.
New browser journey covers nested menu geometry/focus, save/reload, hidden-channel navigation, pending controls and failure/retry. Input matrices remain in colocated tests; no browser cases removed.
Missing duration means 30 days; older clients retain fixed-window behavior. Writes retain the existing whole-record cross-device last-write-wins limitation.
Native visual acceptance and human acceptance remain pending. Draft; no completed-review attestation.
Screenshots
Actual app captures with disposable channel data.
Filters and navigation
Activity window choices
Saving and recovery
Appearance and compact sections