Repository navigation
cmux NEXT: agents mark the tab where you must act (cmux attention request, tab-attention-v1) - #24286
Conversation
…-attention-v1)
`cmux attention request --tab <tab_…> --reason <text>` and `cmux attention
clear --tab <tab_…>` send `tab.update {attention}` (MCP tab_update with
attention). The daemon keeps `{reason, at_ms}` on the tab record and every
client sees it as the tab's extra.attention. It never moves focus. The mark
clears on the agent's clear, when a browser tab's page goes to another URL
(frontend-rendered and CDP browsers), or when the tab closes, so a reopened
tab does not ask again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on 44fc3d3 to compare; do not merge until green; see lane-rules |
|
Bead |
|
Found 8 test failures on Blacksmith runners: Failures
|
- The CDP event thread now compares the page URL against the one it last saw after target-info, frame and same-document navigation, so a mark clears even when another setter moved the URL first. Test added. - clippy: slice::from_ref; rustfmt the eprintln. - CLI test asserts the real 'not an id' message. - Bad-value test uses short idempotency keys. - The reason limit is 200 UTF-8 bytes, matching the catalog's max_length. - Help no longer names palette UI this PR does not ship. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
|
Review (claude sonnet, correctness first): SHIP at a6e4474 Independent re-review by a different model (Claude Sonnet; the lane runs Opus), after the BLOCK at 78947df. Read-only checks: git diff, grep, Previous BLOCK items, all fixed:
worker.rs: the per-thread Non-blocking:
|
|
|
…, in its commit Review (codex xhigh) BLOCK at 53b2f38: - The CDP worker seeded its last-seen URL from the first event, so a mark set before the worker saw the old page survived a navigation whose URL moved first. - The navigation clear read the mark, then cleared it in a later commit, so a mark an agent set on the new page in between was dropped. A browser tab's mark now records the page it was set on (attention_json.page, not shown in extra.attention). The clear runs one conditional UPDATE in its commit: it drops the mark only when the mark's page differs from the page the tab is on, so a late or repeated clear for the new page keeps that page's mark, and the worker's first event always asks. The worker's seen URL now only skips the read for a page it already asked about. Also: the Rust SDK's TabUpdateOptions gains attention (set and clear), and a reason with U+2028 or U+2029 is refused as more than one line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
…rowser.rs imports in cargo fmt order Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
… SDK refuses a multi-line reason The navigation clear now decides in its commit against the tab's current page: a late callback for a page the tab already left clears nothing, so a mark the agent set on the new page stays when two navigations overlap. The Rust SDK refuses what the daemon refuses (a control character, U+2028 or U+2029). The worker's page-change check takes its clear as a closure, so its test proves the clear is asked once per page. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
|
|
|
|
Review (codex xhigh, correctness first): SHIP at 12f9a15 No findings. Independent review by a different model (Codex gpt-6.1-sol at xhigh on cmux16, diff-only, read-only sandbox). It checked that each finding of the earlier BLOCK at a3d0d8c is fixed: a stale navigation clear now checks the current page, the SDK refuses a multi-line reason, and the worker test records each clear. Checks at this head:
|
|
Shipped in:
|
…umn too, as the migration does tab_marked_unread_column_is_added_and_an_empty_row_is_dropped failed with "SQL logic error": 7e71621 (#24286, tab-attention-v1) made every tab_state update write attention_json, and the fixture table had only the marked_unread column. The fixture now runs add_tab_attention_column after add_tab_marked_unread_column. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… why tab-attention-v1 (the daemon half is #24286): the tab record's extra.attention {reason, at_ms} becomes TabModel.attention, and showsUnread reads it, so the tab's blue dot, the screen bar, the sidebar tab list and the pane's blue ring all show it with no new drawing. The workspace row gets its manual dot and shows the reason as its text line. Going into the pane (a click or a key) or Dismiss Highlight hides the ring; the dot stays until the agent clears the mark, the page changes or the tab closes, and a new request rings again. Mark as Read on the tab also drops the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
… why tab-attention-v1 (the daemon half is #24286): the tab record's extra.attention {reason, at_ms} becomes TabModel.attention, and showsUnread reads it, so the tab's blue dot, the screen bar, the sidebar tab list and the pane's blue ring all show it with no new drawing. The workspace row gets its manual dot and shows the reason as its text line. Going into the pane (a click or a key) or Dismiss Highlight hides the ring; the dot stays until the agent clears the mark, the page changes or the tab closes, and a new request rings again. Mark as Read on the tab also drops the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
… why tab-attention-v1 (the daemon half is #24286): the tab record's extra.attention {reason, at_ms} becomes TabModel.attention, and showsUnread reads it, so the tab's blue dot, the screen bar, the sidebar tab list and the pane's blue ring all show it with no new drawing. The workspace row gets its manual dot and shows the reason as its text line. Going into the pane (a click or a key) or Dismiss Highlight hides the ring; the dot stays until the agent clears the mark, the page changes or the tab closes, and a new request rings again. Mark as Read on the tab also drops the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
… why tab-attention-v1 (the daemon half is #24286): the tab record's extra.attention {reason, at_ms} becomes TabModel.attention, and showsUnread reads it, so the tab's blue dot, the screen bar, the sidebar tab list and the pane's blue ring all show it with no new drawing. The workspace row gets its manual dot and shows the reason as its text line. Going into the pane (a click or a key) or Dismiss Highlight hides the ring; the dot stays until the agent clears the mark, the page changes or the tab closes, and a new request rings again. Mark as Read on the tab also drops the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
… why tab-attention-v1 (the daemon half is #24286): the tab record's extra.attention {reason, at_ms} becomes TabModel.attention, and showsUnread reads it, so the tab's blue dot, the screen bar, the sidebar tab list and the pane's blue ring all show it with no new drawing. The workspace row gets its manual dot and shows the reason as its text line. Going into the pane (a click or a key) or Dismiss Highlight hides the ring; the dot stays until the agent clears the mark, the page changes or the tab closes, and a new request rings again. Mark as Read on the tab also drops the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray
…nd why (carries #24311) (#27962) * cmux NEXT: a tab an agent needs you in shows the unread dot, ring and why tab-attention-v1 (the daemon half is #24286): the tab record's extra.attention {reason, at_ms} becomes TabModel.attention, and showsUnread reads it, so the tab's blue dot, the screen bar, the sidebar tab list and the pane's blue ring all show it with no new drawing. The workspace row gets its manual dot and shows the reason as its text line. Going into the pane (a click or a key) or Dismiss Highlight hides the ring; the dot stays until the agent clears the mark, the page changes or the tab closes, and a new request rings again. Mark as Read on the tab also drops the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * SidebarMapping: keep newestUnread's doc comment on newestUnread Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Attention ring: going into a remote marked tab hides its ring too interacted(_:tabID:) found tabs on this Mac's daemon only, while attentionMarks rings marked tabs on every machine, so a click or a key in a Cloud or SSH tab never dismissed its ring. A tab found on another machine now gets the ring's dismissal, which is this app's own state; its notifications and Mark as Unread keep their daemon's own paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Attention ring: resolve a click or key on the window's own machine; reject a bad at_ms A tab on another machine can share an id with one here (a forked machine keeps its tab ids). Interactions now find the tab in the workspace the window shows, on the machine that owns it, and the hidden-ring state lives on the tab's own model, so one machine's click or Dismiss Highlight never hides another's ring. A mark whose at_ms is missing, negative, fractional or not a number is no mark. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Attention ring: typing in another machine's terminal clears no workspace mark here; tests prove the redraw and the untouched local tab noteTyping's workspace Mark as Unread clear now runs only for a window that shows this Mac's workspace (or none), so a key in a remote terminal never clears a local workspace whose tab shares the id. The ring test checks that hiding the ring wakes its observers, and the two-machine test checks that a click on the remote tab leaves the local tab's Mark as Unread alone. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * TabAttentionTests: the observation flag is nonisolated (onChange is a Sendable closure) Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Test remote attention rings through a delayed strip click Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Keep delayed strip clicks on their originating machine Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Pass the strip fixture readiness condition explicitly Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Test attention ownership through workspace replacement and menu reads Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Bind attention reads to their owner and show clears immediately Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Guard attention clears and ring generations Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Make attention clears conditional and monotonic Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Document revision guarded attention clears Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Persist attention clear revisions across remarks Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * Fix decimal encoding for guarded attention clears Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: import wire decimal parser Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: preflight attention clear capability Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: read nullable attention revision Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: preserve explicit attention targets Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * style: format tab update SDK Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: scope remote highlight dismissal and validate revisions Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * test: read SQLite timestamps as signed integers Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: scope highlight dismissal to its machine and pinned owner Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: serialize machine-scoped highlight debug state Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: provide scheduler in attention test fixtures Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: reject malformed guarded attention timestamps Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: keep attention input ownership lookup indexed Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * test: import attention fixture scheduler module Agent-Session: https://cmux.com/deeplink/agent?id=aid-493104335f660a57687e * fix: guard shared attention interactions by owner request identity Integrate the shared native request-ID contract from 9171431 and cecd056 while retaining machine-scoped dismissal state and client-local attention generation. Clear only the captured owner token and require the capability on the actual sending connection after handoff. Regressions cover coalesced same-clock replacements, stale native mouse release, and legacy transport refusal. Fleet runtime validation is pending the backend-containing integration tree from #27497; no runtime result is claimed. Static verification: nine checks pass; unchanged localization inputs exceed existing debt. Swift #26809 and structural dogfood holds remain. * fix(attention): an older daemon's mark hides its ring on entry and Dismiss Highlight A mark without a request id (a daemon before tab-attention-request-id-v1) stayed ringed until the agent cleared it: going in and Dismiss Highlight skipped it. Hiding the ring is this client's view state, keyed by the client-local attention generation, so it now applies to those marks too. A press whose mark was replaced since is still dropped: a mark without a request id compares the generation captured at the press. The owner clear still needs the id. Fixes the review BLOCK at c27c81c on #24311. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * fix(attention): a remote workspace or tab menu runs every targeted row on its own machine Review BLOCK at 23ffe95 on #27962: only Dismiss Highlight and Mark Tab Unread carried the owner machine, so a remote menu's other rows routed to the first daemon holding the same id. Every menu row that names the right-clicked object now carries its machine, and menu validation checks the row against that machine, as the run does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * fix(attention): a remote workspace menu's rename field renames it on its own machine Review at 44d1031 on #27962: the menu's rows were scoped to the workspace's machine but the identity header's rename field built its own invocation without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * fix(attention): a remote tab's menu rows resolve their pane on the tab's machine Box review BLOCK at 06e3510 on #27962: with the menu's machine on the invocation, routing went to the remote daemon but ActionScope.pane and AppActionContext.paneController still found the first pane holding a same-id tab on any machine, so Reload Tab could reach this Mac's tab. Both now look only on the target's machine when the invocation names one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * fix(attention): name the pane in ActionScope's pane lookup closure (compile) Box review at 8c0b5f5: $0 inside a closure nested in one with a named parameter does not compile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * fix(attention): Move Tab keeps the remote tab model it was given Box review BLOCK at 3e011c0 on #27962: movingTabs looked the tab up again by id across every machine, so with a same-id tab on this Mac shown, Move Tab to New Workspace or Window could move this Mac's tab. It now finds the pane of that very tab model on its own machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * Revert "fix(attention): Move Tab keeps the remote tab model it was given" This reverts commit ad63a5f. Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * Revert "fix(attention): name the pane in ActionScope's pane lookup closure (compile)" This reverts commit 3e011c0. Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * Revert "fix(attention): a remote tab's menu rows resolve their pane on the tab's machine" This reverts commit 8c0b5f5. Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * Revert "fix(attention): a remote workspace menu's rename field renames it on its own machine" This reverts commit a9a4b8b. Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * Revert "fix(attention): a remote workspace or tab menu runs every targeted row on its own machine" This reverts commit 44d1031. Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * fix(attention): a machine-scoped menu row validates against its machine The one part of the reverted 44d1031 that fixed this PR's own code: menu validation rebuilt the invocation without targetMachineID, so a scoped row's title and enablement were checked against a same-id object on another machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * fix(attention): opening a marked tab hides its ring Sol review BLOCK at 5825e87 on #27962 (P2): jump to unread or a banner click opens the tab with the .open trigger, which dismissAttention ignored, so the ring stayed after the person went in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad * refactor(attention): TabInteractionTarget lives in CmuxNextDaemon (app-type guardrail) The type holds only daemon models (TabModel, DaemonStore) and its mark check; nested in NotificationCenterService it grew a CmuxNextApp file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8bf8af53d779b9f5acad --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
) (#32213) * cmux NEXT: a tab an agent needs you in shows the unread dot, ring and why tab-attention-v1 (the daemon half is #24286): the tab record's extra.attention {reason, at_ms} becomes TabModel.attention, and showsUnread reads it, so the tab's blue dot, the screen bar, the sidebar tab list and the pane's blue ring all show it with no new drawing. The workspace row gets its manual dot and shows the reason as its text line. Going into the pane (a click or a key) or Dismiss Highlight hides the ring; the dot stays until the agent clears the mark, the page changes or the tab closes, and a new request rings again. Mark as Read on the tab also drops the mark. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * SidebarMapping: keep newestUnread's doc comment on newestUnread Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * cmux NEXT: Go to What Needs Me, and marked tabs in Needs you A tab an agent marked with `cmux attention request` (tab-attention-v1) now shows in two places, each by the agent's reason, the workspace and the tab title, never an id: - Needs you: a `kind: "tab"` item. AgentPaneAttentionTabs pushes the marked tabs to every agent page (`attentionTabs` host event); its Go to calls `chat.attention.open {tabId}`, which shows only a listed tab through the App's user jump (revealTab). No answers and no side question. - The palette's Go to What Needs Me (`attention.goTo`): a page of the marked tabs, newest first; Return goes through the same Go to. No default key. AttentionTabsWatch observes the store and updates the list; nothing polls. Strings localized in every catalog locale. Leo: "idk where things are man i dont see anything other than the current workspace which is you and you have a cmux next github brwoser tab open (we need to have cmux expose this harder if it isn't already/hve better instructions)" Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * AttentionPalettePage: key the action page by ActionID Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * cmux NEXT: a banner with Show for a tab an agent marked When an agent marks a tab with `cmux attention request` (tab-attention-v1), the app posts one system banner per request: "Workspace › Tab", "Needs you", the agent's reason. Show (or a click) goes to the tab through the same Go to as Needs you and the palette; posting it moves nothing. It follows notifications.* like an agent's notification (desktop mode, muted workspaces, quiet hours, sound), marks made before launch post nothing, and a cleared mark takes its banner back. Leo: "idk where things are man i dont see anything other than the current workspace which is you and you have a cmux next github brwoser tab open (we need to have cmux expose this harder if it isn't already/hve better instructions)" Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Go to What Needs Me: an agent's run opens no palette attention.goTo is a focus action, so an agent-origin `cmux action run attention.goTo` now refuses unless focus was requested, as Search Tabs does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * DesktopNotifier: Mark as Read's doc comment back on its function Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Regenerate the action exports and docs shortcuts for attention.goTo Regenerated on the fleet (scripts/cmux-next/regenerate-action-exports.sh, steps 3ee6d476 and c491d7ee) and with web/scripts/export-docs-shortcuts.ts. They also pick up the base's stale entries for home.*Conversation* and neverHibernateSite. The defaults snapshot is bot-only (#21946), so it is left to the base autofix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Regenerate actions.md for attention.goTo after the base merge Fleet step df753c55 (regenerate-action-exports.sh at 1c2a8dc); action-surfaces.json and the docs shortcuts were already fresh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Attention ring: going into a remote marked tab hides its ring too interacted(_:tabID:) found tabs on this Mac's daemon only, while attentionMarks rings marked tabs on every machine, so a click or a key in a Cloud or SSH tab never dismissed its ring. A tab found on another machine now gets the ring's dismissal, which is this app's own state; its notifications and Mark as Unread keep their daemon's own paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * AttentionTabsWatch: AppServices owns the watch, and letting it go cancels its loop The observation task was never stored, so once AppServices was freed its stream waited forever on a closure that read nothing. The watch is now an object that AppServices keeps; its deinit cancels the task, which ends the stream. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * AttentionTabsWatch: nonisolated deinit (cx-t7hu) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Attention ring: resolve a click or key on the window's own machine; reject a bad at_ms A tab on another machine can share an id with one here (a forked machine keeps its tab ids). Interactions now find the tab in the workspace the window shows, on the machine that owns it, and the hidden-ring state lives on the tab's own model, so one machine's click or Dismiss Highlight never hides another's ring. A mark whose at_ms is missing, negative, fractional or not a number is no mark. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you: a page's Go to needs the person's gesture; an open palette page follows the marks chat.attention.open shows a tab, which moves the person's focus: it now spends the pane's one-use user gesture like other focus-moving page calls, so page script alone cannot show a tab. Go to What Needs Me reads the marked tabs at each load and reloads when they change, so a cleared mark's row leaves an open page and a new one appears. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you: rows name their machine; a bad atMs is no row; test the open page's reload Tabs on two machines can share an id, so a marked tab's row key is now its machine and its tab id, and Go to shows that machine's tab only (revealTab(_:onMachine:)). The page drops an item whose atMs is not a whole nonnegative number, as the host does. A test drives the real palette: an open Go to What Needs Me page keeps its query and page across a change, gains a new mark's row and loses a cleared one's. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you banner: read the muted workspace and the viewed pane on the row's own machine A marked tab's row key now names its machine. The banner's policy inputs (is the pane viewed, is its workspace muted) look the tab up on that machine, not by a bare id that another machine's tab may share. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Attention ring: typing in another machine's terminal clears no workspace mark here; tests prove the redraw and the untouched local tab noteTyping's workspace Mark as Unread clear now runs only for a window that shows this Mac's workspace (or none), so a key in a remote terminal never clears a local workspace whose tab shares the id. The ring test checks that hiding the ring wakes its observers, and the two-machine test checks that a click on the remote tab leaves the local tab's Mark as Unread alone. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you banner: test that muted is read on the row's own machine Two machines' tabs share an id in workspaces of their own. Muting one machine's workspace silences only that machine's tab's banner. The banner's policy inputs move into attentionArrival(_:) so the test reads what the policy decides on. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * TabAttentionTests: the observation flag is nonisolated (onChange is a Sendable closure) Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you: a row key fits the page's limit however long the machine id; test Go to's lookup on two machines A row key is now a 16-hex digest of its machine's id, '/', and its tab id, so it stays within chat.attention.open's 256-byte limit. Go to finds the key's machine among the connected daemons (AttentionTabsWatch.locate) and reveals the tab there. The test connects an SSH machine whose tab shares this Mac's tab id and checks that each row's key finds its own machine's tab. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you banner: Show opens only the banner's own live request; policy finds the row's machine by its key A banner's Show (or click) now opens the tab only while that banner's request (its at_ms and row key) is still a live mark, so a banner from an earlier launch or one a newer request replaced opens nothing. The policy lookup uses the row key's machine digest (AttentionTabsWatch.locate). The Show test uses the real machine-qualified key and covers a replaced and a cleared request. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you: Go to refuses a tab whose workspace id another machine's workspace also has Windows find a workspace by its id alone and prefer this Mac's. A remote row whose workspace id this Mac's workspace also has (a cloned machine's state) now refuses rather than show this Mac's tab. The two-machine test drives the bound Go to. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * Needs you banner: only a banner this launch posted can Show A banner left in Notification Center by an earlier launch keeps its id after a restart, and its request may still be the live mark. Show now also requires that this launch posted the banner and has not withdrawn it. A test restarts the service with a live mark and checks the old banner opens nothing. Leo-ask: ask-12231fbe5e Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16037-16c2-7a73-b063-2e37ed40b9c4&host=cosmic-gray * cmux NEXT: repair needs-you banner on current base Rebase the stale attention-banner branch onto current feat-cmux-next while preserving machine-bound tab routing, gesture-gated Go to, and Needs you UI coverage. Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec Sidebar-Look: no visual change * Merge current-base needs-you repair tree Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec Sidebar-Look: no visual change * Harden needs-you notification lifecycle Sidebar-Look: no visual change Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * Inject attention state and keep row requests generation-bound Move attention observation, palette rows, and banner identity into AgentPane; keep system notification integration in the existing app service. Exercise stale-generation refusal, bounded keys, sound policy, and startup withdrawal. Sidebar-Look: no visual change Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): use current tab attention capability API Repairs the exact-head review compile finding in Mark as Read. Swift syntax and prepush gate pass; native compilation remains on fleet. Sidebar-Look: no visual change Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): allow attention page operation Expose chat.attention.open through the page host allowlist so marked-tab Go to requests reach the injected routing handler. Sidebar-Look: no visual change Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): baseline attention snapshots by machine Establish each daemon's quiet baseline only after its live tree and current session snapshot arrive. Rebaseline replaced stores and replayed streams without suppressing ready machines. Qualify remote workspace mute and sound settings while preserving existing local keys; use the same keys for writers, banners, rings and sidebar indicators. Add regressions for late snapshot ordering, empty baselines, offline remotes, reconnect/replay, store replacement and cloned workspace IDs. Static gate and web lint pass. Native red/green evidence remains pending the Swift dependency hold. Sidebar-Look: no visual change Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): respect typing quiet period for tab attention Record typing by machine and tab, and pass its age into attention policy so banner and sound suppression matches normal notifications without leaking across cloned tab IDs. Add coverage for both machine directions and expiry. Native red/green remains blocked by Swift dependency 26809; static gate and web lint pass. Sidebar-Look: no visual change Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): restore xcstrings catalog version Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): remove invalid notification key enum initializer Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): retain attention requests through reconnect readiness Capture the quiet request baseline when the session snapshot is applied, before subsequent deltas or tree readiness can coalesce in observation. Classify live post-snapshot requests once per machine/generation and let the notification lifecycle post deferred eligible requests even when it already saw their unready rows. Regressions cover reconnect deltas before the tree with separate/coalesced observations, missing initial tab models, cleared pending requests, and replay. Native red/green remains unproven while Swift dependency 26809 is held. Static gate and web lint pass. Sidebar-Look: no visual change Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * fix(next): select throwing workspace mute action binding Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * test(next): supply the app scheduler to attention SSH fixtures The focused fleet run reached test compilation and identified three owned SSHMachineSession fixtures still using the pre-mainWork API. Pass each fixture its existing AppServices scheduler. Regression assertions remain unchanged. Agent-Session: https://cmux.com/deeplink/agent?id=aid-cb9fc69664e9708a30ec * cmux NEXT: marked tabs in Needs you Agent-Session: https://cmux.com/deeplink/agent?id=aid-04743fa7d44d1f9b2454 * Bundle the attention palette string catalog Agent-Session: https://cmux.com/deeplink/agent?id=aid-04743fa7d44d1f9b2454 * Own attention tabs in AppServices and route page events Agent-Session: https://cmux.com/deeplink/agent?id=aid-04743fa7d44d1f9b2454 * Preserve current base documentation and needs-you fixtures Agent-Session: https://cmux.com/deeplink/agent?id=aid-04743fa7d44d1f9b2454 * Bind attention navigation to owner-issued request tokens Agent-Session: https://cmux.com/deeplink/agent?id=aid-04743fa7d44d1f9b2454 * fix(next): open marked tabs from Home inbox Agent-Session: https://cmux.com/deeplink/agent?id=aid-32928e845232cc28d954 * fix(next): wire marked tab host events Agent-Session: https://cmux.com/deeplink/agent?id=aid-32928e845232cc28d954 * fix(home): avoid selecting marked tabs after opening Agent-Session: https://cmux.com/deeplink/agent?id=aid-32928e845232cc28d954 * fix(debug): restore palette renderer for named-window captures Agent-Session: https://cmux.com/deeplink/agent?id=aid-32928e845232cc28d954 * test(home): reject fallback selection after a marked-tab open Agent-Session: https://cmux.com/deeplink/agent?id=aid-32928e845232cc28d954 * Carry of #24345: drop the duplicate AgentPane import; regenerate cmux-app.d.ts after the base merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1500aad3011a497e835c * Attention banners: redact an incognito tab's banner; keep remote mutes saved before qualified keys Review at 2794003 (codex gpt-6.1-sol) blocked on two findings: - An attention banner from an incognito window's tab named its workspace, tab and reason in Notification Center. postAttention now resolves the tab's workspace and posts with incognito redaction. - Remote workspace mutes saved by earlier builds under bare workspace ids were dropped on upgrade. A bare id still mutes a remote workspace while no workspace on this Mac has that id (NotificationWorkspaceKey.legacyRemoteKey), and toggling the workspace's mute clears it. Tests: AttentionBannerTests.anIncognitoTabsBannerNamesNothing and aRemoteMuteSavedBeforeQualifiedKeysStaysMuted (run in PR CI; this host has no fleet client for a local compile check). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1500aad3011a497e835c * Notification keys: one machine-aware lookup for mute and sound; keep remote sound rules saved before qualified keys Review at edaec4b (codex gpt-6.1-sol) blocked on remote workspace sound rules saved under bare ids by earlier builds. NotificationWorkspaceKey.ruleKey reads such a rule while only it exists and no workspace on this Mac has the id, so it keeps applying and the settings edit it in place. Ordinary notifications, the move-to-top check and attention marks now read mute and sound through NotificationCenterService.notificationKeys, so a remote workspace's qualified mute or sound rule (what the toggle and sound settings write) applies to every banner, not just Needs you ones. Test: AttentionBannerTests.aRemoteSoundRuleSavedBeforeQualifiedKeysStillApplies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1500aad3011a497e835c * Needs you: a marked tab's ask-about refusal throws a bare Error, as its neighbours do (pane-english) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-1500aad3011a497e835c --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo-ask: ask-12231fbe5e
Leo: "idk where things are man i dont see anything other than the current workspace which is you and you have a cmux next github brwoser tab open (we need to have cmux expose this harder if it isn't already/hve better instructions)"
What happened: an agent needed Leo to confirm GitHub sudo in a browser tab it had opened (in a workspace 42 rows down the sidebar) and told him a raw
ws_…id he could not see or search.This is slice A of the "needs you here" surface: the daemon state, CLI and MCP path. The app styling, notification with Show, the "Go to what needs me" palette command and the agent instructions follow in their own PRs.
What changes
tab.updatetakesattention: a one-line reason (1-200 characters, no control characters) ornullto clear. The daemon stores{reason, at_ms}on the tab record (tab_state.attention_json, an additive column), and every client sees it as the tab'sextra.attention. Capabilitytab-attention-v1.cmux attention request --tab <tab_…> --reason <text>andcmux attention clear --tab <tab_…>. Both sendtab.update {attention}, so CLI, MCP (tab_updatewithattention, generated from the catalog) and the app share one mutation path.cmux docs, "Show your work…") tells agents to mark the tab and to name workspaces and tabs by their titles, never by aws_ortab_id.Tests
state/tab_attention_tests.rs:tab_state_storeunit tests: migration, clear on close, reason validation.attention_request_and_clear_send_tab_update, plus the transport-path coverage cases (which check the plan against the catalog).Not in this PR
App styling (the existing blue needs-you treatment on the tab and its workspace row), the Needs you list entry, the system notification with Show, the palette command, and the MCP server instructions text.
No capture: daemon/CLI only; no native UI changes in this PR.
Agent session: cosmic-gray
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Agents can now mark the tab where the person must act (confirm, log in, approve, pick), instead of pointing them at an opaque
ws_/tab_id for a tab far down the sidebar.tab.updatetakesattention, a one-line reason ornullto clear; the daemon stores it on the tab record and every client sees it asextra.attentionundertab-attention-v1. Reasons with control characters, U+2028, or U+2029 are refused.cmux attention request --tab <tab_…> --reason <text>andcmux attention clear --tab <tab_…>both sendtab.update— the same mutation path CLI, MCP (tab_update), and the app share.cmux docsnow tells agents to mark the tab and to name tabs and workspaces by their titles, never by id.App styling, the needs-you list entry, system notification with Show, and the palette command follow in later PRs.
Written for commit 12f9a15. Summary will update on new commits.