Add native shared tab-row tools protocol
Native shared tab-row tools (PR a)
Build the native mechanism for content-supplied trailing tools in the shared tab row. Agent pages publish a bounded declarative list with pane.tabRowTools.set; native PaneToolbarView renders symbols, toggles, badges and press-open menus, and sends tabRowToolInvoked {id, menuItemId?} back through the page host. The tabRow event now includes nativeRowTools so the publisher can gate its layout.
Leo said:
"speaking of that top right buttons section area thing, okay, what do you think about moving it into Swift? Like just going more native with it? Because I just feel like on my fing God, I've ran into so many fing different hacks and stuff just to get this nonsense working. ... we keep running into this nonsense, right? ... And then we could just RPC it or whatever the f*** into TypeScript sometimes. But I feel like, okay, more native buttons and stuff, maybe that might be nicer."
The migration tunable is chrome.tabs.nativeRowTools, default OFF while this series lands. This PR does not remove the existing web tools hole or clearance CSS. The final series PR will flip the default and remove both together so the migration cannot stall behind a Debug switch.
Risk: normal. Swift cannot be built on this VM; python3 scripts/cmux-next/prepush-gate.py passed locally. A standalone SwiftFormat binary is unavailable here. Added decoding bounds tests and the tab-row event/op coverage. Fleet compile and Swift suites will be run by the coordinator.
Leo's standing direction:
"Like you need to be more ambitious, really. Like the whole dynamic workflow situation. I don't know if you already have the UI for that, how good it is, if you guys have tested it out yet. But, you know, we need to have that. And likewise, obviously, like the session info area, like that's where the things can be shown, and also the right tab area. All of these, like better and better UI. Just go ahead, man. I feel like you can do a hell of a lot more. More codex, more Claude, more whatever. We have the capacity, so let's use the fing capacity to go do some more productive fing work, right?"
Menu rows are page-declared actions: native returns their IDs and the page owns execution, like WebContextMenu. The menu-action baseline explicitly allows this one row builder; the checker and other allowances are unchanged. Keyboard Space and VoiceOver open the same press menu as a mouse press.
Validation at 909b6a9b2c3a46847d6feed5e79ac1c697565d62: menu-action guard, prepush gate and diff whitespace check pass locally. The new native keyboard-menu regression test requires the Mac suite. The prior aggregate check's No new SwiftUI failure reproduces identically on base 920ece18da6218fb2e2376feaffce0eb50594417: HomeChatColorsPanel.swift and HomeChatColorsView.swift import SwiftUI outside the allowlist. The prior fast-tier failure is artifact upload ETIMEDOUT; its execution outcome is separate from upload evidence.
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Adds the native protocol for content-supplied tools in the shared tab row, moving chat header controls from a web-rendered overlay into native Swift buttons.
- Agent pages publish declarative tools via
pane.tabRowTools.set;PaneToolbarViewrenders them as symbols, toggles, badges, and press-open menus, and sendstabRowToolInvoked {id, menuItemId?}back through the page host. - The toolbar follows the selected page's model through tab switches, first-paint holds, and AppKit reparenting; pane retirement and page close clear the ownership callback, a page reload drops the old page's tools, and menu-bearing tools respond to keyboard and VoiceOver activation, refresh their tint on toggle, and route presses through the page's gesture tracker.
- The
tabRowevent now includesnativeRowToolsso the publisher can gate its layout; native tools only render for the shared page host with a return event stream. - When a narrow pane cannot fit every native button, the non-fitting ones fall back into the "…" overflow menu, which chat panes now show; disabled tools stay in the menu.
- Strict decoding bounds (16 tools, 32 menu items per menu, 256 across all tools and nesting, 2 menu levels, 64-char text, 256-byte text) reject malformed payloads; optional badge, checked, and role fields may be absent.
- Gated behind
chrome.tabs.nativeRowTools(default OFF); the existing web tools hole and clearance CSS stay until the final PR of the series flips the default and removes both together.
Migration
No action needed while the tunable is off. A final PR in the series will flip the default and remove the web tools hole and clearance CSS.
Capture tour-agent-pane at 1ade7ac0e9d4 (fleet build, capture mini, text checked for private data)
| Light | Dark |
|---|---|
![]() | ![]() |
Agent session: agent session

