Skip to content

Offer plugin updates from the Buzz shell - #2491

Merged
dr0uleau merged 15 commits into
mainfrom
nexus/add-plugin-update-checks-and-one-click-reload-in-c9bcf80a
Nov 5, 2026
Merged

dr0uleau merged 15 commits into
mainfrom
nexus/add-plugin-update-checks-and-one-click-reload-in-c9bcf80a

Conversation

@dr0uleau

@dr0uleau dr0uleau commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Why

Desktop users need a clear way to find and apply Git plugin updates during normal use.

What

Offer shell notices and a Plugins menu entry for Git plugins that declare update support. The plugin sets the default for background checks. A saved per-plugin user choice overrides it. Plugins without the declaration receive no background checks. Check at startup and hourly while Buzz is visible. Checks do not install or reload plugins.

How

Clicking the notice body opens that plugin’s update checkbox in Manage plugins. The notice has a hover state and keyboard access. Update, Review permissions, Later, and Dismiss keep their own actions. Back restores the prior destination. Explicit Close retires matching plugin visits.

Fetch a fresh immutable preview on action. Apply updates without added access after confirmation from the notice. Require the existing access review for added access or a publisher change. Preserve source identity, managed pins, enabled state, signing rules, import concurrency, and rollback limits.

Later hides the current candidate for the app run. Failed checks and installs offer retry. Activation failures offer retry and the existing rollback confirmation outside Settings.

Nexus needs the matching manifest declaration and host pin in draft PR #196. Older hosts reject the new manifest field.

Risk

An enabled plugin reloads as soon as the update installs. The notice tells users to save unfinished forms and stop plugin workers first.

Testing

At 7a433af38, Blox passes all three push checks: TypeScript with 8,025 related frontend tests, design types and guards, and Clippy. The native plugin crate passes 105 tests. The policy regression fails on the old owner. The deferred-authorization regression fails before its fix and passes after it. Scoped independent review finds no remaining blockers. All 34 focused update tests pass. Clock and deferred-discovery tests reproduce both review findings before the fixes. They also cover recovery without a repeated zero-delay timer.

The full Toast browser file passes in Chromium and WebKit at 29ca9f643: 13 tests pass and one existing test skips. One browser case adds real pointer hit tests and keyboard use for notice navigation. It checks light/narrow and dark/wide layouts. Component and app tests cover the settings checkbox and Back/Close history. No browser cases are removed.

Native checks use the signed macOS app at 646ae3a94 and the real relay. Published Nexus builds cover the notice in both themes, Later and the Plugins menu, an enabled update, and access review with cancellation. The app restores after restart. Native policy checks also verify saved overrides across package replacement and restart. The fixture adds only the update declaration to published Nexus code.

The signed app at 755afe96 contains the new notice navigation. Later commits add browser types and fix check timing and pending Retry clicks. They preserve the notice layout and navigation. Native acceptance passes at 755afe96 with the saved sign-in, helper, signer, and profile. The app restores its community and update notice after restart. A native pointer click on the notice title opens Nexus details and focuses the checked update setting. The operator confirms the flow on 2026-11-05. The existing screenshots show the native notice, access review, and checkbox. The operator authorizes merge as is; small dialog UX fixes belong in a separate PR. All 41 CI checks pass at 7a433af38. Human review approves the PR. Both review threads are resolved.

Screenshots

Native macOS debug app at 646ae3a94, connected to the real relay. Conversation content is blurred for privacy.

Light Dark
Plugin update notice in light mode Plugin update notice in dark mode
Access review · light Access review · dark
Plugin access increase review in light mode Plugin access increase review in dark mode

The per-plugin setting uses the native app at cba7d609. The local Nexus fixture adds the update declaration to published plugin bytes. Its code and host access stay the same. The production declaration is in the linked plugin PR.

Checks on Checks off
Automatic update checks enabled Automatic update checks disabled

buzz-review-completed

Generated with Codex

@dr0uleau
dr0uleau requested review from a team, gilgtm and kazemek21 November 4, 2026 21:22
@dr0uleau
dr0uleau force-pushed the nexus/add-plugin-update-checks-and-one-click-reload-in-c9bcf80a branch from 1fa90de to e1b6d16 Compare November 5, 2026 00:02
@dr0uleau
dr0uleau marked this pull request as ready for review November 5, 2026 01:02
dr0uleau and others added 13 commits November 4, 2026 17:20
Co-authored-by: OpenAI Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: OpenAI Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: OpenAI Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
@dr0uleau
dr0uleau force-pushed the nexus/add-plugin-update-checks-and-one-click-reload-in-c9bcf80a branch from 0d27d6d to 29ca9f6 Compare November 5, 2026 02:01

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Kyle reviewed this PR and the Nexus review-tracker notes. Approving with two non-blocking scheduling comments.

Posted by Codex (gpt-6.1-sol) on behalf of kylez.

Comment thread src/app/PluginUpdates.tsx Resolved
Comment thread src/plugins/updates.ts Resolved
dr0uleau and others added 2 commits November 4, 2026 21:48
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
Co-authored-by: Codex <[email protected]>
Signed-off-by: Daniel Rouleau <[email protected]>
@dr0uleau
dr0uleau merged commit 97ee8dc into main Nov 5, 2026
43 checks passed
@dr0uleau
dr0uleau deleted the nexus/add-plugin-update-checks-and-one-click-reload-in-c9bcf80a branch November 5, 2026 15:59
damienrj added a commit to damienrj/buzz-app that referenced this pull request Nov 5, 2026
…ux-8fe4a6

* commit 'bac7a4fccad5fbf5cc31d949738b28264be1705a':
  feat(desktop): add Settings to the macOS app menu (block#2594)
  Preserve and renew external app approval (block#2464)
  fix(direct-messages): show verified identity in new message recipient search (block#2585)
  Offer plugin updates from the Buzz shell (block#2491)
  fix(messages): keep decoded images across virtualized remounts (block#2474)

# Conflicts:
#	src/app/PluginImport.tsx
wpfleger96 added a commit that referenced this pull request Nov 5, 2026
…-service

* origin/main:
  feat(settings): follow the system clock and let people hide message times (#2440)
  feat(plugins): repository access rules for Git imports (#2484)
  feat(desktop): add Settings to the macOS app menu (#2594)
  Preserve and renew external app approval (#2464)
  fix(direct-messages): show verified identity in new message recipient search (#2585)
  Offer plugin updates from the Buzz shell (#2491)

# Conflicts:
#	src-tauri/src/host_mcp.rs
damienrj added a commit to damienrj/buzz-app that referenced this pull request Nov 5, 2026
Upstream block#2491 checks Git plugins that declare update support at startup
and hourly. Checking every Git plugin from Settings would ignore that
opt-in, so this branch keeps only the compact install-request dialog.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: damienrj <[email protected]>
johnmatthewtennant added a commit that referenced this pull request Nov 5, 2026
Signed-off-by: John Tennant <[email protected]>

* origin/main: (47 commits)
  fix(messages): pass verified labels to the forward recipient picker (#2633)
  feat(messages): forward a message to a person (#2167)
  docs(agents): design relay-facing paths for the whole fleet at once (#2620)
  Route debug sessions through the credential helper (#2541)
  perf(search): skip no-op slow-search resets on each keystroke (#2605)
  perf(agents): dedupe channel members only for dm connection setup (#2603)
  perf(search): keep the search tab row across palette keystrokes (#2588)
  perf(sidebar): skip the hidden actions menu in solo and team headers (#2582)
  perf(search): rank each palette name once per render (#2606)
  perf(sidebar): skip re-rendering unchanged animated channel rows (#2572)
  feat(settings): follow the system clock and let people hide message times (#2440)
  feat(plugins): repository access rules for Git imports (#2484)
  feat(desktop): add Settings to the macOS app menu (#2594)
  Preserve and renew external app approval (#2464)
  fix(direct-messages): show verified identity in new message recipient search (#2585)
  Offer plugin updates from the Buzz shell (#2491)
  fix(messages): keep decoded images across virtualized remounts (#2474)
  Keep /leave commands out of channel history (#2476)
  fix(agents): ask before switching or closing drops unsaved edits (#2503)
  fix(agents): keep the Model settings row full width (#2577)
  ...
agude-sq added a commit to agude-sq/buzz-app that referenced this pull request Nov 5, 2026
* origin/main: (43 commits)
  feat(settings): follow the system clock and let people hide message times (block#2440)
  feat(plugins): repository access rules for Git imports (block#2484)
  feat(desktop): add Settings to the macOS app menu (block#2594)
  Preserve and renew external app approval (block#2464)
  fix(direct-messages): show verified identity in new message recipient search (block#2585)
  Offer plugin updates from the Buzz shell (block#2491)
  fix(messages): keep decoded images across virtualized remounts (block#2474)
  Keep /leave commands out of channel history (block#2476)
  fix(agents): ask before switching or closing drops unsaved edits (block#2503)
  fix(agents): keep the Model settings row full width (block#2577)
  feat(github): show a pull request's changes beside its summary (block#2492)
  fix(search): open an existing DM from a ⌘K person row without a relay open; cover hidden-DM previews (block#2519)
  feat(search): show channel type icon in search result subtitles (block#2521)
  test(browser): bind port-0 fixture servers where the OS assigns (block#2564)
  test(browser): fix six journey sync flakes from the 2026-11-04 sweep (block#2566)
  fix(channels): ask before Escape, Close or an outside click drops a template draft (block#2501)
  fix(channels): render the channel details description as linked Markdown with a label-only Edit target (block#2506)
  fix(agents): let Back and Forward shortcuts traverse provider dialogs (block#2509)
  Fix Inbox recovery after a delayed Retry (block#2496)
  feat(composer): optional ⌘/Ctrl+Enter to send (block#2331)
  ...

# Conflicts:
#	docs/buzz-help.md
matt2e added a commit that referenced this pull request Nov 7, 2026
## Failing test

`src/app/navigation.test.tsx` "keeps a return path for addressed plugin
settings and retires it on Close" (added by #2491) fails intermittently
in the Vitest flake-check lane:

```
Error: Test timed out in 5000ms.
```

It is one long journey on a full `App` mount with the default 5000 ms
timeout: open the Plugins list, open Pair mobile, Back, Forward, open
Appearance, open Pair mobile, Close, Back, Back.

## Why this is a timeout flake, not a race

The test is slow all the time, and every failure is the same timeout. No
assertion has failed.

- **Main:** 25 green `JavaScript` shard runs since #2491 took 2148–4414
ms (median 3921 ms). That leaves under 1.2 s of headroom.
- **Flake-check failures:** each one was a cold iteration 1 that ran
past 5000 ms. The same test then passed iterations 2–5 at its usual
speed, with no product or test change between them.

| Run | Iter 1 | Iters 2–5 |
|---|---|---|
| #2718
[42217828904](https://github.com/block/buzz-app/actions/runs/42217828904),
Flake check 1/2 | **× 5045 ms** | 4061–4133 ms |
| #2718, Flake check 2/2 | 3796 ms | 3377–3581 ms |
| #2729
[42194107421](https://github.com/block/buzz-app/actions/runs/42194107421)
attempt 1 | **× 5055 ms** | 3973–4399 ms |
| #2729 attempt 2 | **× 5224 ms** | 4016–4423 ms |

- **Neither PR touches this test's path.** #2718 changes deep-link
ingress and #2729 changes messages and relay code. The flake check
selected this file only through imports (`navigation.test.tsx` →
`services.ts` → `deep-links.ts`). #2729's attempt 3 passed.
- **Local near-miss:** in the local baseline below, one iteration on
unmodified `main` took 4920 ms.

## What this changes

The test is split where its title already splits. Each new test mounts
its own `App` with the file's usual per-test setup. The 5000 ms timeout
is unchanged.

1. **"keeps a return path for addressed plugin settings through Back and
Forward":** open the list, open Pair mobile, Back, Forward. These are
the original's first-half assertions, verbatim.
2. **"retires every visit to addressed plugin settings on Close":** open
the list, open Pair mobile, open Appearance, open Pair mobile, Close,
Back, Back. These are the original's second-half assertions, verbatim.
- The test keeps one earlier Pair mobile visit behind Appearance.
`dismissPluginDetails` retires *every* matching visit, and the final
Back landing on the list is what proves it.
- Without the earlier visit, that last assertion is vacuous. With Close
mutated to retire only the current visit
(`navigation.dismiss([navigation.snapshot().entry.id], settings)`):

| Version | Result with the mutated Close |
|---|---|
| Original test | fails |
| Split without the earlier visit | **passes** (misses the regression) |
| This split | fails |

Every assertion in the original test is kept in one of the two tests.
Production code is unchanged.

## Verification

All runs were local, on macOS (16 cores). The flake-check runs happened
while the machine was under heavy unrelated load (load average 35–40).

- `tsc --noEmit` and `biome check --error-on-warnings
src/app/navigation.test.tsx` pass.
- Each new test passes run alone (`-t`), and the whole file passes under
`--sequence.shuffle` with seeds 1–3. Seed 2 runs the Close test first.

**Per-test timings (ms).** The command was `BUZZ_TEST_WORKERS=2
./bin/node scripts/flake-check.mjs vitest --iterations=5 <files>`. The
file list is the same 15-file selection as #2718's failing lane.

| Test | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| Before: original (on `3bcf1c4bb`) | 2407 | 1994 | 2487 | 2037 | 4920 |
| After: Back and Forward | 1399 | 2071 | 1538 | 906 | 1384 |
| After: Close | 1951 | 2966 | 2131 | 1496 | 1801 |

Running `navigation.test.tsx` alone the same way: Back and Forward took
848–1595 ms and Close took 1352–2114 ms, with 0 of 5 iterations failing.

**Headroom.** The local worst case drops from 4920 to 2966 ms. The Close
half is the longer one, at about 0.75–0.8× the original's local time.
Scaled to CI's 3921 ms median, it should land near 3 s, about 1.8–2 s
under the timeout instead of about 1.1 s. That is an estimate. This PR's
own flake-check lane will repeat the edited file and give the real CI
numbers.

**Unrelated local failures.** Each 15-file run had one failure in
`src/app/entity-navigation.test.tsx`, which this PR does not touch, and
both happened under the load above:
- Before: "opens Inbox for a malformed launch link when the catalog
settles after the client" failed a `findByRole` wait.
- After: "normalizes old Bestie links … retaining { …(2) } scope" timed
out at 5608 ms.

No browser journeys were added or removed.

🤖 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]>
matt2e added a commit that referenced this pull request Nov 9, 2026
The not-available card for a Settings section (a section of an
uninstalled plugin, a bare section id, or a registered card whose
visibility settled false for a demoted admin) offered Go to Messages
beside Try again, and the turned-off card from a7045c7 offered it
beside Manage plugins. Inside the modal Settings dialog that action
makes no sense: the person is not on the main surface, and the dialog's
own section list and Close are the way out.

Yes, it is a holdover from the main-surface card. App.tsx builds one
`destinationFailure` element and renders it both in the shell, for page,
panel and plugin targets, and inside the Settings dialog's content, for
settings targets. "Calm, useful failure states when a destination can't
open" (#2015, 9169357) introduced Go to Messages with `leaveForMessages`
reasoning only about the main surface (Messages as "the nearest useful
place", or elsewhere when Messages itself failed) and, in the same
commit, replaced the earlier card's `!settings` guard on its Open
Settings action with no Settings guard at all, so the dialog inherited
the action. #2491 (97ee8dc) later moved the dialog without touching it.

Gate `leaveForMessages` on `!settings`. A settings target's cards then
keep Try again (now the primary action, as when no Messages page exists)
and Manage plugins; page, panel and plugin cards are unchanged. The
dialog has no overview section or back affordance of its own to send
people to: its section list is always beside the card, and Back and
Close Settings keep their navigation-history meaning, so no replacement
action is added.

FOUNDATION: src/app/App.tsx lines 458-463, the `leaveForMessages`
comment and its added `!settings &&` term only.

Tests in entity-navigation.test.tsx, whose fixture has a Messages page,
cover the not-available and turned-off cards inside Settings (Try again
alone and prominent; Manage plugins alone; no Go to Messages anywhere)
and fail on the previous App.tsx; its existing Activity tests keep
asserting Go to Messages on the page cards. The help guide never names
Go to Messages, so it needs no change.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
matt2e added a commit that referenced this pull request Nov 10, 2026
The not-available card for a Settings section (a section of an
uninstalled plugin, a bare section id, or a registered card whose
visibility settled false for a demoted admin) offered Go to Messages
beside Try again, and the turned-off card from a7045c7 offered it
beside Manage plugins. Inside the modal Settings dialog that action
makes no sense: the person is not on the main surface, and the dialog's
own section list and Close are the way out.

Yes, it is a holdover from the main-surface card. App.tsx builds one
`destinationFailure` element and renders it both in the shell, for page,
panel and plugin targets, and inside the Settings dialog's content, for
settings targets. "Calm, useful failure states when a destination can't
open" (#2015, 9169357) introduced Go to Messages with `leaveForMessages`
reasoning only about the main surface (Messages as "the nearest useful
place", or elsewhere when Messages itself failed) and, in the same
commit, replaced the earlier card's `!settings` guard on its Open
Settings action with no Settings guard at all, so the dialog inherited
the action. #2491 (97ee8dc) later moved the dialog without touching it.

Gate `leaveForMessages` on `!settings`. A settings target's cards then
keep Try again (now the primary action, as when no Messages page exists)
and Manage plugins; page, panel and plugin cards are unchanged. The
dialog has no overview section or back affordance of its own to send
people to: its section list is always beside the card, and Back and
Close Settings keep their navigation-history meaning, so no replacement
action is added.

FOUNDATION: src/app/App.tsx lines 458-463, the `leaveForMessages`
comment and its added `!settings &&` term only.

Tests in entity-navigation.test.tsx, whose fixture has a Messages page,
cover the not-available and turned-off cards inside Settings (Try again
alone and prominent; Manage plugins alone; no Go to Messages anywhere)
and fail on the previous App.tsx; its existing Activity tests keep
asserting Go to Messages on the page cards. The help guide never names
Go to Messages, so it needs no change.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
matt2e added a commit that referenced this pull request Nov 11, 2026
The not-available card for a Settings section (a section of an
uninstalled plugin, a bare section id, or a registered card whose
visibility settled false for a demoted admin) offered Go to Messages
beside Try again, and the turned-off card from a7045c7 offered it
beside Manage plugins. Inside the modal Settings dialog that action
makes no sense: the person is not on the main surface, and the dialog's
own section list and Close are the way out.

Yes, it is a holdover from the main-surface card. App.tsx builds one
`destinationFailure` element and renders it both in the shell, for page,
panel and plugin targets, and inside the Settings dialog's content, for
settings targets. "Calm, useful failure states when a destination can't
open" (#2015, 9169357) introduced Go to Messages with `leaveForMessages`
reasoning only about the main surface (Messages as "the nearest useful
place", or elsewhere when Messages itself failed) and, in the same
commit, replaced the earlier card's `!settings` guard on its Open
Settings action with no Settings guard at all, so the dialog inherited
the action. #2491 (97ee8dc) later moved the dialog without touching it.

Gate `leaveForMessages` on `!settings`. A settings target's cards then
keep Try again (now the primary action, as when no Messages page exists)
and Manage plugins; page, panel and plugin cards are unchanged. The
dialog has no overview section or back affordance of its own to send
people to: its section list is always beside the card, and Back and
Close Settings keep their navigation-history meaning, so no replacement
action is added.

FOUNDATION: src/app/App.tsx lines 458-463, the `leaveForMessages`
comment and its added `!settings &&` term only.

Tests in entity-navigation.test.tsx, whose fixture has a Messages page,
cover the not-available and turned-off cards inside Settings (Try again
alone and prominent; Manage plugins alone; no Go to Messages anywhere)
and fail on the previous App.tsx; its existing Activity tests keep
asserting Go to Messages on the page cards. The help guide never names
Go to Messages, so it needs no change.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
matt2e added a commit that referenced this pull request Nov 12, 2026
The not-available card for a Settings section (a section of an
uninstalled plugin, a bare section id, or a registered card whose
visibility settled false for a demoted admin) offered Go to Messages
beside Try again, and the turned-off card from a7045c7 offered it
beside Manage plugins. Inside the modal Settings dialog that action
makes no sense: the person is not on the main surface, and the dialog's
own section list and Close are the way out.

Yes, it is a holdover from the main-surface card. App.tsx builds one
`destinationFailure` element and renders it both in the shell, for page,
panel and plugin targets, and inside the Settings dialog's content, for
settings targets. "Calm, useful failure states when a destination can't
open" (#2015, 9169357) introduced Go to Messages with `leaveForMessages`
reasoning only about the main surface (Messages as "the nearest useful
place", or elsewhere when Messages itself failed) and, in the same
commit, replaced the earlier card's `!settings` guard on its Open
Settings action with no Settings guard at all, so the dialog inherited
the action. #2491 (97ee8dc) later moved the dialog without touching it.

Gate `leaveForMessages` on `!settings`. A settings target's cards then
keep Try again (now the primary action, as when no Messages page exists)
and Manage plugins; page, panel and plugin cards are unchanged. The
dialog has no overview section or back affordance of its own to send
people to: its section list is always beside the card, and Back and
Close Settings keep their navigation-history meaning, so no replacement
action is added.

FOUNDATION: src/app/App.tsx lines 458-463, the `leaveForMessages`
comment and its added `!settings &&` term only.

Tests in entity-navigation.test.tsx, whose fixture has a Messages page,
cover the not-available and turned-off cards inside Settings (Try again
alone and prominent; Manage plugins alone; no Go to Messages anywhere)
and fail on the previous App.tsx; its existing Activity tests keep
asserting Go to Messages on the page cards. The help guide never names
Go to Messages, so it needs no change.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
matt2e added a commit that referenced this pull request Nov 13, 2026
The not-available card for a Settings section (a section of an
uninstalled plugin, a bare section id, or a registered card whose
visibility settled false for a demoted admin) offered Go to Messages
beside Try again, and the turned-off card from a7045c7 offered it
beside Manage plugins. Inside the modal Settings dialog that action
makes no sense: the person is not on the main surface, and the dialog's
own section list and Close are the way out.

Yes, it is a holdover from the main-surface card. App.tsx builds one
`destinationFailure` element and renders it both in the shell, for page,
panel and plugin targets, and inside the Settings dialog's content, for
settings targets. "Calm, useful failure states when a destination can't
open" (#2015, 9169357) introduced Go to Messages with `leaveForMessages`
reasoning only about the main surface (Messages as "the nearest useful
place", or elsewhere when Messages itself failed) and, in the same
commit, replaced the earlier card's `!settings` guard on its Open
Settings action with no Settings guard at all, so the dialog inherited
the action. #2491 (97ee8dc) later moved the dialog without touching it.

Gate `leaveForMessages` on `!settings`. A settings target's cards then
keep Try again (now the primary action, as when no Messages page exists)
and Manage plugins; page, panel and plugin cards are unchanged. The
dialog has no overview section or back affordance of its own to send
people to: its section list is always beside the card, and Back and
Close Settings keep their navigation-history meaning, so no replacement
action is added.

FOUNDATION: src/app/App.tsx lines 458-463, the `leaveForMessages`
comment and its added `!settings &&` term only.

Tests in entity-navigation.test.tsx, whose fixture has a Messages page,
cover the not-available and turned-off cards inside Settings (Try again
alone and prominent; Manage plugins alone; no Go to Messages anywhere)
and fail on the previous App.tsx; its existing Activity tests keep
asserting Go to Messages on the page cards. The help guide never names
Go to Messages, so it needs no change.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
matt2e added a commit that referenced this pull request Nov 13, 2026
The not-available card for a Settings section (a section of an
uninstalled plugin, a bare section id, or a registered card whose
visibility settled false for a demoted admin) offered Go to Messages
beside Try again, and the turned-off card from a7045c7 offered it
beside Manage plugins. Inside the modal Settings dialog that action
makes no sense: the person is not on the main surface, and the dialog's
own section list and Close are the way out.

Yes, it is a holdover from the main-surface card. App.tsx builds one
`destinationFailure` element and renders it both in the shell, for page,
panel and plugin targets, and inside the Settings dialog's content, for
settings targets. "Calm, useful failure states when a destination can't
open" (#2015, 9169357) introduced Go to Messages with `leaveForMessages`
reasoning only about the main surface (Messages as "the nearest useful
place", or elsewhere when Messages itself failed) and, in the same
commit, replaced the earlier card's `!settings` guard on its Open
Settings action with no Settings guard at all, so the dialog inherited
the action. #2491 (97ee8dc) later moved the dialog without touching it.

Gate `leaveForMessages` on `!settings`. A settings target's cards then
keep Try again (now the primary action, as when no Messages page exists)
and Manage plugins; page, panel and plugin cards are unchanged. The
dialog has no overview section or back affordance of its own to send
people to: its section list is always beside the card, and Back and
Close Settings keep their navigation-history meaning, so no replacement
action is added.

FOUNDATION: src/app/App.tsx lines 458-463, the `leaveForMessages`
comment and its added `!settings &&` term only.

Tests in entity-navigation.test.tsx, whose fixture has a Messages page,
cover the not-available and turned-off cards inside Settings (Try again
alone and prominent; Manage plugins alone; no Go to Messages anywhere)
and fail on the previous App.tsx; its existing Activity tests keep
asserting Go to Messages on the page cards. The help guide never names
Go to Messages, so it needs no change.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
matt2e added a commit that referenced this pull request Nov 14, 2026
The not-available card for a Settings section (a section of an
uninstalled plugin, a bare section id, or a registered card whose
visibility settled false for a demoted admin) offered Go to Messages
beside Try again, and the turned-off card from a7045c7 offered it
beside Manage plugins. Inside the modal Settings dialog that action
makes no sense: the person is not on the main surface, and the dialog's
own section list and Close are the way out.

Yes, it is a holdover from the main-surface card. App.tsx builds one
`destinationFailure` element and renders it both in the shell, for page,
panel and plugin targets, and inside the Settings dialog's content, for
settings targets. "Calm, useful failure states when a destination can't
open" (#2015, 9169357) introduced Go to Messages with `leaveForMessages`
reasoning only about the main surface (Messages as "the nearest useful
place", or elsewhere when Messages itself failed) and, in the same
commit, replaced the earlier card's `!settings` guard on its Open
Settings action with no Settings guard at all, so the dialog inherited
the action. #2491 (97ee8dc) later moved the dialog without touching it.

Gate `leaveForMessages` on `!settings`. A settings target's cards then
keep Try again (now the primary action, as when no Messages page exists)
and Manage plugins; page, panel and plugin cards are unchanged. The
dialog has no overview section or back affordance of its own to send
people to: its section list is always beside the card, and Back and
Close Settings keep their navigation-history meaning, so no replacement
action is added.

FOUNDATION: src/app/App.tsx lines 458-463, the `leaveForMessages`
comment and its added `!settings &&` term only.

Tests in entity-navigation.test.tsx, whose fixture has a Messages page,
cover the not-available and turned-off cards inside Settings (Try again
alone and prominent; Manage plugins alone; no Go to Messages anywhere)
and fail on the previous App.tsx; its existing Activity tests keep
asserting Go to Messages on the page cards. The help guide never names
Go to Messages, so it needs no change.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Signed-off-by: mtoohey <[email protected]>
Signed-off-by: Matt Toohey <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants