fix(next): keep incognito Runs and hand-offs right, hide late-flagged ephemeral workspaces from phones
Merged
TE
5d ago+149+149+012345678901234567890123456789-10-10-01234567890123456789
Fixes #31040 and #31039, the blocking review findings left open when #30881 and #30880 landed.
Problem
- Regression from #30881.
SandboxRunNotices.followdecided whether a Run was incognito after the create request returned. A normal tab closed while the Run was being created had no tab by then, so the Run was counted as incognito: its banner opened nothing and its record was dropped at quit. - Also #31040. Incognito hand-offs are not saved. After a relaunch,
HandoffNotices.resumefinds them in the owner's list and rebuilds them throughlistedwithout the flag, so later status banners post their full text. - #31039.
EphemeralWorkspaces.placementsrepublishes the phone's hidden set only when it opens an incognito window. A workspace whose tree entry arrives before itssession.eventsephemeral flag is placed in a normal window first. When the flag lands, nothing republishes, somobile.workspace.listand the terminal RPCs keep exposing it.
Change
- The page runner (
AgentPageChats.wireSandbox) reads the tab's incognito state when the send starts, before any await, while the pane holds the key, and passes it toSandboxRunNotices.follow(..., incognito:). A send with no tab at that moment is still treated as incognito. SandboxRunFollowerkeeps the ids of incognito tasks (ids only, like the incognito ledger, up to 256), and applies the flag to any later record with that id, including a hand-off rebuilt from the list after a relaunch. An id is dropped when its task ends.WindowManager.observeMembershipalso observes the local store's set of ephemeral workspace ids and republishes the hidden set (recordIncognitoWorkspaces) when it changes. The stream dedupes equal sets, so a reorder doesn't trigger it. It is cancelled with the membership observation.
Tests
Two commits: the first adds the failing tests, the second the fix.
SandboxRunNoticeTests.aRunsIncognitoIsReadWhenItsSendStartsNotWhenItsCreateAnswersHandoffNoticeTests.anIncognitoHandoffFoundInTheListAfterARelaunchStaysIncognitoIncognitoSpaceTests.phonesHideAWorkspaceWhoseEphemeralFlagLandsAfterItsPlacement
Not covered here: the daemon-lane splice still serves unfiltered list-workspaces to newer iOS builds, and Feed and iPhone push items for incognito notifications are not filtered. Both stay listed in #31039.
š¤ Generated with Claude Code
Agent session: agent session
![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
Fixes #31040 and #31039: incognito Runs keep their incognito flag through hand-offs, relaunches, and races with the owner's list, and phones stop exposing workspaces whose ephemeral flag lands after placement.
Bug Fixes
- Reads a Run's incognito state when the send starts, not when the create request answers, so a tab closed mid-create no longer miscounts the Run.
- Incognito hand-offs found in the owner's list after a relaunch keep the flag ā and the flag reaches a record the list already followed or ended before the app's own watch ā so banners stay redacted, clicks open nothing, and the record is never saved.
- A workspace whose ephemeral flag lands after the tree entry is hidden from phones as the flag lands, without reorder-triggered republishes.