Skip to content

Make the navigation rail the only sidebar layout and remove the sidebar navigation plugin API - #5229

Merged
SawyerHood merged 1 commit into
mainfrom
bb/enable-the-rail-experiment-on-mobile-thr_4478xd9vtf
Oct 8, 2026
Merged

SawyerHood merged 1 commit into
mainfrom
bb/enable-the-rail-experiment-on-mobile-thr_4478xd9vtf

Conversation

@SawyerHood

Copy link
Copy Markdown
Collaborator

Human comments

What was wrong

The navigation rail shipped as the default-off navigationRail experiment and only on wide windows, so bb carried two sidebar layouts: the rail, and the older navigation rows at the top of the sidebar with a plugin API for replacing them. The rail is becoming the default, which leaves the rows, their replacement slots, and the settings that pick between providers with nothing to render.

What changed

The rail is the only sidebar layout, on every screen size.

  • AppLayoutSidebar has one path. On narrow windows and phones the rail sits inside the drawer: Home, Plugins, Skills, and Settings swap the list beside it and leave the drawer open, and a plugin page closes it. Customize rail opens as a sheet from More.
  • The navigationRail experiment key is removed from @bb/domain, Settings → Experiments, and the docs. A stored row for it is ignored.
  • The "Back to app" rows, the section titles above the Settings/Plugins/Skills lists, and the footer's built-in Settings action are gone; the rail's Home and Settings replace them.

Removed plugin API (@get-bb/plugin-sdk, bumped to 0.6.33).

  • app.slots.experimental_sidebarNavigation
  • experimental_useSidebarNavigation, experimental_useSidebarNavigationSplit, experimental_SidebarNavigationIcon
  • app.slots.experimental_sidebarHeader. It only mounted without the rail, where New thread now always takes the header.
  • Every ExperimentalSidebarNavigation* and ExperimentalSidebarHeader* type, and the testing-harness support for them.

Plugins that call these stop working. docs/api_to_audit.md named Compact Nav 0.1.x as a released consumer of the navigation slot.

Removed with it.

  • The built-in Navigation plugin (plugins/navigation) and the examples/plugins/sidebar-navigation example, with their registry, turbo, lockfile, demo-server, and marketplace entries. The server drops an installed copy of the built-in at startup.
  • UI preferences sidebar.navigationProvider and sidebar.headerProvider, and the Appearance → Navigation and Header pickers. Stored rows under those keys are ignored; a server test pins that.
  • The app's navigation model keeps sidebar.pluginPanelOrder and sidebar.visiblePluginPanels, which now order and show or hide rail destinations. Its types moved from the SDK into the app.

Left in place, now unused. PluginNavPanelRegistration.experimental_sidebarAccessory is still accepted by the SDK, but no host surface mounts it because the rail is icon-only. The docs say so. Removing it, or drawing it on the rail, is a follow-up decision.

Behavior that goes away. The navigation rows showed a mini-map when a panel was open in a split; the rail does not. Theme Preview's mock sidebar still does not draw a rail; only its "Back to app" row and "Settings" label were removed so its anchors match the app.

Docs. docs/configuration.md, docs/api_to_audit.md, the bb guide (app-settings.md, bb-guide-customization.md, bb-guide-plugins.md, the plugin-authoring references), and the Plugin Guide surfaces and wireframes describe the rail as the standard layout and no longer list the removed API. No wire change between server and host daemon.

How you verified

  • pnpm exec turbo run typecheck lint test --continue across the repo: all tasks pass. After the last rebase onto main, which touched only the app, Theme Preview, and docs, I re-ran those two packages. Two tests timed out under the full parallel run on my machine and pass on their own (ToolsView.plugin-detail.test.tsx, plugin-native-server-loading.test.ts); neither touches the sidebar.
  • pnpm exec turbo run smoke:tarball smoke:boot --filter=bb-app: both pass, expected built-ins running.
  • packages/plugin-sdk/scripts/check-npm-version-guard.mjs and .github/workflows/check-plugin-sdk-version.mjs pass at 0.6.33.
  • Tests added or rewritten: the rail inside the compact drawer and body swaps with the drawer open (AppLayoutSidebar.test.tsx); Customize from More on a compact viewport, which destinations dismiss the drawer, nested plugin routes, the Automations destination, and remembered panels before and after plugins settle (AppNavRail.test.tsx); retired preference keys (public-ui-preferences.test.ts). The compact Customize test fails without the fix.
  • Real dev app in headless Chromium at 1280×800 and at iPhone 14 size, on a data dir that had the old built-in plugin and a stored experiment value: the rail shows by default, the old rows and "Back to app" are gone, Appearance has no Navigation or Header picker, Experiments has no Navigation rail entry, the list swaps with the drawer open, a plugin page closes the drawer, long-press and More both open Customize, and there are no page errors.
  • Not verified: the macOS desktop framed title bar on a real Mac (unit tests only), the hosted demo, and iOS Safari or the native mobile shell.

🤖 Generated with Claude Code

AGENT GENERATED

…igation plugin API

The rail was the navigationRail experiment on wide windows. It now draws on
every screen size, including inside the compact drawer, and the experiment
key is gone.

With the rail always on, the navigation rows at the top of the sidebar had
no renderer left, so they are deleted along with everything that fed them:

- app.slots.experimental_sidebarNavigation, experimental_useSidebarNavigation,
  experimental_useSidebarNavigationSplit and experimental_SidebarNavigationIcon
- app.slots.experimental_sidebarHeader, which only mounted without the rail
- the built-in Navigation plugin and the sidebar-navigation example
- the sidebar.navigationProvider and sidebar.headerProvider preferences and
  their Appearance pickers
- the footer's built-in Settings action, the Back to app rows, and the
  non-rail sidebar shells

In the compact drawer, Home, Plugins, Skills and Settings swap the list
beside the rail and leave the drawer open; a plugin page closes it.
Customize rail opens as a sheet from More.

PluginNavPanelRegistration.experimental_sidebarAccessory is still accepted,
but no host surface mounts it.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@SawyerHood
SawyerHood marked this pull request as ready for review October 8, 2026 20:57
@SawyerHood
SawyerHood merged commit ff94848 into main Oct 8, 2026
48 checks passed
@SawyerHood
SawyerHood deleted the bb/enable-the-rail-experiment-on-mobile-thr_4478xd9vtf branch October 8, 2026 21:26
brsbl added a commit that referenced this pull request Oct 8, 2026
Brings in #5222 after #5228 removed the welcome page and checklist card
and #5229 removed the navigation plugin. experimental_setupComplete still
comes from useSetupChecklist, which drives the remaining setup banner.
Plugin SDK moves to 0.6.35, one above the base's 0.6.34.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hxy91819 added a commit to hxy91819/bb that referenced this pull request Oct 12, 2026
Absorbed by desktop-v0.46.0:
- fix/acp-permission-mode: upstream get-bb#4922
- fix/sidebar-touch-hover-actions: upstream get-bb#5097
- feature/sidebar-pinned-new-thread: upstream get-bb#5229 nav rail layout
- feature/automation-auto-marker: upstream Automation timeline row (get-bb#4763)
- fix/mobile-composer-top-clearance: upstream get-bb#5026
- fix/mobile-model-drawer: upstream 8a01b97

Dropped: fix/acp-fast-mode, fix/acp-codex-goal (ACP Codex no longer used);
fix/mobile-model-picker folded into fix/provider-icon-hitbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
benJephunneh added a commit to benJephunneh/bb-overlay that referenced this pull request Oct 13, 2026
bb 0.46.0 removed the sidebar-header surface (get-bb/bb#5229), so HeaderMark is
skipped on current bb. Say why on the console, so a missing mark reads as a change
in bb rather than a broken plugin.

The docs told people to pick it too: README step 2 and INSTALL step 2 both listed
"Sidebar header: NavAIgate" under Settings, Appearance, which no longer exists.

For the record, the surface lived in bb 0.44.0 and 0.45.0 and was gone in 0.46.0 —
the same window this plugin's own engines.bb >=0.44 and README described.
benJephunneh added a commit to benJephunneh/bb-overlay that referenced this pull request Oct 13, 2026
bb 0.46.0 removed the sidebar-header surface (get-bb/bb#5229), so HeaderMark is
skipped on current bb. Say why on the console, so a missing mark reads as a change
in bb rather than a broken plugin.

The docs told people to pick it too: README step 2 and INSTALL step 2 both listed
"Sidebar header: NavAIgate" under Settings, Appearance, which no longer exists.

For the record, the surface lived in bb 0.44.0 and 0.45.0 and was gone in 0.46.0 —
the same window this plugin's own engines.bb >=0.44 and README described.
brsbl added a commit that referenced this pull request Oct 14, 2026
#5229 put the navigation rail inside the compact drawer and dropped the
header's macOS start inset, so in windows under 768px New thread sat
under the traffic lights and the sidebar toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brsbl added a commit that referenced this pull request Oct 14, 2026
#5229 put the navigation rail inside the compact drawer and dropped the
header's macOS start inset, so in windows under 768px New thread sat
under the traffic lights and the sidebar toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymichael added a commit that referenced this pull request Oct 14, 2026
…#4992)

## Human comments

## What was wrong

BB command and plugin documentation was duplicated across guide
chapters, shipped skills, and repository docs. Updating one surface
could leave conflicting instructions elsewhere, while completed plans
and historical audits obscured current references.

## What changed

- Make `bb guide` the core CLI manual and reduce the `bb-cli` skill to
chapter routing and agent guidance.
- Move plugin-specific commands and settings into their owning skills,
including ACP configuration, notifications, sidebar preferences, and
workflows.
- Remove the standalone automations chapter and route `bb guide
automation` and `automations` to the plugins chapter.
- Split the threads chapter by task so an agent reads only what it
needs: `threads` (spawn, hand off, fork, edit), `thread-inspection`
(list, inspect, wait, open), `thread-messaging` (tell, metadata,
interactions, queue), and `thread-lifecycle` (stop, clear, compact,
retry, archive, delete). Each is 90–175 lines instead of one 530-line
page; aliases such as `queue`, `retry`, and `inspect` route to the right
chapter.
- Consolidate plugin API guidance and trim repository docs to living
references, removing completed plans, obsolete audits, and unused
assets.
- Update documentation expectations and construct workflow test fixtures
from the actual settings defaults.

The branch is rebased onto `origin/main`, preserving its newer
documentation. Runtime changes are limited to guide chapter routing and
aliases; there are no daemon wire changes.

## How you verified

- Rebased onto `origin/main` at 1859b76. Main's newer guidance went
into the consolidated destinations, including:
- Settings: `keepHistoryAfterContextClear`, onboarding replay and `bb
project discover`, `bb settings cli-command`, `bb settings usage
--refresh`, the `timelinePush` experiment, and the always-on navigation
rail.
- Plugins: `bb plugin prune`, background plugin updates, and `bb
marketplace add --subdirectory`.
- Threads and providers: `bb thread commands`/`options`, `usage.cost`,
push-notification levels, `bb provider-retry explain`, and OpenCode
agents as ACP modes.
- Plugin API: `environment.removed`, `experimental_saveFile`, the
tokenizer-based `experimental_scanPublicSdkOnly` (#5518),
`experimental_optionLabels`, the provider bridge's 50 ms text batching,
and its session-option state kinds.
- Removed documentation of the sidebar navigation and header plugin APIs
that main deleted (#5229).
- Deduplicated `docs/configuration.md` (one statement per setting or
plugin), folded the dated sections of `docs/ci-performance.md` into its
topical sections, and restored the core-callers notes in
`docs/api_to_audit.md` that AGENTS.md requires.
- Built the CLI and ran `bb guide` with each new chapter, the
`queue`/`retry`/`inspect`/`messaging` aliases, and an unknown chapter.
- Checked that inbound anchor links to the rewritten docs still resolve.
- `pnpm exec turbo run test --filter=@bb/templates
--filter=@get-bb/plugin-sdk --filter=@bb/sdk
--filter=bb-plugin-workflows`: passed.
- `pnpm exec turbo run test --filter=@bb/cli --filter=@bb/server --
src/__tests__/command-output/guide.test.ts
src/__tests__/plugin-guide-docs.test.ts
test/services/plugins/plugin-authoring-docs.test.ts`: passed.
- `oxfmt --check` on every changed Markdown file: clean.

> AGENT GENERATED

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: qa <qa@x>
brsbl added a commit that referenced this pull request Oct 15, 2026
#5229 put the navigation rail inside the compact drawer and dropped the
header's macOS start inset, so in windows under 768px New thread sat
under the traffic lights and the sidebar toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brsbl added a commit that referenced this pull request Oct 15, 2026
…ar drawer (#5495)

## Human comments

## What was wrong

In macOS desktop windows narrower than 768px, New thread in the sidebar
drawer sits under the traffic lights, and the sidebar toggle draws on
top of it (reported on Discord after desktop-v0.46.0). #5229
(`ff9484883`) moved the navigation rail into the compact drawer and
dropped the macOS start inset from `SidebarTopReserveRow`. The drawer's
header row now starts right after the rail, at x=52. That is under the
lights (x=18–78), and the sidebar toggle, fixed at x=84–112, overlaps
it.

## What changed

- `SidebarTopReserveRow`
(`apps/app/src/components/sidebar/SidebarChrome.tsx`) pads the drawer's
header row so New thread starts at x=116, just after the sidebar toggle.
That is where it sat in 0.45.0.
- The padding applies only on macOS desktop, in the compact drawer (not
the framed sidebar), and outside full screen, where there are no traffic
lights.
- Wide framed windows, browsers and other platforms are unchanged. No
wire, CLI or contract changes.

## How you verified

- New `SidebarChrome.test.tsx`: the compact macOS drawer reserves the
space, while the framed window and a compact browser window don't. CI
failed with only the test ([run
38601538235](https://github.com/get-bb/bb/actions/runs/38601538235),
app-8: "expected false to be true") and passes with the fix.
- Real Mac (macOS 26.5.2), using the Electron desktop dev app built from
`main` (before) and from this branch (after), with the same seeded
thread. The window was resized natively to 700×800 with the sidebar
drawer open, and to 1100×800.
- **700px:** New thread moves from x=52–287, under the lights and the
toggle, to x=116–287. The hit test at its center returns New thread.
  - **1100px:** the framed layout is identical before and after.
- The colored dots are stand-ins drawn at the traffic lights' native
position (18, 18). The native buttons can't be captured without Screen
Recording permission.
- Not covered: a narrow window in native full screen, where the padding
is off by design because there are no lights.
- Remote CI runs the tests; nothing was run locally.
- CI: every job passes except the plugin SDK npm version guard in
Checks. Plugin Fork Check was skipped by change-based selection. The
guard fails because `@get-bb/plugin-sdk@0.6.43` was published to npm at
15:11 UTC today, and building the SDK from `main` now produces a
different `dist/provider-bridge-testing.js`. This PR doesn't touch the
SDK. Every PR based on current `main` without a version bump fails the
same way (for example #5490 and #5443), and #5492 passes because it
bumps to 0.6.44. It clears once a bump lands on `main` and this PR's CI
reruns.

| Screen / state | Viewport | Before | After |
| --- | --- | --- | --- |
| Thread · sidebar drawer open (zoom) | macOS desktop · 700×800 |
![Before 700
zoom](https://github.com/user-attachments/assets/1f708c7d-f2aa-42ee-aa2d-c5043d2468ed)
| ![After 700
zoom](https://github.com/user-attachments/assets/793b9443-c4e1-463f-a2e6-31c785b87891)
|
| Thread · sidebar drawer open | macOS desktop · 700×800 | ![Before
700](https://github.com/user-attachments/assets/379ba908-be84-4d51-aa75-654ff175ff77)
| ![After
700](https://github.com/user-attachments/assets/ffa9aebd-8e67-4d79-b9db-c46057e63433)
|
| Thread · framed sidebar (unchanged) | macOS desktop · 1100×800 |
![Before
1100](https://github.com/user-attachments/assets/a77833bb-81f7-4b5f-9546-fd5fb4a0c6b7)
| ![After
1100](https://github.com/user-attachments/assets/1327b504-d9f3-4e91-8706-a83257371042)
|

### Merge order with "Compact the macOS app frame and move headers into
the title bar" (#5529)

Resolved: the PRs can merge in either order. #5495 used to pad the
narrow-window drawer header with a literal `88px`, which assumed the
sidebar toggle sits at the 84px reserve; with #5529's wider reserve New
thread would have started under the toggle (measured at an earlier 88px
reserve: New thread at x=112 under the toggle at x=88–116). #5495 now
includes `5bd8c8b85`, which derives that padding from
`--bb-macos-traffic-light-reserve` (falling back to 84px), so New thread
starts 4px after the toggle under either geometry. Measured on a real
Mac at 700px:

| Build | Sidebar toggle | New thread |
| --- | --- | --- |
| #5495 head `5bd8c8b85` on main | x=84–112 | x=116 |
| #5529 head `96084fc15` + #5495 | x=87–115 | x=119 |

BB-Thread-ID: thr_eigbyjruhs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

> AGENT GENERATED

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ymichael added a commit that referenced this pull request Oct 15, 2026
The navigation region is a nav element again, as it was before #5229, so
plugins that find their column with closest("nav"), such as Nav Rail, dock as
designed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymichael added a commit that referenced this pull request Oct 16, 2026
The navigation region is a nav element again, as it was before #5229, so
plugins that find their column with closest("nav"), such as Nav Rail, dock as
designed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymichael added a commit that referenced this pull request Oct 16, 2026
The navigation region is a nav element again, as it was before #5229, so
plugins that find their column with closest("nav"), such as Nav Rail, dock as
designed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ymichael added a commit that referenced this pull request Oct 16, 2026
…ents (#5584)

## Human comments

## What was wrong

#5229 (0.46.0) made the icon rail the only sidebar navigation and
removed the plugin API that let a plugin draw it
(`experimental_sidebarNavigation`, `experimental_sidebarHeader`, and
their hooks).
- Users who preferred labeled rows had no way back (#5360).
- Navigation plugins on the marketplace stopped loading: Nav Rail,
Compact Nav, Collapsible Navigation, Slim Nav, Sidebar Subtitles, and
Herdr commands (#5376).
- Panel counts had nowhere to show, because the rail is icon-only and no
longer mounted `experimental_sidebarAccessory` (#5327). 30 bb-community
plugins draw one.

The old slot only covered rows above the thread list, so the rail and
the slot could not coexist.

## What changed

**One navigation slot with a declared placement.**
- `app.slots.experimental_sidebarNavigation` is restored under its
pre-0.46 names. Registrations declare `placement: "rail" | "list"`;
`list` is the default, so older plugins keep working.
- bb lays out the sidebar from the placement before the provider
renders:
- **rail:** a fixed column that stays when the sidebar collapses, New
thread in the header and Settings at the bottom of the column.
- **list:** rows above the thread list, the footer in the same column
after the thread list with a Settings action, Back to app rows on the
Settings, Plugins, and Skills lists, a collapse that hides the whole
sidebar, and the header slot.
- Both placements use the same macOS window frame on wide viewports.
Switching navigation keeps the title-bar controls in place and Settings
Search at the same height; sidebar headers do not reserve an empty
window-control gutter below the title bar. Providers without header
controls use only an 8-pixel top inset instead of reserving an empty
48-pixel header row. Compact windows retain the floating toggle.
- bb's Top list keeps the 0.45 row affordances: a hover "…" options
button (always shown on touch devices) with the same menu as
right-click, the split pane map beside a row's label when its page is
open in a split, and More only when a destination is hidden.
- bb's Top list pins New thread and More and scrolls the destinations
between them, capped near 70% of the window with fades at the scroll
edges, so many plugin panels or a short window can't push the thread
list out of view (the pre-0.46 rows could). The shared region stays
uncapped so plugin providers manage their own height.
- bb's own **Rail** (`navigation/rail`, the default) and **Top list**
(`navigation/top-list`) are the bundled Navigation plugin (see below),
so they use exactly the contract a third-party provider gets.
- The region is a `<nav>` element again, as before #5229, and list
placements keep the footer after the thread list in the same column, as
0.45 did. Plugins that find their column with `closest("nav")` and inset
what follows, such as Nav Rail, therefore dock with the footer beside
the rail.
- Picking a provider (`sidebar/sidebarNavigationProvider.ts`):
- `sidebar.navigationProvider` (Settings → Appearance → Navigation)
selects Automatic or a provider by plugin key.
- Automatic uses the first provider from a plugin the user installed,
else the first built-in one (Rail). A pinned provider that is missing
once plugins settle falls back the same way; with no provider at all the
sidebar uses the list placement and says no navigation plugin is
enabled.
  - Legacy `__builtin__` and `navigation/navigation` read as Automatic.
- Before plugin frontends settle, a plugin provider's last placement is
reserved, so a reload does not flash the rail.
- A crashing provider or header is replaced by the built-in provider for
its placement, with one toast.
- `experimental_Original` renders the built-in provider for the same
placement, or nothing when the Navigation plugin is disabled.

**Rail and Top list are a bundled, forkable plugin**
(`plugins/navigation`).
- The plugin registers both providers, plus Rail's New thread button as
its `headerComponent`, using only `experimental_useSidebarNavigation`,
`experimental_useSidebarNavigationSplit`,
`experimental_SidebarNavigationIcon`, and registry components. It is
default-enabled, on `scripts/forkable-plugins.json`, and served by the
demo server.
- The host keeps only what surrounds a provider: the placement layout
(including the rail's top inset), Settings, the customize editor, the
navigation model, and badge collection. The macOS window frame is
independent of navigation placement, and navigation headers sit below
the title bar on wide macOS windows.
- The shortcut pill, overflow fade, and split-pane mini-map move into
shared-ui and the component registry, so the app, Navigation, and Thread
list share one copy each (Thread list drops its private copies).

**Built-in providers come from the install source.**
- The app records which plugins were installed as built-ins from the
plugin list. Every replacement setting (thread list, navigation, source
code, diffs) labels their providers "(built-in)" and lists them after
installed plugins, and Automatic prefers a provider from an installed
plugin, then slot order. No per-slot constants remain.
- Monaco is a built-in plugin, so it now shows as "(built-in)" in the
Source code and Diffs settings, and Automatic prefers a third-party
renderer over it.
- The bundled Thread list option drops its "BB default." description;
the Automatic row already names what it chooses.
- The Navigation setting hides when no navigation plugin is installed,
like the thread list setting, and settings search uses the matching
condition.

**Shared model** (`SidebarNavigationModel.tsx`,
`lib/plugin-sidebar-navigation.ts`):
- `experimental_useSidebarNavigation()` returns `isHomeActive`, and its
actions include `goHome()`, `setOrder()`, and `openCustomize()`.
`openCustomize()` opens bb's editor in a popover beside any provider,
after open menus close, and returns focus to the control that opened it.
bb's menus and the editor call it "Customize navigation" on every
provider.
- Each panel's `experimental_useBadge` value is in the model as
`item.badge`. The badge sources mount once in the model instead of in
the rail.

**Badges (supersedes #5524).**
- This PR includes #5524's value-based `experimental_useBadge` and its
compatibility handling for `experimental_sidebarAccessory` (the field is
dropped with a warning), plus Tasks' migration to the hook.
- `ExperimentalBadge` is `{ count?, text?, tone?, label }`:
- `text` is a short visible value of at most 8 characters, such as
"NEW", "73%", or "2 down", and cannot be combined with `count`;
- `tone` is `neutral` (the default), `warning`, or `critical`, and bb
owns the colors.
- The fields follow the 30 bb-community plugins that drew
`experimental_sidebarAccessory`: 12 drew one count, 8 several numbers or
a fraction, 5 a short status, 3 a percentage, and 18 used red, amber, or
an accent color for state.
- Drawing:
- Fills are solid theme colors: muted gray for neutral, attention amber
with a new `--attention-foreground` for warning, and destructive red for
critical.
- The rail draws counts (capped at `9+`) and a tone-colored dot for
text, each cut out of the icon by a ring in the rail's own background.
- The Top list and More menu draw the count (capped at `99+`), the text,
or a dot.
- More's dot takes the strongest hidden tone, and the label is in every
accessible name.
- Plugins written before 0.46 that drew counts from the item's old
`experimental_Accessory` field show none until they read `item.badge`.

**Header.** A navigation's optional `headerComponent` renders in the
sidebar header row while it is active, replacing the separate
`experimental_sidebarHeader` slot and its `sidebar.headerProvider`
setting; that slot remains as an untyped runtime alias so a pre-0.46
plugin's header joins its navigation. The thread list setting is now
**Sidebar thread list**.

**Plugin SDK 0.6.53.**
- Restored types and runtime exports.
- `ExperimentalBadgeTone` and the new badge fields.
- Collector validation for `placement`.
- Test-harness support (the `sidebarNavigation` option and
`sidebarNavigationCalls`).
- Tasks now requires `>=0.6.53`. No server/daemon wire change.

**Docs.**
- `docs/configuration.md`, the customization guide, and the
plugin-authoring references (new `frontend-sidebar-navigation.md`, plus
`frontend-core-slots.md` and the API indexes).
- `docs/api_to_audit.md` entries with stabilization items and the core
callers on the same path.
- A Plugin Guide "Sidebar navigation" surface on the rail fixture, and
verify-bb rows for Top list and navigation/header plugins, including
disabling the Navigation plugin.
- The navigation docs, SDK doc comments, and renderer slot docs describe
the bundled Navigation plugin, the `navigation/*` keys, and the
built-in-aware Automatic rule.

## How you verified

- Empty header correction (`8cee6a05da`): the new regression test fails
before the fix; all 24 affected sidebar, header, and Settings tests pass
after it, along with app lint and typecheck. The rendered macOS
simulation confirms an 8-pixel inset above Top list and the retained
48-pixel Settings Search row.
- Desktop spacing fix (`fb133df5d9`): both regression tests fail before
the fix and pass after it. The 62 focused app layout, sidebar
chrome/header, and Settings tests pass; app lint and typecheck pass. An
isolated browser with simulated macOS chrome confirms Rail and Top list
use identical title-bar/toggle coordinates and Settings Search height,
with no extra window-control gutter. Compact windows retain their
floating toggle. This renderer check does not verify native Electron
window behavior.
- Windows CI timeout fix (`ae0adb0fa6`): the two ACP restart tests use
the same 30-second allowance as similar process-restart tests. All 499
ACP tests pass locally (4 skipped), along with lint and typecheck;
Windows confirmation remains with CI.

- Full typecheck, lint, and test run is left to CI on this branch
(rebased onto `399d63d277`). The rail and its Settings cell keep the
spacing from #5529 (compact macOS frame) and #5609 (row-rhythm
alignment), and the app typecheck passes after the rebase. Locally, the
affected app, SDK, Plugin Guide, Tasks, guide, mobile, and server suites
passed before the last rebase; the mobile theme and `global.css` were
regenerated for the new `--attention-foreground` token.
- `check-plugin-sdk-version.mjs` and `check-npm-version-guard.mjs` pass
at 0.6.53.
- Navigation plugin commit (`5a0cc8d599`):
- `scripts/check-plugin-forks.mjs plugins/navigation
plugins/thread-list`: both copies install, typecheck, test, and `bb
plugin build` outside the monorepo with published packages only (Thread
list passed on a re-run after one vitest worker start timeout under
load).
- Turbo typecheck and lint pass for the app, both sidebar plugins,
shared-ui, plugin registry, server, demo server, domain, SDK, Plugin
Guide, and templates. Tests pass for Navigation (14), Thread list,
Plugin Guide, plugin registry, demo server (which now serves both
sidebar plugins), the server's builtin-registry and UI-preference
suites, and 229 app test files across settings, lib, sidebar, code,
layout, and plugin. One app file (`PluginSettings.test.tsx`) failed
under the parallel run and passed alone.
- The app's Rail and Top list integration tests now load the real plugin
through `test/fixtures/navigation-plugin.ts`; the plugin's own drawing
(count caps, text badges, More's tone, menus, the header button) is
tested portably in `plugins/navigation/app.test.tsx`.
- After rebasing onto `399d63d277`: turbo typecheck and lint pass for
every package affected relative to main (155 tasks); Navigation, Thread
list, plugin registry, and 231 app test files pass.
- Ran `pnpm start:worktree` with the bundled plugin and the installed
Nav Rail, Compact Nav, and Collapsible Navigation plugins. I confirmed
the server and plugins come up, but did not repeat the visual pass below
after this commit.
- New and updated tests:
  - provider resolution (`sidebarNavigationProvider.test.ts`);
- plugin providers on the real SDK path: list placement, badges,
`openCustomize`, pinned built-ins, crash fallback, and Original
(`SidebarNavigationHost.test.tsx`);
- Top list rows, text and tone badges, the More dot, and Customize focus
(`SidebarNavigationList.test.tsx`);
- list placements keep the footer after the navigation in one column
(`AppSidebar.test.tsx`);
- the rail on the provider host, including invalid badge values (zero
count, count plus text, text over 8 characters, unknown tone), text
drawn as a toned dot, and More's strongest tone
(`SidebarNavigationRail.test.tsx`);
- the header slot, Back to app routing, and the last-known preference
store;
- SDK harness and placement validation, and the server reading stored
pre-0.46 provider rows.
- Manual checks with `pnpm start:worktree` in headless Chromium at
1440×900 (light and dark) and 390×844, plus the packaged macOS desktop
app (`pnpm desktop:worktree`), with Rail and Top list on the framed and
unframed windows:
- Installed from bb-community, unmodified: **Nav Rail**, **Compact
Nav**, and **Collapsible Navigation**. Each loads and draws its
navigation; Nav Rail docks as a vertical rail with the footer beside it
and moves New thread into the header; Compact Nav and Collapsible
Navigation also work as header providers.
- Installed the deleted `examples/plugins/sidebar-navigation` plugin:
Customize, Original, the crash fallback, pinning Rail over it, a reload
without a rail flash, and removal falling back to Rail.
- A local plugin with four badged panels (critical text, warning count,
warning text, neutral text) renders as intended on the rail and in the
Top list in both themes.
- Not verified: iOS Safari and the native mobile shell; the header
alignment on macOS after the header moved into the plugin. A pinned
plugin key that is not installed shows an empty rail-width column on the
first load until frontends settle, then falls back.

**Follow-up commits on this branch.**
- `fb133df5d9` keeps the macOS window chrome stable when switching
between rail and list placements (`AppLayout.tsx`, `SidebarChrome.tsx`,
with tests and docs).
- `8cee6a05da` removes the empty header row above Top list navigation
(`AppSidebar.tsx`, with a test).
- `ae0adb0fa6` gives the ACP restart tests enough time on Windows
(`provider-bridge-acp-next` test timeouts only).
- CI is green on `8cee6a05da`: 48 checks passed or skipped.

Supersedes #5524.

Fixes #5360
Fixes #5327

🤖 Generated with [Claude Code](https://claude.com/claude-code)

> AGENT GENERATED

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant