Skip to content

fix(mobile): release notification and account streams from the transport - #23032

Merged
brennanb2025 merged 16 commits into
mainfrom
brennanb2025/ready-stream-transport-release
Oct 3, 2026
Merged

brennanb2025 merged 16 commits into
mainfrom
brennanb2025/ready-stream-transport-release

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 6 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​286 $\color{#cf222e}{\Huge{\mathbf{−}}}$​35 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​251
Prod 23 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​353 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1546 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1193

What this fixes

The problem. When the phone is connected to a desktop, it opens two background feeds from that desktop: desktop notifications and the account list. Each feed is a registration on the desktop, and the phone has to tell the desktop to stop it when the phone no longer needs it. For these two feeds, the phone often never sent that stop, or sent it with an out-of-date id, so the desktop kept a dead registration and kept pushing events to a phone that was no longer listening, until that phone connection closed.

The cases on main:

  • Account list, direct connection: the stop was never sent. Every visit to the phone's Accounts screen left one more account feed running on the desktop. Reproduced live: after three visits, the desktop held 4 account listeners for one phone (1 → 2 → 3 → 4).
  • Notifications and account list, closed quickly: if the phone closed the feed before the desktop's first reply arrived, no stop was ever sent.
  • Notifications, after the phone reconnects (for example switching between direct and relay): a feed closed in the short window before the desktop answered on the new connection was stopped with the old connection's id, which no longer names anything, so the new feed kept running.
  • Notifications, relay connection: the stop was sent twice.

Scope. Phone app only, direct and relay connections. No desktop change and no wire change. Not affected: terminal, chat, tab-list and browser-preview feeds; SSH hosts; and everything the phone shows.

Where these came from. None of these is a recent regression. Each gap has been there since the code that opened or closed the feed first landed:

Before and after for users

  • Before: nothing looked wrong on screen. The cost was hidden: the desktop kept one extra live registration per leaked feed and kept sending its events over the phone connection (wasted desktop work, phone bandwidth and battery), and this grew with every visit to the Accounts screen until the phone disconnected.
  • After: the phone looks and behaves the same (notifications arrive, dismissals sync, the account list loads), and every notification or account feed is stopped exactly once, with the id the desktop issued on the current connection. Leaving the Accounts screen takes the desktop back to one listener.

How it works

Background: for a few feeds, the desktop only says which registration it created in its first reply, a ready message carrying a subscriptionId. To stop the feed the phone must send that id back (notifications.unsubscribe {subscriptionId}, accounts.unsubscribe {subscriptionId}). The only part of the phone that sees every ready, including the new one after a reconnect, and that knows whether a feed was closed before its ready arrived, is the connection layer (the direct stream registry and the relay stream manager).

The mechanism:

  1. One table of these feeds. READY_STREAM_RELEASE_METHODS in mobile/src/transport/rpc-client-server-subscription.ts maps each such feed to its stop method: browser preview, workspace events, and now notifications and accounts.
  2. Both connection types send the stop from that table. The direct registry (rpc-client-stream-registry.ts) and the relay manager (mobile-relay-rpc-streams.ts) check the table (isReadyIdStream) and use their existing "stop by the desktop's id" path. Closed after ready: stop with the current id. Closed before ready: keep a cancelled placeholder, and send the stop when the ready arrives. That path already handled browser preview and workspace events; this PR routes the two missing feeds through it.
  3. The notification code no longer stops its own feed. mobile-notifications.ts stopped keeping its own copy of the id (which went stale on reconnect and did not exist before ready) and just calls the disposer the connection layer returns. Its now-unused stop request module is deleted.
  4. The relay's name guess is gone. The relay used to derive a stop for any other feed by rewriting x.subscribe into x.unsubscribe. On main only notifications and accounts reached that guess. It was the second notification stop, and the only thing stopping relay account feeds. Both feeds are now in the table, so the guess is removed.
  5. A test keeps the table complete. The phone's subscription inventory (rpc-subscription-inventory.ts) now records how each feed is stopped (ready-id or params), and its boundary test fails unless the ready-id feeds are exactly the table's. A new feed of this kind can't be added without a stop.

Before and after in the codebase

Before (main) After
Who stops a feed whose id arrives in ready Three places, each different: direct registry (hardcoded browser preview + workspace events), relay manager (same two hardcoded, plus a string-rewrite guess for everything else), and notification feature code (its own id copy and its own stop request) The connection layer only, from one table both connection types read
Account list stop None on direct; relay only by the name guess, and only after ready From the table, on both, before or after ready
Notification stop Feature code after ready (stale after reconnect, missing before ready), plus the relay guess (duplicate) Once, from the table, with the current id
desktop-notification-stream-operations.ts Stop request definition used by the feature code Deleted
Adding a new feed of this kind Had to be remembered in both connection files separately, or it leaked silently One table entry; the inventory test fails if it's missing

The plan this belongs to

#22928 moves every phone feed to one rule: a feed is stopped exactly once, by the part of the phone that knows which desktop registration it is, so a stop can never miss its feed or hit a newer one. The earlier steps (#22948, #22939, #22945, #23006, #22943, #23045) did this for terminal, chat and tab-list feeds and for feeds reopened after a reconnect. This PR is the last step: it applies the same rule to the notification and account-list feeds.

Why this approach

Only the connection layer sees every ready, so it is the only place that can hold a current id. Moving the stop there removes the stale-id and close-before-ready bugs by construction; patching the feature code's copy would have kept the id in two places. The connection layer already stopped browser preview and workspace events this way, so this extends that path rather than adding another.

Alternatives considered:

  • Refresh the notification code's id on reconnect: the id still lives in two places, and the notification code would still need its own close-before-ready tracking.
  • Keep the relay's name guess: one class of feeds would be stopped by an explicit table and another by a string rewrite no test pins.
  • Keep separate per-method checks in the direct and relay code: a feed added to one but not the other leaks silently, which is exactly how the direct account leak happened.

Differences from comparable designs:

  • Intended: stops are looked up in a per-method table rather than sent through one generic "release this registration" call. Every shipped desktop already accepts these per-feed stops, while a generic release would be a new wire method that old desktops reject and that would need capability negotiation. The inventory test catches a missing entry.
  • Intended: a feed closed before its ready is kept as a cancelled placeholder and stopped when the ready arrives, instead of being stopped by the id of the request that opened it (as terminal feeds are since fix(runtime): let the phone end a terminal stream by the request that opened it #23006). The desktop registers these feeds synchronously just before sending ready, so the placeholder lives for one round trip, and it is dropped on ready, error, end or connection close.
  • Intended: the desktop's own client for remote Orca servers keeps a similar method-to-stop table (getCleanupRequest in src/shared/remote-runtime-shared-control-protocol.ts). The phone keeps its own, because that module imports desktop-only connection code and only three rows overlap.

Feeds deliberately left out of the table: files.watch and browser.clientHost.attach (the phone may not call them); terminal, tab-list, native chat and agent session feeds (stopped from their subscribe params and request id, params in the inventory); browser network tunnels and the terminal multiplex (their ready has no id).

Linked Issue

Part of #22928

Visual Proof

No screen changes. Live phone QA ran on an iOS simulator paired to an isolated desktop built from main, first with main's phone app, then with this branch's phone app, watching the desktop's feed registrations.

Check main's phone app this PR
Account listeners on the desktop after 3 visits to the Accounts screen 1 → 2 → 3 → 4 (leak) back to 1 after each visit
Phone receives a desktop notification yes yes
Notifications after a hard desktop restart and phone reconnect yes yes
Leftover notification listeners on the desktop none none
Terminal open / send / leave / return, 3 cycles not run every send executed

Accounts screen on this build:
after-pr-accounts-screen-loaded.png

Reconnected after a hard desktop restart:
after-pr-after-host-restart-reconnected.png

Terminal sends after leaving and returning:
after-pr-cycle3-send-R32C3.png

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

New and updated tests, using the real direct registry and the real relay manager (each fails without the fix):

  • Notifications, both connections: close before ready, then ready arrives → exactly one notifications.unsubscribe with that id (main: none).
  • Notifications, direct: reopen after a socket close, close before the new ready → the only stop names the new id (main: the old id).
  • Notifications, relay: close after ready → exactly one stop (main: two).
  • Accounts, direct: close after ready → accounts.unsubscribe (main: none); close before ready → stopped once ready arrives, on both connections.
  • Every feed in the table, both connections: one stop after ready, one when the close came first. Reads the table, so future entries are covered.
  • Inventory boundary test fails if a ready-id feed is missing from the table (checked by removing accounts.subscribe).
  • Unchanged behaviour: dismissals and the catch-up read still run, and a reopened feed re-runs the catch-up on its new ready.

On the current head (87e46dd): the transport and notification test files, rpc-client-ready-stream-release.test.ts, the inventory boundary test, and every file under mobile/src/test-support/rpc-recording and bridged-parity pass with --config vitest.config.ts; host and mobile typecheck pass; oxlint and the changed-code quality gate are clean; CI is green.

Recorded RPC goldens (rpc:diff against main): of 794, 787 are unchanged, 6 desktop-notification goldens change, and 1 is deleted. The 6 change because the stop is now sent by the connection layer instead of the notification code: same wire frame, minus the feature code's request entries; after a reconnect the old connection's sub-1 is also stopped, as workspace-event feeds already are; and where the desktop's reply ends the feed with an error, no stop is sent. The deleted matrix-notifications.desktop-stream-notifications.unsubscribe-1 varied the reply to the notification code's own stop request, which no longer exists, so its scripted replies are dropped from pilot-scenarios.json too. The corpus is now 793, so the bridged-parity tally and the comments quoting the corpus size drop by one. Main's recorded-request check parses every recorded stop with the desktop's own params parser and passes; the four stops the table can build were also checked against that parser.

AI Disclosure

Review

  • Security: no new methods or parameters. notifications.unsubscribe and accounts.unsubscribe are already on the mobile allowlist, and the phone only sends ids the desktop issued to it.
  • Cross-platform: phone connection logic only.
  • Remote SSH: unaffected; this is the phone-to-desktop connection, not how the desktop reaches its hosts.
  • Mobile: direct and relay both change, each covered by tests and by live QA on direct.
  • Mixed phone/desktop versions: no wire change. Every desktop already answers these feeds with {type:'ready', subscriptionId} and accepts the matching stop (src/main/runtime/rpc/methods/notifications.ts, accounts.ts). An older desktop simply starts receiving the stop it was missing.
  • Performance: the desktop stops pushing account and notification events to phone connections that stopped listening, and the relay sends one fewer stop.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

This branch has merged main several times (latest f37a849). It composes with the earlier steps in the same files: the stream record is removed before its listener hears end or an error (#22939); the relay's same-slot sibling skip still runs before every stop and never skips a ready-id stop, because those ids are unique; terminal stops carry the opening request id (#23006); a direct tab-list stop waits for the first snapshot (#22943); and reopening after a socket close forgets the old desktop id (#22945). Merge conflicts were only in recorded goldens and in comments that quote the corpus size, resolved by re-recording from the merged tree.

Checklist

  • This PR is small and focused
  • I explained what changed and why (the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…ation release

Repins the recording baseline to a547d89 and re-records every golden.
780 goldens move only in baseline and recorderSha256 (repin plus a comment
edit in run-recording.ts). Six desktop-notification goldens move in their
body: the notification code no longer issues notifications.unsubscribe as a
request, so its sender-call entries go and only the transport's wire frame
remains; the replayed scenario now also releases sub-1 on the retiring
session at cutover; the subscribe-1-1 matrix records the cancelled
placeholder a non-ready reply leaves. The unsubscribe-1 matrix was removed
earlier because the request it varied no longer exists. The three scenarios
drop their scripted reply to that request.

@pullfrog pullfrog Bot 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.

✅ No new issues found.

Reviewed changes

  • Transport owns ready-id stream release — READY_STREAM_RELEASE_METHODS in rpc-client-server-subscription.ts is now the single table behind buildReadyStreamUnsubscribe and the new isReadyIdStream, adding notifications.subscribe and accounts.subscribe to the two methods that already worked this way.
  • Direct registry replays without the dead socket's id — markForReplay clears stream.subscriptionId, so a reopened feed discards the previous connection's registration and releases only the id from its new ready.
  • Relay drops the name-guess fallback — the .subscribe→.unsubscribe string rewrite is gone; a feed is released via the table or a cancelled placeholder, which removes the duplicate notifications.unsubscribe.
  • Notification module sheds its local id and stop — mobile-notifications.ts keeps only its listener/catch-up work; desktop-notification-stream-operations.ts is deleted.
  • Golden repertoire re-recorded — 787→786 goldens, six desktop-notification body moves, matrix-notifications.desktop-stream-notifications.unsubscribe-1 deleted, and the bridged-parity pins/tally renumbered to match.

The behavioural claims hold up on a read of the transports: every subscribe method the phone actually opens is either in the table (browser.screencast, runtime.clientEvents.subscribe, notifications, accounts), handled by its own param-derived path (terminal.subscribe, session.tabs.subscribe, nativeChat.subscribe), or id-less (agentSession.subscribe), so removing the relay name guess leaks nothing. The sub-1→sub-2 replay test genuinely fails against the unpatched markForReplay, so it is coverage rather than a tautology.

ℹ️ Nitpicks

  • mobile/src/test-support/rpc-recording/README.md:410-420 still explains the old blindness with "Neither unsubscribe builder in rpc-client-stream-registry.ts knows notifications.subscribe". That paragraph is history, but the mechanism clause is now false — this PR put notifications.subscribe in that builder — and the sibling paragraph at :656 was updated while this one was not.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

… table

Each subscribe site now declares how the phone releases it on the host, and
the boundary test requires the ready-id sites to name exactly the methods in
READY_STREAM_RELEASE_METHODS. A new stream whose host id arrives only in
`ready` is otherwise released on neither connection, and nothing noticed:
that is how direct accounts.subscribe went unreleased.

@pullfrog pullfrog Bot 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.

✅ No new issues found.

Reviewed changes

Incremental delta since the prior pullfrog review (e7e3a57): one commit, ecc04dc.

  • Subscription inventory gains a release classification — every RPC_SUBSCRIPTION_SITES entry now declares how the phone ends its host stream, through the new RpcSubscriptionRelease type: ready-id, params, or connection-close.
  • Boundary test binds the ready-id entries to the transport release table — a new test asserts set equality between the inventory's release: 'ready-id' methods and READY_STREAM_RELEASE_METHODS keys, so a feed marked ready-id without a table entry (or a table entry with no ready-id site) fails. The classifications hold up against both transports: ready-id is exactly the four table methods, the three params entries have matching builders (terminal, nativeChat, session.tabs), and agentSession.subscribe is genuinely connection-close (neither builder handles it).
  • Doc headers updated — the boundary test and inventory headers now describe the fifth failure mode.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Conflicts:
- mobile-relay-rpc-streams.ts: keep main's sendOrder sibling skip on every
  unsubscribe; route the cancel-before-ready arm through isReadyIdStream and
  keep the name-guessing fallback deleted (only notifications and accounts
  reached it, both now in the ready-id table).
- rpc-client-stream-registry.ts: keep main's receivedSnapshot reset beside the
  shared subscriptionId reset in markForReplay.
- Goldens, bridged-parity counts: take main's; the next commit re-records.
- pilot-scenarios.json: main's manifest with this branch's three
  notifications.unsubscribe#1 replies removed.

Also: agentSession.subscribe gained agentSession.unsubscribe on main (#22835),
so its inventory release is now 'params', and the recorder comment no longer
names it as builder-less.
Repins baseline to the merge commit aae9aa7 and re-records the whole
corpus with --record. Against origin/main: 783 goldens move only in
baseline and recorderSha256 (the repin and the recorder comment edit); the
six desktop-notification recordings move in body, byte-identical to this
branch's pre-merge recordings (the transport now sends the stop); the
notifications.unsubscribe matrix golden is deleted because that request no
longer exists. Corpus 789: result-absent-settlement 343 -> 342, and the
comments quoting the corpus size follow.
@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Refactors notification stream lifecycle and transport cleanup.

The PR appears safe to merge; no new actionable issue was identified in changes since the previous review.

Summary

The PR moves notification and account-stream cleanup into the mobile transport, which uses the desktop-issued ready ID to release registrations on direct and relay connections.

  • Adds shared release-method mapping and boundary tests for ready-ID streams.
  • Removes notification-owned unsubscribe requests and updates recordings to reflect transport-owned cleanup.
Diagram
sequenceDiagram
  participant Phone as Mobile consumer
  participant Transport as Direct or relay transport
  participant Desktop
  Phone->>Transport: subscribe to notifications or accounts
  Transport->>Desktop: subscribe
  Desktop-->>Transport: ready(subscriptionId)
  Phone->>Transport: dispose
  Transport->>Desktop: unsubscribe(subscriptionId)
Loading

Reviews (6) · Last reviewed commit: "Merge remote-tracking branch 'origin/mai..."

@pullfrog pullfrog Bot 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.

✅ No new issues found.

Reviewed changes

Incremental delta since the prior pullfrog review (f503170): the branch merged origin/main twice and re-recorded the golden corpus against the new baseline.

  • Merged origin/main — brings in main's transport refactor (finish, buildRequestStreamUnsubscribe, the relay sendOrder/slot-eviction path, session-tabs snapshot hold) alongside unrelated app-update, keyboard, and session work. The resolution keeps this PR's release behavior intact: isReadyIdStream still routes every ready-id feed through disposeServerSubscription (direct) and the cancelled-placeholder release (relay), and markForReplay still clears stream.subscriptionId.
  • Re-recorded the corpus after the merge — 789 goldens repinned to the merge baseline; the six desktop-notification recordings change only in baseline/lockfileSha256/recorderSha256, leaving their bodies byte-identical to the pre-merge branch, and the deleted notifications.unsubscribe matrix stays deleted.
  • Renumbered the bridged-parity pins — corpus 789, identical 397, result-absent-settlement 342, result-absent-stream-release 6, params-undefined 33, write-ordinal 8; the recorder README, page-closure headers, and boundary-test comments follow.

The author's own delta is test-support metadata with no product-code behavior change. I checked the counts against the tree (789 golden files, 398 manifest scenarios; 397 + 342 + 3 + 6 + 33 + 8 = 789) and ran the PR's transport and notification suites against the merged code — rpc-client-ready-stream-release.test.ts, mobile-relay-rpc-streams.test.ts, mobile-notifications.test.ts, and rpc-subscription-boundary.test.ts all pass (39 tests).

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

- Drop the unused `connection-close` release kind: agent session feeds
  now stop by params, so no phone stream uses it.
- The notification listener's SAFETY note names the transport's `error`
  frame too.
- The recording README's mutant history is past tense: the transport now
  releases `notifications.subscribe`.
…ream-transport-release

# Conflicts:
#	mobile/rpc-foundation/goldens/aivault-history-scan-fulfilled.json
#	mobile/rpc-foundation/goldens/aivault-history-scan-unsupported.json
#	mobile/rpc-foundation/goldens/aivault-history-scan-worktrees-late.json
#	mobile/rpc-foundation/goldens/aivault-history-screen-listed.json
#	mobile/rpc-foundation/goldens/aivault-history-screen-worktrees.json
#	mobile/rpc-foundation/goldens/aivault-resume-launch-create-refused.json
#	mobile/rpc-foundation/goldens/aivault-resume-launch-invalid-tab.json
#	mobile/rpc-foundation/goldens/aivault-resume-launch-locked.json
#	mobile/rpc-foundation/goldens/aivault-resume-launch-sent.json
#	mobile/rpc-foundation/goldens/aivault-resume-prepare-refused.json
#	mobile/rpc-foundation/goldens/aivault-resume-prepare-repin.json
#	mobile/rpc-foundation/goldens/aivault-resume-prepare-skipped.json
#	mobile/rpc-foundation/goldens/aivault-resume-prepare-unavailable.json
#	mobile/rpc-foundation/goldens/b1.json
#	mobile/rpc-foundation/goldens/b2.json
#	mobile/rpc-foundation/goldens/b3.json
#	mobile/rpc-foundation/goldens/browser-dialog-accepted.json
#	mobile/rpc-foundation/goldens/browser-dialog-dismissed.json
#	mobile/rpc-foundation/goldens/browser-keyboard-input.json
#	mobile/rpc-foundation/goldens/browser-pointer-click-accepted.json
#	mobile/rpc-foundation/goldens/browser-pointer-click-fallback.json
#	mobile/rpc-foundation/goldens/browser-wheel-scrolled.json
#	mobile/rpc-foundation/goldens/clipboard-image-attachment-anonymous.json
#	mobile/rpc-foundation/goldens/clipboard-image-attachment-blocked-before-send.json
#	mobile/rpc-foundation/goldens/clipboard-image-attachment-cancelled.json
#	mobile/rpc-foundation/goldens/clipboard-image-attachment-pasted.json
#	mobile/rpc-foundation/goldens/clipboard-image-attachment-upload-refused.json
#	mobile/rpc-foundation/goldens/clipboard-image-upload-aborts-on-chunk-failure.json
#	mobile/rpc-foundation/goldens/clipboard-image-upload-chunked.json
#	mobile/rpc-foundation/goldens/clipboard-image-upload-single-frame-fallback.json
#	mobile/rpc-foundation/goldens/clipboard-image-upload-start-refused.json
#	mobile/rpc-foundation/goldens/codex-reset-credit-consumed.json
#	mobile/rpc-foundation/goldens/codex-reset-credit-resumed.json
#	mobile/rpc-foundation/goldens/components-codex-capability.json
#	mobile/rpc-foundation/goldens/components-setup-ask.json
#	mobile/rpc-foundation/goldens/components-target-local.json
#	mobile/rpc-foundation/goldens/components-target-ssh.json
#	mobile/rpc-foundation/goldens/diff-review-branch-compare.json
#	mobile/rpc-foundation/goldens/diff-review-branch-file-diff.json
#	mobile/rpc-foundation/goldens/diff-review-notes-refused-before-compare.json
#	mobile/rpc-foundation/goldens/diff-review-refused-file-diff.json
#	mobile/rpc-foundation/goldens/diff-review-snapshot.json
#	mobile/rpc-foundation/goldens/diff-review-status-unavailable.json
#	mobile/rpc-foundation/goldens/diff-review-worktree-file-diff.json
#	mobile/rpc-foundation/goldens/file-tap-open-refused.json
#	mobile/rpc-foundation/goldens/file-tap-opens-worktree-file.json
#	mobile/rpc-foundation/goldens/file-tap-previews-absolute-artifact.json
#	mobile/rpc-foundation/goldens/file-tap-resolve-miss.json
#	mobile/rpc-foundation/goldens/file-tap-resolve-refused.json
#	mobile/rpc-foundation/goldens/files-explorer-legacy-fallback.json
#	mobile/rpc-foundation/goldens/files-explorer-readdir.json
#	mobile/rpc-foundation/goldens/files-ownership-local.json
#	mobile/rpc-foundation/goldens/files-ownership-ssh.json
#	mobile/rpc-foundation/goldens/files-preview-artifact-direct.json
#	mobile/rpc-foundation/goldens/files-preview-artifact-image-read.json
#	mobile/rpc-foundation/goldens/files-preview-artifact-image.json
#	mobile/rpc-foundation/goldens/files-preview-grant-refresh.json
#	mobile/rpc-foundation/goldens/files-preview-worktree-image-read.json
#	mobile/rpc-foundation/goldens/files-preview-worktree-image.json
#	mobile/rpc-foundation/goldens/files-preview-worktree-text-read.json
#	mobile/rpc-foundation/goldens/files-preview-worktree.json
#	mobile/rpc-foundation/goldens/files-save-blind.json
#	mobile/rpc-foundation/goldens/files-save-verified.json
#	mobile/rpc-foundation/goldens/files-tab-doc-shapes.json
#	mobile/rpc-foundation/goldens/home-host-accounts.json
#	mobile/rpc-foundation/goldens/home-host-stats.json
#	mobile/rpc-foundation/goldens/host-view-settings-sync.json
#	mobile/rpc-foundation/goldens/host-worktree-actions-pin-open-delete.json
#	mobile/rpc-foundation/goldens/host-worktree-delete-refused.json
#	mobile/rpc-foundation/goldens/host-worktree-refresh-stream.json
#	mobile/rpc-foundation/goldens/interruptions-inventory-lifecycle.json
#	mobile/rpc-foundation/goldens/interruptions-settings-bot-overrides-fulfilled.json
#	mobile/rpc-foundation/goldens/inventory-lifecycle.json
#	mobile/rpc-foundation/goldens/inventory-repeat-query.json
#	mobile/rpc-foundation/goldens/lifecycle-b3.json
#	mobile/rpc-foundation/goldens/lifecycle-inventory-lifecycle.json
#	mobile/rpc-foundation/goldens/lifecycle-settings-bot-overrides-fulfilled.json
#	mobile/rpc-foundation/goldens/lifecycle-settings-task-hydration-fulfilled.json
#	mobile/rpc-foundation/goldens/lifecycle-settings-workspace-context-fulfilled.json
#	mobile/rpc-foundation/goldens/linear-select-workspace.json
#	mobile/rpc-foundation/goldens/live-worktree-name-stream.json
#	mobile/rpc-foundation/goldens/matrix-agentsession.structured-create-agentsession.create-1.json
#	mobile/rpc-foundation/goldens/matrix-agentsession.structured-create-agentsession.createsupport-1.json
#	mobile/rpc-foundation/goldens/matrix-agentsession.structured-launch-agentsession.createsupport-1.json
#	mobile/rpc-foundation/goldens/matrix-aivault.history-aivault.listsessions-1.json
#	mobile/rpc-foundation/goldens/matrix-aivault.history-screen-platform-status.json
#	mobile/rpc-foundation/goldens/matrix-aivault.history-screen-status.get-2.json
#	mobile/rpc-foundation/goldens/matrix-aivault.history-screen-worktree.ps-1.json
#	mobile/rpc-foundation/goldens/matrix-aivault.history-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-aivault.resume-launch-session.tabs.createterminal-1.json
#	mobile/rpc-foundation/goldens/matrix-aivault.resume-launch-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-aivault.resume-preparation-aivault.preparesessionresume-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.dialog-browser.dialogaccept-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.keyboard-browser.keyboardinserttext-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.keyboard-browser.keypress-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.pointer-click-browser.mouseclick-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.pointer-click-browser.mousedown-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.pointer-click-browser.mousemove-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.pointer-click-browser.mouseup-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.wheel-browser.mousemove-1.json
#	mobile/rpc-foundation/goldens/matrix-browser.wheel-browser.mousewheel-1.json
#	mobile/rpc-foundation/goldens/matrix-clipboard.image-attachment-clipboard.startimageupload-1.json
#	mobile/rpc-foundation/goldens/matrix-clipboard.image-upload-clipboard.saveimageastempfile-1.json
#	mobile/rpc-foundation/goldens/matrix-clipboard.image-upload-clipboard.startimageupload-1.json
#	mobile/rpc-foundation/goldens/matrix-components.codex-reset-capability-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-components.codex-reset-credit-accounts.consumecodexresetcredit-1.json
#	mobile/rpc-foundation/goldens/matrix-components.execution-target-local-preflight.detectagents-1.json
#	mobile/rpc-foundation/goldens/matrix-components.execution-target-preflight.detectremoteagents-1.json
#	mobile/rpc-foundation/goldens/matrix-components.execution-target-ssh.connect-1.json
#	mobile/rpc-foundation/goldens/matrix-components.execution-target-ssh.getstate-1.json
#	mobile/rpc-foundation/goldens/matrix-components.new-workspace-repositories-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-components.setup-script-repo.hooks-1.json
#	mobile/rpc-foundation/goldens/matrix-files.explorer-screen-files.list-1.json
#	mobile/rpc-foundation/goldens/matrix-files.explorer-screen-files.readdir-1.json
#	mobile/rpc-foundation/goldens/matrix-files.mutation-ownership-ssh.getstate-1.json
#	mobile/rpc-foundation/goldens/matrix-files.mutation-ownership-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-files.mutation-ownership-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-artifact-image-files.readterminalartifactpreview-1.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-load-files.readterminalartifact-1.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-load-files.readterminalartifact-2.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-load-files.resolveterminalpath-1.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-save-files.readterminalartifact-1.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-save-files.writeterminalartifact-1.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-worktree-image-files.readpreview-1.json
#	mobile/rpc-foundation/goldens/matrix-files.preview-worktree-text-files.read-1.json
#	mobile/rpc-foundation/goldens/matrix-files.tab-doc-files.read-1.json
#	mobile/rpc-foundation/goldens/matrix-files.tab-doc-files.readpreview-1.json
#	mobile/rpc-foundation/goldens/matrix-files.tab-doc-git.diff-1.json
#	mobile/rpc-foundation/goldens/matrix-files.terminal-path-tap-files.open-1.json
#	mobile/rpc-foundation/goldens/matrix-files.terminal-path-tap-files.resolveterminalpath-1.json
#	mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.baserefdefault-1.json
#	mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-git.base-ref-chain-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-git.branch-diff-preview-git.branchdiff-1.json
#	mobile/rpc-foundation/goldens/matrix-git.changes-load-git.branchcompare-1.json
#	mobile/rpc-foundation/goldens/matrix-git.changes-load-git.status-1.json
#	mobile/rpc-foundation/goldens/matrix-git.changes-load-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-git.changes-load-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-git.commit-message-ai-git.generatecommitmessage-1.json
#	mobile/rpc-foundation/goldens/matrix-git.history-commit-files-git.commitcompare-1.json
#	mobile/rpc-foundation/goldens/matrix-git.history-commit-files-git.history-1.json
#	mobile/rpc-foundation/goldens/matrix-git.history-read-git.history-1.json
#	mobile/rpc-foundation/goldens/matrix-git.remote-prerequisite-git.push-1.json
#	mobile/rpc-foundation/goldens/matrix-git.review-preparation-git.status-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-comment-mutation-github.addissuecomment-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-comment-mutation-github.addprreviewcommentreply-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-comment-mutation-github.project.deleteissuecommentbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-comment-mutation-github.project.updateissuecommentbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-comment-mutation-github.resolvereviewthread-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-mutation-github.mergepr-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-mutation-github.removeprreviewers-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-mutation-github.requestprreviewers-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-mutation-github.rerunprchecks-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-mutation-github.setprautomerge-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-mutation-github.updateprstate-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-read-github.listassignableusers-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-read-github.prcheckdetails-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-read-github.prchecks-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-read-github.prforbranch-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-read-github.reposlug-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-read-github.workitemdetails-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-read-hostedreview.forbranch-1.json
#	mobile/rpc-foundation/goldens/matrix-github.pr-title-mutation-github.updateprtitle-1.json
#	mobile/rpc-foundation/goldens/matrix-home.host-accounts-accounts.list-1.json
#	mobile/rpc-foundation/goldens/matrix-home.host-stats-stats.summary-1.json
#	mobile/rpc-foundation/goldens/matrix-host-worktree-refresh-runtime.clientevents.subscribe-1-1.json
#	mobile/rpc-foundation/goldens/matrix-host-worktree-refresh-runtime.clientevents.subscribe-1-2.json
#	mobile/rpc-foundation/goldens/matrix-host-worktree-refresh-runtime.clientevents.subscribe-1-3.json
#	mobile/rpc-foundation/goldens/matrix-host-worktree-refresh-runtime.clientevents.subscribe-2-1.json
#	mobile/rpc-foundation/goldens/matrix-host.view-settings-ui.get-1.json
#	mobile/rpc-foundation/goldens/matrix-host.view-settings-ui.set-1.json
#	mobile/rpc-foundation/goldens/matrix-host.worktree-actions-worktree.activate-1.json
#	mobile/rpc-foundation/goldens/matrix-host.worktree-actions-worktree.rm-1.json
#	mobile/rpc-foundation/goldens/matrix-host.worktree-actions-worktree.set-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-git.push-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-hostedreview.create-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-chain-worktree.set-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.bulkstage-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.commit-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.generatecommitmessage-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.push-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-2.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-3.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-git.status-4.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.create-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-hostedreview.getcreationeligibility-2.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.create-intent-worktree.set-1.json
#	mobile/rpc-foundation/goldens/matrix-hostedreview.eligibility-hostedreview.getcreationeligibility-1.json
#	mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-1.json
#	mobile/rpc-foundation/goldens/matrix-legacy-inventory-files.searchpaths-2.json
#	mobile/rpc-foundation/goldens/matrix-legacy-inventory-fresh-inventory.json
#	mobile/rpc-foundation/goldens/matrix-legacy-inventory-old-inventory.json
#	mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.getissue-1.json
#	mobile/rpc-foundation/goldens/matrix-linear-detail-barrier-linear.issuecomments-1.json
#	mobile/rpc-foundation/goldens/matrix-linear.select-workspace-picker-linear.selectworkspace-1.json
#	mobile/rpc-foundation/goldens/matrix-live-worktree-name-runtime.clientevents.subscribe-1-1.json
#	mobile/rpc-foundation/goldens/matrix-live-worktree-name-runtime.clientevents.subscribe-1-2.json
#	mobile/rpc-foundation/goldens/matrix-live-worktree-name-runtime.clientevents.subscribe-2-1.json
#	mobile/rpc-foundation/goldens/matrix-live-worktree-name-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-live-worktree-name-worktree.show-2.json
#	mobile/rpc-foundation/goldens/matrix-live-worktree-name-worktree.show-3.json
#	mobile/rpc-foundation/goldens/matrix-mobileweb.bundle-fetch-app-js.json
#	mobile/rpc-foundation/goldens/matrix-mobileweb.bundle-fetch-index-head.json
#	mobile/rpc-foundation/goldens/matrix-mobileweb.bundle-fetch-index-tail.json
#	mobile/rpc-foundation/goldens/matrix-mobileweb.bundle-fetch-mobileweb.bundle.manifest-1.json
#	mobile/rpc-foundation/goldens/matrix-mobileweb.bundle-manifest-mobileweb.bundle.manifest-1.json
#	mobile/rpc-foundation/goldens/matrix-nativechat.image-paste-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-nativechat.image-paste-terminal.send-2.json
#	mobile/rpc-foundation/goldens/matrix-nativechat.image-upload-clipboard.startimageupload-1.json
#	mobile/rpc-foundation/goldens/matrix-nativechat.session-option-pick-settings.mutatenativechatsessionoptions-1.json
#	mobile/rpc-foundation/goldens/matrix-nativechat.terminal-write-orchestration.workerterminaluserinput-1.json
#	mobile/rpc-foundation/goldens/matrix-nativechat.terminal-write-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.getmissedsince-1.json
#	mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.subscribe-1-1.json
#	mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.subscribe-1-2.json
#	mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.unsubscribe-1.json
#	mobile/rpc-foundation/goldens/matrix-notifications.display-test-screen-notifications.testpush-1.json
#	mobile/rpc-foundation/goldens/matrix-notifications.push-dismissal-notifications.getmissedsince-1.json
#	mobile/rpc-foundation/goldens/matrix-notifications.push-registration-notifications.registerpush-1.json
#	mobile/rpc-foundation/goldens/matrix-notifications.push-registration-notifications.unregisterpush-1.json
#	mobile/rpc-foundation/goldens/matrix-pairing.pre-profile-direct-status.json
#	mobile/rpc-foundation/goldens/matrix-pairing.pre-profile-pairing.getendpoints-1.json
#	mobile/rpc-foundation/goldens/matrix-pairing.pre-profile-pairing.provisionrelay-1.json
#	mobile/rpc-foundation/goldens/matrix-pairing.pre-profile-relay-status.json
#	mobile/rpc-foundation/goldens/matrix-project-explicit-false-github.project.updateissuebyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-relay.credential-rotation-pairing.getendpoints-1.json
#	mobile/rpc-foundation/goldens/matrix-relay.credential-rotation-pairing.getendpoints-2.json
#	mobile/rpc-foundation/goldens/matrix-relay.credential-rotation-pairing.provisionrelay-1.json
#	mobile/rpc-foundation/goldens/matrix-relay.direct-upgrade-pairing.getendpoints-1.json
#	mobile/rpc-foundation/goldens/matrix-relay.direct-upgrade-pairing.getendpoints-2.json
#	mobile/rpc-foundation/goldens/matrix-relay.direct-upgrade-pairing.provisionrelay-1.json
#	mobile/rpc-foundation/goldens/matrix-relay.pairing-recovery-pairing.getendpoints-1.json
#	mobile/rpc-foundation/goldens/matrix-session.browser-tab-create-browser.tabcreate-1.json
#	mobile/rpc-foundation/goldens/matrix-session.content-create-files.createfile-1.json
#	mobile/rpc-foundation/goldens/matrix-session.content-create-files.open-1.json
#	mobile/rpc-foundation/goldens/matrix-session.content-create-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-session.content-create-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-session.create-terminal-session.tabs.createterminal-1.json
#	mobile/rpc-foundation/goldens/matrix-session.create-terminal-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-session.diff-notes-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-session.diff-review-actions-worktree.set-1.json
#	mobile/rpc-foundation/goldens/matrix-session.diff-review-base-ref-show.json
#	mobile/rpc-foundation/goldens/matrix-session.diff-review-git.branchcompare-1.json
#	mobile/rpc-foundation/goldens/matrix-session.diff-review-git.status-1.json
#	mobile/rpc-foundation/goldens/matrix-session.diff-review-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.diff-review-review-show.json
#	mobile/rpc-foundation/goldens/matrix-session.markdown-disk-fallback-files.read-1.json
#	mobile/rpc-foundation/goldens/matrix-session.markdown-disk-fallback-markdown.readtab-1.json
#	mobile/rpc-foundation/goldens/matrix-session.markdown-save-markdown.savetab-1.json
#	mobile/rpc-foundation/goldens/matrix-session.native-chat-page-nativechat.readsession-1.json
#	mobile/rpc-foundation/goldens/matrix-session.native-chat-page-nativechat.subscribe-1-1.json
#	mobile/rpc-foundation/goldens/matrix-session.native-chat-page-nativechat.subscribe-2-1.json
#	mobile/rpc-foundation/goldens/matrix-session.native-chat-readability-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.native-chat-stop-orchestration.workerterminaluserinput-1.json
#	mobile/rpc-foundation/goldens/matrix-session.native-chat-stop-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-session.native-chat-stop-terminal.send-2.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-branch-context-git.branchcompare-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-branch-context-git.status-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-branch-context-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-branch-context-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-sidebar-github.prchecks-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-sidebar-github.prforbranch-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-sidebar-hostedreview.forbranch-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-sidebar-worktree.show-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-triage-agent.launchreplay-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-triage-preflight.detectagents-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-triage-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.pr-triage-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-session.review-branch-diff-git.branchdiff-1.json
#	mobile/rpc-foundation/goldens/matrix-session.review-file-diff-git.diff-1.json
#	mobile/rpc-foundation/goldens/matrix-session.review-file-diff-git.diff-2.json
#	mobile/rpc-foundation/goldens/matrix-session.review-file-diff-git.diff-3.json
#	mobile/rpc-foundation/goldens/matrix-session.review-git-mutations-git.discard-1.json
#	mobile/rpc-foundation/goldens/matrix-session.review-git-mutations-git.stage-1.json
#	mobile/rpc-foundation/goldens/matrix-session.review-git-mutations-git.stage-2.json
#	mobile/rpc-foundation/goldens/matrix-session.review-send-sheet-session.tabs.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.startup-worktree.activate-1.json
#	mobile/rpc-foundation/goldens/matrix-session.startup-worktree.activate-2.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-activation-session.tabs.activate-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-activation-terminal.focus-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-close-session-session.tabs.close-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-close-terminal.close-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-documents-markdown.readtab-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-rename-terminal.rename-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.activate-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tab-reveal-session.tabs.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.tabs-stream-health-session.tabs.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-display-mode-terminal.setdisplaymode-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-gesture-input-orchestration.workerterminaluserinput-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-gesture-input-terminal.clearbuffer-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-gesture-input-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-input-send-orchestration.workerterminaluserinput-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-input-send-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-inventory-terminal.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-paste-orchestration.workerterminaluserinput-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-paste-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-session.terminal-paste-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-session.worktree-connection-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-session.worktree-connection-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings-agent-read-preflight.detectremoteagents-1.json
#	mobile/rpc-foundation/goldens/matrix-settings-agent-read-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-settings-agent-read-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings-best-effort-settings.update-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.bot-overrides-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.home-providers-linear.status-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.home-providers-preflight.check-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.home-providers-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.new-tab-local-agents-preflight.detectagents-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.new-tab-local-agents-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.new-tab-local-agents-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.quick-commands-settings.getterminalquickcommands-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.quick-commands-settings.updateterminalquickcommands-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-host.platform-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.repo-metadata-ssh.listtargetsummaries-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-folderworkspace.list-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-projectgroup.list-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.resume-metadata-worktree.ps-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-hydration-linear.status-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-hydration-preflight.check-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-hydration-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-hydration-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-hydration-ui.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-workspace-create-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-workspace-create-worktree.create-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.task-workspace-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.workspace-context-linear.status-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.workspace-context-preflight.check-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.workspace-context-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.workspace-context-ui.get-1.json
#	mobile/rpc-foundation/goldens/matrix-settings.workspace-submit-settings.get-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.dictation-chunk-speech.dictation.chunk-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.dictation-session-speech.dictation.finish-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.dictation-session-speech.dictation.start-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.dictation-start-speech.dictation.cancel-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.dictation-start-speech.dictation.start-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.setup-sheet-speech.dictation.setup-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.setup-sheet-speech.models.delete-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.setup-sheet-speech.models.download-1.json
#	mobile/rpc-foundation/goldens/matrix-speech.setup-sheet-speech.models.list-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-checks-files-github.addprreviewcomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-checks-files-github.prfilecontents-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-checks-files-github.rerunprchecks-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-checks-files-github.resolvereviewthread-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-checks-files-github.setprfileviewed-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-comment-github-github.addissuecomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-comment-gitlab-gitlab.addissuecomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-comment-gitlab-mr-gitlab.addmrcomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-detail-github-github.workitemdetails-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-detail-gitlab-gitlab.workitemdetails-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-detail-linear-linear.getissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-detail-linear-linear.issuecomments-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-detail-metadata-github.listassignableusers-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-detail-metadata-github.listlabels-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-merge-gitlab-gitlab.mergemr-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-metadata-github-github.updatepr-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-metadata-gitlab-gitlab.updateissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-metadata-gitlab-mr-gitlab.updatemr-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-reply-merge-github.addissuecomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-reply-merge-github.addprreviewcommentreply-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-reply-merge-github.mergepr-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-reply-merge-linear.updateissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-review-github-github.prchecks-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-review-github-github.requestprreviewers-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-status-gitlab-github.updateissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-status-gitlab-gitlab.updateissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.item-status-gitlab-mr-gitlab.updatemrstate-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.linear-connect-linear.connect-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.linear-item-linear.addissuecomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.linear-item-linear.createissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.linear-item-linear.getissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.linear-team-context-linear.listteams-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.linear-team-context-linear.teamstates-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.paste-lookup-github.reposlug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.paste-lookup-github.workitem-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.paste-lookup-github.workitembyownerrepo-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.paste-lookup-gitlab.workitembypath-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-board-load-github.project.listaccessible-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-board-load-github.project.listviews-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-board-load-github.project.listviews-2.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-board-load-github.project.resolveref-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-board-load-github.project.viewtable-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-repo-slugs-github.reposlug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-comments-issue-github.project.addissuecommentbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-comments-issue-github.project.updateissuebyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-comments-issue-github.project.updateissuecommentbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-comments-pr-github.project.updatepullrequestbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-detail-github.project.workitemdetailsbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-fields-github.project.clearitemfield-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-fields-github.project.updateissuetypebyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-fields-github.project.updateitemfield-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-files-merge-github.addprreviewcomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-files-merge-github.mergepr-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-files-merge-github.prfilecontents-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-files-merge-github.updateissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-files-merge-github.updateprstate-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-metadata-load-github.project.listassignableusersbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-metadata-load-github.project.listissuetypesbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-metadata-load-github.project.listlabelsbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-review-checks-github.prchecks-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-review-checks-github.requestprreviewers-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-review-checks-github.rerunprchecks-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-review-checks-github.setprfileviewed-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-threads-github.addissuecomment-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-threads-github.addprreviewcommentreply-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-threads-github.project.deleteissuecommentbyslug-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.project-row-threads-github.resolvereviewthread-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.provider-load-github.countworkitems-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.provider-load-github.listworkitems-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.provider-load-linear.listteams-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.provider-load-linear.status-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.provider-load-settings.update-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.route-repo-list-repo.list-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.smart-source-search-github.listworkitems-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.smart-source-search-gitlab.listworkitems-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.smart-source-search-linear.listissues-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.smart-source-search-linear.searchissues-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.smart-source-search-repo.searchrefs-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-create-github-github.createissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-create-github-repo.update-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-create-gitlab-gitlab.createissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-create-linear-linear.createissue-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-list-gitlab-items-gitlab.listworkitems-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-list-gitlab-todos-gitlab.todos-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-list-linear-linear.listissues-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.task-list-linear-linear.searchissues-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-source-repo.searchrefs-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-source-repo.sparsepresets-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-sparse-repo.savesparsepreset-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-sparse-ssh.getstate-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-ssh-local-preflight.detectagents-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-ssh-preflight.detectremoteagents-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-ssh-repo.hooks-1.json
#	mobile/rpc-foundation/goldens/matrix-tasks.workspace-ssh-ssh.connect-1.json
#	mobile/rpc-foundation/goldens/matrix-terminal.query-reply-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-terminal.raw-input-orchestration.workerterminaluserinput-1.json
#	mobile/rpc-foundation/goldens/matrix-terminal.raw-input-terminal.send-1.json
#	mobile/rpc-foundation/goldens/matrix-terminal.takeover-report-orchestration.workerterminaluserinput-1.json
#	mobile/rpc-foundation/goldens/matrix-terminal.takeover-report-orchestration.workerterminaluserinput-2.json
#	mobile/rpc-foundation/goldens/matrix-terminal.viewport-refit-terminal.updateviewport-1.json
#	mobile/rpc-foundation/goldens/matrix-transport.capability-probe-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-transport.host-status-gates-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-transport.pairing-race-direct-status.json
#	mobile/rpc-foundation/goldens/matrix-transport.pairing-race-relay-status.json
#	mobile/rpc-foundation/goldens/matrix-worktree.agent-launch-create-agent.launch-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.catalog-snapshot-worktree.ps-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.create-retry-worktree.create-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.home-catalog-worktree.ps-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.hosted-base-worktree.resolvemrbase-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.hosted-base-worktree.resolveprbase-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.retired-names-worktree.listretirednames-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.review-link-worktree.set-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.runtime-capabilities-status.get-1.json
#	mobile/rpc-foundation/goldens/matrix-worktree.setup-hook-trust-ui.set-1.json
#	mobile/rpc-foundation/goldens/mobile-web-bundle-build-changed.json
#	mobile/rpc-foundation/goldens/mobile-web-bundle-fetch-paged.json
#	mobile/rpc-foundation/goldens/mobile-web-bundle-manifest-read.json
#	mobile/rpc-foundation/goldens/mobile-web-bundle-unavailable.json
#	mobile/rpc-foundation/goldens/native-chat-image-paste-single.json
#	mobile/rpc-foundation/goldens/native-chat-image-paste-stops-on-rejection.json
#	mobile/rpc-foundation/goldens/native-chat-image-paste-trailing-image.json
#	mobile/rpc-foundation/goldens/native-chat-image-paste-two-images.json
#	mobile/rpc-foundation/goldens/native-chat-image-upload-cancelled.json
#	mobile/rpc-foundation/goldens/native-chat-image-upload-second-fails.json
#	mobile/rpc-foundation/goldens/native-chat-image-upload-single.json
#	mobile/rpc-foundation/goldens/native-chat-image-upload-start-refused.json
#	mobile/rpc-foundation/goldens/native-chat-image-upload-two.json
#	mobile/rpc-foundation/goldens/native-chat-page-earlier.json
#	mobile/rpc-foundation/goldens/native-chat-readability-local-repo.json
#	mobile/rpc-foundation/goldens/native-chat-readability-refused.json
#	mobile/rpc-foundation/goldens/native-chat-readability-remote-repo.json
#	mobile/rpc-foundation/goldens/native-chat-session-option-pick-empty.json
#	mobile/rpc-foundation/goldens/native-chat-session-option-pick-refused.json
#	mobile/rpc-foundation/goldens/native-chat-session-option-pick-written.json
#	mobile/rpc-foundation/goldens/native-chat-stop-accepted.json
#	mobile/rpc-foundation/goldens/native-chat-stop-both-rejected.json
#	mobile/rpc-foundation/goldens/native-chat-stop-delivery-unknown.json
#	mobile/rpc-foundation/goldens/native-chat-write-accepted.json
#	mobile/rpc-foundation/goldens/native-chat-write-clear-line.json
#	mobile/rpc-foundation/goldens/native-chat-write-delivery-unknown.json
#	mobile/rpc-foundation/goldens/native-chat-write-rejected.json
#	mobile/rpc-foundation/goldens/native-chat-write-typed-command.json
#	mobile/rpc-foundation/goldens/new-tab-local-agents.json
#	mobile/rpc-foundation/goldens/new-workspace-repositories-fulfilled.json
#	mobile/rpc-foundation/goldens/notifications-desktop-stream-closed.json
#	mobile/rpc-foundation/goldens/notifications-desktop-stream-replayed.json
#	mobile/rpc-foundation/goldens/notifications-desktop-stream.json
#	mobile/rpc-foundation/goldens/notifications-display-test-accepted.json
#	mobile/rpc-foundation/goldens/notifications-display-test-not-registered.json
#	mobile/rpc-foundation/goldens/notifications-display-test-rate-limited.json
#	mobile/rpc-foundation/goldens/notifications-display-test-unknown-reason.json
#	mobile/rpc-foundation/goldens/notifications-push-gateway-rejected.json
#	mobile/rpc-foundation/goldens/notifications-push-registered.json
#	mobile/rpc-foundation/goldens/pairing-pre-profile-direct-wins-and-provisions.json
#	mobile/rpc-foundation/goldens/pairing-pre-profile-provision-unsupported-saves-direct-host.json
#	mobile/rpc-foundation/goldens/pairing-pre-profile-times-out.json
#	mobile/rpc-foundation/goldens/pr-branch-identity.json
#	mobile/rpc-foundation/goldens/pr-branch-repo-context.json
#	mobile/rpc-foundation/goldens/pr-comment-mutation.json
#	mobile/rpc-foundation/goldens/pr-comment-resolve-unconfirmed.json
#	mobile/rpc-foundation/goldens/pr-mutation-in-band-failure.json
#	mobile/rpc-foundation/goldens/pr-mutation-status.json
#	mobile/rpc-foundation/goldens/pr-read-fork-routing.json
#	mobile/rpc-foundation/goldens/pr-read-surface.json
#	mobile/rpc-foundation/goldens/pr-read-upstream-error.json
#	mobile/rpc-foundation/goldens/pr-sidebar-checks-refused.json
#	mobile/rpc-foundation/goldens/pr-sidebar-load.json
#	mobile/rpc-foundation/goldens/pr-title-mutation.json
#	mobile/rpc-foundation/goldens/pr-title-unconfirmed.json
#	mobile/rpc-foundation/goldens/pr-triage-launch-unconfirmed.json
#	mobile/rpc-foundation/goldens/pr-triage-launch.json
#	mobile/rpc-foundation/goldens/pr-triage-prompt-not-delivered.json
#	mobile/rpc-foundation/goldens/pr-triage-update-required.json
#	mobile/rpc-foundation/goldens/probe-new-tab-both-refused.json
#	mobile/rpc-foundation/goldens/probe-new-tab-null-sibling-refused.json
#	mobile/rpc-foundation/goldens/probe-new-tab-refused-sibling-rejects.json
#	mobile/rpc-foundation/goldens/probe-new-tab-rejects-sibling-refused.json
#	mobile/rpc-foundation/goldens/push-dismissal-tray-reconciled.json
#	mobile/rpc-foundation/goldens/quick-commands-load-refused.json
#	mobile/rpc-foundation/goldens/quick-commands-loaded-and-saved.json
#	mobile/rpc-foundation/goldens/quick-commands-save-refused-rolls-back.json
#	mobile/rpc-foundation/goldens/relay-direct-upgrade-commits.json
#	mobile/rpc-foundation/goldens/relay-direct-upgrade-unsupported-host-declines.json
#	mobile/rpc-foundation/goldens/relay-pairing-recovery-invite-authorizes.json
#	mobile/rpc-foundation/goldens/relay-pairing-recovery-resume-committed.json
#	mobile/rpc-foundation/goldens/relay-rotation-installs-and-commits.json
#	mobile/rpc-foundation/goldens/relay-rotation-resumes-committed-pending.json
#	mobile/rpc-foundation/goldens/review-branch-diff-shapes.json
#	mobile/rpc-foundation/goldens/review-create-agent-refused.json
#	mobile/rpc-foundation/goldens/review-file-diff-shapes.json
#	mobile/rpc-foundation/goldens/review-git-mutations-run.json
#	mobile/rpc-foundation/goldens/review-mark-reviewed-persists.json
#	mobile/rpc-foundation/goldens/review-mark-reviewed-rolls-back.json
#	mobile/rpc-foundation/goldens/review-open-in-session.json
#	mobile/rpc-foundation/goldens/review-send-notes-heals-stale-input.json
#	mobile/rpc-foundation/goldens/review-send-sheet-lists-terminals.json
#	mobile/rpc-foundation/goldens/review-stage-file.json
#	mobile/rpc-foundation/goldens/review-stage-refused.json
#	mobile/rpc-foundation/goldens/sc-base-ref-default.json
#	mobile/rpc-foundation/goldens/sc-base-ref-repo-fallback.json
#	mobile/rpc-foundation/goldens/sc-base-ref-unavailable.json
#	mobile/rpc-foundation/goldens/sc-base-ref-worktree-hit.json
#	mobile/rpc-foundation/goldens/sc-branch-diff-previewed.json
#	mobile/rpc-foundation/goldens/sc-changes-loaded.json
#	mobile/rpc-foundation/goldens/sc-commit-message-cancel-rejected.json
#	mobile/rpc-foundation/goldens/sc-commit-message-canceled.json
#	mobile/rpc-foundation/goldens/sc-commit-message-generated.json
#	mobile/rpc-foundation/goldens/sc-create-existing-review.json
#	mobile/rpc-foundation/goldens/sc-create-intent-stage-commit-push-create.json
#	mobile/rpc-foundation/goldens/sc-create-intent-unlisted-provider.json
#	mobile/rpc-foundation/goldens/sc-create-link-failure-is-non-fatal.json
#	mobile/rpc-foundation/goldens/sc-create-pushes-then-creates.json
#	mobile/rpc-foundation/goldens/sc-create-refused-empty-message.json
#	mobile/rpc-foundation/goldens/sc-create-rejected-empty-message.json
#	mobile/rpc-foundation/goldens/sc-eligibility-fetched.json
#	mobile/rpc-foundation/goldens/sc-history-commit-files.json
#	mobile/rpc-foundation/goldens/sc-history-loaded.json
#	mobile/rpc-foundation/goldens/sc-pr-link-hosted-review.json
#	mobile/rpc-foundation/goldens/sc-pr-link-read.json
#	mobile/rpc-foundation/goldens/sc-pr-link-set.json
#	mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-refusal.json
#	mobile/rpc-foundation/goldens/sc-prefill-unavailable-on-rejection.json
#	mobile/rpc-foundation/goldens/sc-prerequisite-force-with-lease.json
#	mobile/rpc-foundation/goldens/sc-prerequisite-publish.json
#	mobile/rpc-foundation/goldens/sc-prerequisite-push.json
#	mobile/rpc-foundation/goldens/sc-prerequisite-skipped.json
#	mobile/rpc-foundation/goldens/sc-reveal-first-poll.json
#	mobile/rpc-foundation/goldens/sc-reveal-timeout.json
#	mobile/rpc-foundation/goldens/sc-review-commit-inner-failure.json
#	mobile/rpc-foundation/goldens/sc-review-commit-refused-empty-message.json
#	mobile/rpc-foundation/goldens/sc-review-commit-rejected.json
#	mobile/rpc-foundation/goldens/sc-review-commit.json
#	mobile/rpc-foundation/goldens/sc-review-status-entries-not-array.json
#	mobile/rpc-foundation/goldens/sc-review-status-normalized.json
#	mobile/rpc-foundation/goldens/schedules-b3.json
#	mobile/rpc-foundation/goldens/schedules-settings-home-providers-fulfilled.json
#	mobile/rpc-foundation/goldens/schedules-settings-new-tab-ssh.json
#	mobile/rpc-foundation/goldens/schedules-settings-repo-metadata-fulfilled.json
#	mobile/rpc-foundation/goldens/schedules-settings-resume-metadata-fulfilled.json
#	mobile/rpc-foundation/goldens/schedules-settings-task-hydration-fulfilled.json
#	mobile/rpc-foundation/goldens/schedules-settings-workspace-context-fulfilled.json
#	mobile/rpc-foundation/goldens/session-browser-tab-created.json
#	mobile/rpc-foundation/goldens/session-create-browser-refused.json
#	mobile/rpc-foundation/goldens/session-create-browser-tab.json
#	mobile/rpc-foundation/goldens/session-create-markdown-name-collision.json
#	mobile/rpc-foundation/goldens/session-create-markdown-note.json
#	mobile/rpc-foundation/goldens/session-create-terminal-ignores-a-second-create-in-flight.json
#	mobile/rpc-foundation/goldens/session-create-terminal-launches-an-agent-quick-command.json
#	mobile/rpc-foundation/goldens/session-create-terminal-refused.json
#	mobile/rpc-foundation/goldens/session-create-terminal-replaces-active.json
#	mobile/rpc-foundation/goldens/session-create-terminal-runs-a-quick-command.json
#	mobile/rpc-foundation/goldens/session-create-terminal-with-prompt.json
#	mobile/rpc-foundation/goldens/session-create-terminal-without-active-tab.json
#	mobile/rpc-foundation/goldens/session-create-terminal-without-handle.json
#	mobile/rpc-foundation/goldens/session-diff-notes-load-refused.json
#	mobile/rpc-foundation/goldens/session-diff-notes-loaded.json
#	mobile/rpc-foundation/goldens/session-file-tab-read.json
#	mobile/rpc-foundation/goldens/session-markdown-disk-read.json
#	mobile/rpc-foundation/goldens/session-markdown-disk-served.json
#	mobile/rpc-foundation/goldens/session-markdown-save-conflict.json
#	mobile/rpc-foundation/goldens/session-markdown-saved.json
#	mobile/rpc-foundation/goldens/session-markdown-tab-disk-fallback.json
#	mobile/rpc-foundation/goldens/session-markdown-tab-read.json
#	mobile/rpc-foundation/goldens/session-markdown-tab-refused.json
#	mobile/rpc-foundation/goldens/session-startup-both-activation-sites.json
#	mobile/rpc-foundation/goldens/session-startup-floating-route-skips-activation.json
#	mobile/rpc-foundation/goldens/session-startup-keeps-terminals-visible-on-reconnect.json
#	mobile/rpc-foundation/goldens/session-startup-refused-tab-load-still-loads-terminals.json
#	mobile/rpc-foundation/goldens/session-tab-activation-focus-and-activate.json
#	mobile/rpc-foundation/goldens/session-tab-activation-refused.json
#	mobile/rpc-foundation/goldens/session-tab-activation-transport-error.json
#	mobile/rpc-foundation/goldens/session-tab-close-refused-keeps-tab.json
#	mobile/rpc-foundation/goldens/session-tab-close-session-tab.json
#	mobile/rpc-foundation/goldens/session-tab-close-terminal.json
#	mobile/rpc-foundation/goldens/session-tab-closed.json
#	mobile/rpc-foundation/goldens/session-tab-rename.json
#	mobile/rpc-foundation/goldens/session-tab-renamed.json
#	mobile/rpc-foundation/goldens/session-tabs-health-errored.json
#	mobile/rpc-foundation/goldens/session-tabs-health-reconciled.json
#	mobile/rpc-foundation/goldens/session-tabs-health-refused.json
#	mobile/rpc-foundation/goldens/session-tabs-health-stale-application-revision.json
#	mobile/rpc-foundation/goldens/session-terminal-display-mode-auto-take-floor.json
#	mobile/rpc-foundation/goldens/session-terminal-display-mode-auto-without-device-token.json
#	mobile/rpc-foundation/goldens/session-terminal-display-mode-auto-without-viewport.json
#	mobile/rpc-foundation/goldens/session-terminal-display-mode-drops-second-toggle.json
#	mobile/rpc-foundation/goldens/session-terminal-display-mode-to-desktop.json
#	mobile/rpc-foundation/goldens/session-terminal-list-dedupes-handles.json
#	mobile/rpc-foundation/goldens/session-terminal-list-empty-guarded.json
#	mobile/rpc-foundation/goldens/session-terminal-list-merged.json
#	mobile/rpc-foundation/goldens/session-terminal-list-refused.json
#	mobile/rpc-foundation/goldens/settings-bot-overrides-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-bot-overrides-refresh-refused.json
#	mobile/rpc-foundation/goldens/settings-bot-overrides-refused.json
#	mobile/rpc-foundation/goldens/settings-bot-overrides-transport-error.json
#	mobile/rpc-foundation/goldens/settings-home-coalesced.json
#	mobile/rpc-foundation/goldens/settings-home-providers-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-home-providers-refuse-after-data.json
#	mobile/rpc-foundation/goldens/settings-home-providers-refused.json
#	mobile/rpc-foundation/goldens/settings-home-providers-transport-error.json
#	mobile/rpc-foundation/goldens/settings-new-tab-refused.json
#	mobile/rpc-foundation/goldens/settings-new-tab-ssh.json
#	mobile/rpc-foundation/goldens/settings-new-tab-transport-error.json
#	mobile/rpc-foundation/goldens/settings-repo-cache-expiry.json
#	mobile/rpc-foundation/goldens/settings-repo-metadata-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-repo-metadata-icons.json
#	mobile/rpc-foundation/goldens/settings-repo-metadata-refuse-after-data.json
#	mobile/rpc-foundation/goldens/settings-repo-metadata-refused.json
#	mobile/rpc-foundation/goldens/settings-repo-metadata-single-host.json
#	mobile/rpc-foundation/goldens/settings-repo-metadata-transport-error.json
#	mobile/rpc-foundation/goldens/settings-resume-metadata-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-resume-metadata-refuse-after-data.json
#	mobile/rpc-foundation/goldens/settings-resume-metadata-refused.json
#	mobile/rpc-foundation/goldens/settings-resume-metadata-transport-error.json
#	mobile/rpc-foundation/goldens/settings-task-hydration-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-task-hydration-refuse-after-data.json
#	mobile/rpc-foundation/goldens/settings-task-hydration-refused.json
#	mobile/rpc-foundation/goldens/settings-task-hydration-transport-error.json
#	mobile/rpc-foundation/goldens/settings-task-workspace-create-linear.json
#	mobile/rpc-foundation/goldens/settings-task-workspace-create-pr-start-point.json
#	mobile/rpc-foundation/goldens/settings-task-workspace-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-task-workspace-refused.json
#	mobile/rpc-foundation/goldens/settings-task-workspace-transport-error.json
#	mobile/rpc-foundation/goldens/settings-task-write.json
#	mobile/rpc-foundation/goldens/settings-workspace-context-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-workspace-context-refuse-after-data.json
#	mobile/rpc-foundation/goldens/settings-workspace-context-refused.json
#	mobile/rpc-foundation/goldens/settings-workspace-context-transport-error.json
#	mobile/rpc-foundation/goldens/settings-workspace-submit-fulfilled.json
#	mobile/rpc-foundation/goldens/settings-workspace-submit-refused.json
#	mobile/rpc-foundation/goldens/settings-workspace-submit-transport-error.json
#	mobile/rpc-foundation/goldens/speech-audio-chunk-acknowledged.json
#	mobile/rpc-foundation/goldens/speech-desktop-start-fulfilled.json
#	mobile/rpc-foundation/goldens/speech-desktop-start-recording-failed.json
#	mobile/rpc-foundation/goldens/speech-desktop-start-superseded.json
#	mobile/rpc-foundation/goldens/speech-dictation-session-cancelled.json
#	mobile/rpc-foundation/goldens/speech-dictation-session-transcript.json
#	mobile/rpc-foundation/goldens/speech-setup-sheet-denied-to-mobile.json
#	mobile/rpc-foundation/goldens/speech-setup-sheet-fulfilled.json
#	mobile/rpc-foundation/goldens/speech-setup-sheet-legacy-desktop.json
#	mobile/rpc-foundation/goldens/speech-setup-sheet-model-vocabulary.json
#	mobile/rpc-foundation/goldens/structured-agent-session-created.json
#	mobile/rpc-foundation/goldens/structured-launch-created.json
#	mobile/rpc-foundation/goldens/structured-launch-definitive-refusal.json
#	mobile/rpc-foundation/goldens/structured-launch-replays-dropped-create.json
#	mobile/rpc-foundation/goldens/structured-launch-support-refused.json
#	mobile/rpc-foundation/goldens/structured-launch-unsupported.json
#	mobile/rpc-foundation/goldens/tasks-route-repo-list.json
#	mobile/rpc-foundation/goldens/terminal-gesture-flush-and-clear.json
#	mobile/rpc-foundation/goldens/terminal-input-send-accepted.json
#	mobile/rpc-foundation/goldens/terminal-input-send-refused.json
#	mobile/rpc-foundation/goldens/terminal-live-input-accepted.json
#	mobile/rpc-foundation/goldens/terminal-paste-accepted.json
#	mobile/rpc-foundation/goldens/terminal-paste-refused.json
#	mobile/rpc-foundation/goldens/terminal-query-reply-accepted.json
#	mobile/rpc-foundation/goldens/terminal-query-reply-unsubscribed.json
#	mobile/rpc-foundation/goldens/terminal-raw-input-refused.json
#	mobile/rpc-foundation/goldens/terminal-raw-input-reported.json
#	mobile/rpc-foundation/goldens/terminal-takeover-report-accepted.json
#	mobile/rpc-foundation/goldens/terminal-takeover-report-retried.json
#	mobile/rpc-foundation/goldens/terminal-viewport-refit-applied.json
#	mobile/rpc-foundation/goldens/terminal-viewport-refit-legacy-desktop.json
#	mobile/rpc-foundation/goldens/terminal-worktree-connection-resolved.json
#	mobile/rpc-foundation/goldens/tk-create-github.json
#	mobile/rpc-foundation/goldens/tk-create-gitlab.json
#	mobile/rpc-foundation/goldens/tk-create-linear.json
#	mobile/rpc-foundation/goldens/tk-item-checks-files.json
#	mobile/rpc-foundation/goldens/tk-item-comment-github.json
#	mobile/rpc-foundation/goldens/tk-item-comment-gitlab-mr.json
#	mobile/rpc-foundation/goldens/tk-item-comment-gitlab.json
#	mobile/rpc-foundation/goldens/tk-item-detail-github-reactions.json
#	mobile/rpc-foundation/goldens/tk-item-detail-github.json
#	mobile/rpc-foundation/goldens/tk-item-detail-gitlab-reactions.json
#	mobile/rpc-foundation/goldens/tk-item-detail-gitlab.json
#	mobile/rpc-foundation/goldens/tk-item-detail-linear.json
#	mobile/rpc-foundation/goldens/tk-item-detail-metadata.json
#	mobile/rpc-foundation/goldens/tk-item-merge-gitlab.json
#	mobile/rpc-foundation/goldens/tk-item-metadata-github.json
#	mobile/rpc-foundation/goldens/tk-item-metadata-gitlab-mr.json
#	mobile/rpc-foundation/goldens/tk-item-metadata-gitlab.json
#	mobile/rpc-foundation/goldens/tk-item-reply-merge.json
#	mobile/rpc-foundation/goldens/tk-item-review-github.json
#	mobile/rpc-foundation/goldens/tk-item-status-gitlab-mr.json
#	mobile/rpc-foundation/goldens/tk-item-status-gitlab.json
#	mobile/rpc-foundation/goldens/tk-linear-connect.json
#	mobile/rpc-foundation/goldens/tk-linear-item.json
#	mobile/rpc-foundation/goldens/tk-linear-team-context.json
#	mobile/rpc-foundation/goldens/tk-list-gitlab-items.json
#	mobile/rpc-foundation/goldens/tk-list-gitlab-todos.json
#	mobile/rpc-foundation/goldens/tk-list-linear.json
#	mobile/rpc-foundation/goldens/tk-project-board-load.json
#	mobile/rpc-foundation/goldens/tk-project-repo-slugs.json
#	mobile/rpc-foundation/goldens/tk-project-row-comments-issue.json
#	mobile/rpc-foundation/goldens/tk-project-row-comments-pr.json
#	mobile/rpc-foundation/goldens/tk-project-row-detail.json
#	mobile/rpc-foundation/goldens/tk-project-row-fields.json
#	mobile/rpc-foundation/goldens/tk-project-row-files-merge.json
#	mobile/rpc-foundation/goldens/tk-project-row-metadata-load.json
#	mobile/rpc-foundation/goldens/tk-project-row-review-checks.json
#	mobile/rpc-foundation/goldens/tk-project-row-threads.json
#	mobile/rpc-foundation/goldens/tk-provider-load.json
#	mobile/rpc-foundation/goldens/transport-capability-probe-cutover-reasks-fast.json
#	mobile/rpc-foundation/goldens/transport-capability-probe-non-string-capabilities-drop.json
#	mobile/rpc-foundation/goldens/transport-capability-probe-publishes.json
#	mobile/rpc-foundation/goldens/transport-capability-probe-refused-backs-off.json
#	mobile/rpc-foundation/goldens/transport-host-status-gates-drop-keeps-capabilities.json
#	mobile/rpc-foundation/goldens/transport-host-status-gates-ready.json
#	mobile/rpc-foundation/goldens/transport-host-status-gates-refused-degrades.json
#	mobile/rpc-foundation/goldens/transport-pairing-race-both-refused.json
#	mobile/rpc-foundation/goldens/transport-pairing-race-direct-completes-first.json
#	mobile/rpc-foundation/goldens/transport-pairing-race-relay-completes-first.json
#	mobile/rpc-foundation/goldens/transport-pairing-race-relay-wins-when-direct-refused.json
#	mobile/rpc-foundation/goldens/tw-capabilities-advertised.json
#	mobile/rpc-foundation/goldens/tw-capabilities-cutover-retried.json
#	mobile/rpc-foundation/goldens/tw-capabilities-legacy-idempotency.json
#	mobile/rpc-foundation/goldens/tw-create-retry-agent-launched.json
#	mobile/rpc-foundation/goldens/tw-create-retry-ambiguous-after-drop.json
#	mobile/rpc-foundation/goldens/tw-create-retry-ambiguous-while-connected.json
#	mobile/rpc-foundation/goldens/tw-create-retry-ambiguous-without-idempotency.json
#	mobile/rpc-foundation/goldens/tw-create-retry-created.json
#	mobile/rpc-foundation/goldens/tw-create-retry-name-collision.json
#	mobile/rpc-foundation/goldens/tw-create-retry-unretryable-refusal.json
#	mobile/rpc-foundation/goldens/tw-create-retry-warning-kept.json
#	mobile/rpc-foundation/goldens/tw-hosted-base-resolved.json
#	mobile/rpc-foundation/goldens/tw-hosted-base-soft-error.json
#	mobile/rpc-foundation/goldens/tw-paste-lookup-resolved.json
#	mobile/rpc-foundation/goldens/tw-paste-lookup-slug-refused.json
#	mobile/rpc-foundation/goldens/tw-paste-lookup-slug-unsupported.json
#	mobile/rpc-foundation/goldens/tw-setup-hook-trust-always.json
#	mobile/rpc-foundation/goldens/tw-setup-hook-trust-approved.json
#	mobile/rpc-foundation/goldens/tw-smart-search-all-providers.json
#	mobile/rpc-foundation/goldens/tw-smart-search-gitlab-provider-error.json
#	mobile/rpc-foundation/goldens/tw-smart-search-linear-listed.json
#	mobile/rpc-foundation/goldens/tw-task-preferences-resume-write.json
#	mobile/rpc-foundation/goldens/tw-workspace-source-presets-refused.json
#	mobile/rpc-foundation/goldens/tw-workspace-source-presets.json
#	mobile/rpc-foundation/goldens/tw-workspace-sparse-missing-preset.json
#	mobile/rpc-foundation/goldens/tw-workspace-sparse-saved.json
#	mobile/rpc-foundation/goldens/tw-workspace-ssh-connect-refused.json
#	mobile/rpc-foundation/goldens/tw-workspace-ssh-connected.json
#	mobile/rpc-foundation/goldens/tw-workspace-ssh-local-agents.json
#	mobile/rpc-foundation/goldens/tw-workspace-ssh-not-ready.json
#	mobile/rpc-foundation/goldens/worktree-catalog-snapshot-unreadable.json
#	mobile/rpc-foundation/goldens/worktree-catalog-snapshot.json
#	mobile/rpc-foundation/goldens/worktree-home-catalog.json
#	mobile/rpc-foundation/goldens/worktree-retired-names.json
#	mobile/rpc-foundation/pilot-scenarios.json
#	mobile/src/test-support/bridged-parity/divergence-classes.ts
#	mobile/src/test-support/rpc-recording/README.md
…r-free format

Main's #23732 dropped the golden header and pin, so the merge took main's goldens whole and
`rpc:record --prune` re-derived them. Only the six desktop-notification recordings this branch
changes move, decoded-identical to their pre-merge recordings, and the obsolete
`unsubscribe-1` matrix golden is pruned.

@pullfrog pullfrog Bot 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.

✅ No new issues found.

Reviewed changes

Incremental delta since the prior pullfrog review (a09d1e0, review 5359972404): the branch merged origin/main at 8b01590847 and re-recorded the desktop-notification goldens on the header-free format.

  • Merged origin/main (8b01590847) — brings #23732, which dropped the golden header and pin, plus unrelated main churn. The resolution keeps this PR's release paths intact: isReadyIdStream still routes every ready-id feed through disposeServerSubscription (direct) and the cancelled-placeholder release (relay), and markForReplay still clears stream.subscriptionId.
  • Re-recorded the six desktop-notification goldens — the recordings now show only the transport's notifications.unsubscribe wire frame, with the former feature-code sender calls (args + settlement) removed, and the obsolete matrix-notifications.desktop-stream-notifications.unsubscribe-1 golden pruned. The replayed golden records the old connection's sub-1 stop (frame-4) alongside the new sub-2 stop (frame-6).
  • Doc and count touch-ups — the recorder README, page-closure headers, and parity test comments follow the header-free corpus (789 goldens, 398 scenarios).

I replayed the corpus on this head — the full mobile rpc-recording suite (1752 passed, 3 skipped, including rpc-recording-through-bridge at 795 passed) and the bridged-parity suite — and re-ran the PR's transport/notification suites (39 passed). The re-recorded bodies match the already-reviewed fix; nothing the merge brought altered this PR's behavior.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 7047976f-e9b2-46d4-a013-2f3738c40d30

📥 Commits

Reviewing files that changed from the base of the PR and between 8b01590 and 05e9977.

📒 Files selected for processing (29)
  • mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.getmissedsince-1.json
  • mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.subscribe-1-1.json
  • mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.subscribe-1-2.json
  • mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.unsubscribe-1.json
  • mobile/rpc-foundation/goldens/notifications-desktop-stream-closed.json
  • mobile/rpc-foundation/goldens/notifications-desktop-stream-replayed.json
  • mobile/rpc-foundation/goldens/notifications-desktop-stream.json
  • mobile/rpc-foundation/pilot-scenarios.json
  • mobile/src/notifications/desktop-notification-stream-operations.ts
  • mobile/src/notifications/mobile-notifications.test.ts
  • mobile/src/notifications/mobile-notifications.ts
  • mobile/src/test-support/bridged-parity/c1-page-closure.ts
  • mobile/src/test-support/bridged-parity/c2-page-closure.ts
  • mobile/src/test-support/bridged-parity/c3-page-closure.ts
  • mobile/src/test-support/bridged-parity/c5-page-closure.ts
  • mobile/src/test-support/bridged-parity/divergence-classes.test.ts
  • mobile/src/test-support/bridged-parity/divergence-classes.ts
  • mobile/src/test-support/rpc-recording/README.md
  • mobile/src/test-support/rpc-recording/adapters/desktop-notification-stream-mount-adapters.ts
  • mobile/src/test-support/rpc-recording/rpc-recording-through-bridge.test.ts
  • mobile/src/test-support/rpc-recording/run-recording.ts
  • mobile/src/transport/mobile-relay-rpc-streams.test.ts
  • mobile/src/transport/mobile-relay-rpc-streams.ts
  • mobile/src/transport/rpc-client-ready-stream-release.test.ts
  • mobile/src/transport/rpc-client-server-subscription.ts
  • mobile/src/transport/rpc-client-stream-registry.ts
  • mobile/src/transport/rpc-subscription-boundary.test.ts
  • mobile/src/transport/rpc-subscription-inventory.ts
  • mobile/src/transport/unvalidated-rpc-request-port-inventory.ts
💤 Files with no reviewable changes (3)
  • mobile/rpc-foundation/goldens/matrix-notifications.desktop-stream-notifications.unsubscribe-1.json
  • mobile/src/notifications/desktop-notification-stream-operations.ts
  • mobile/rpc-foundation/pilot-scenarios.json

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

The RPC transport now maps ready-ID stream methods to their unsubscribe methods and handles release when a stream is disposed before or after readiness. Notification code no longer sends its own unsubscribe RPC. Tests and recording fixtures now cover direct and relay transports, stream teardown, and updated notification traces. The bridged-parity corpus counts also reflect the revised recordings.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 05e99

The change centralizes subscription cleanup while retaining notification handling and catch-up behavior. No actionable merge-blocking issue is identified; merge after normal checks. Live phone validation remains unperformed.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 05e99

The change improves background-feed cleanup without an identified new attack path. Confidence remains limited because cleanup after a lost connection has not been fully verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • observed — The new automatic release behavior is bounded to four fixed stream-to-release mappings. The mapping does not accept a caller-selected release method; it extends cleanup behavior rather than granting a new general-purpose RPC capability.

Trust Boundaries and Controls

  • observed — Release identity comes from server response metadata correlated to the locally tracked opener request. Transport ownership removes the notification feature's independently retained ticket, and direct replay explicitly forgets the old connection's ID. Desktop enforcement of subscription ownership was not verified.

Resilience and Maintainability Implications

  • observed — Relay clear discards active streams and pending cleanup entries. Both release paths remove local bookkeeping without awaiting server confirmation, so cleanup after failed dispatch or connection replacement depends on desktop lifecycle behavior that the reviewed mobile source does not establish.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 19 files. (7 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: moving notification and account stream release into the mobile transport layer.
Description check ✅ Passed The description is complete and well structured. It includes the problem, scope, implementation details, rationale, linked issue, visual proof, testing evidence, review considerations, and completed c…
Full details: Docstring Coverage

Explanation

Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 19 files. (7 skipped: 7 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ream-transport-release

Corpus is 793 goldens: main's 794 (four #22954 launch goldens) minus this
branch's deleted notification-unsubscribe matrix. Bridged tally 401 identical,
342 / 3 / 6 / 33 / 8, confirmed by replay; re-record with --prune moved nothing.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Reviewed and tested. Status: ready for review. This is the last step of the terminal subscription identity series (#22928).

What it fixes, as a user would see it. The phone never stopped some background feeds it opened on the desktop. Every visit to the phone's Accounts screen left one more account-list feed running on the desktop. A notifications feed closed before its first reply could also stay open, and one could be left stopped with an out-of-date id after the phone switched between a direct and a relay connection. With this change, the phone's connection layer ends every feed the desktop gave an id to, including one closed before the desktop's first reply.

Review. A fresh review ran after merging current main, because the same phone connection files changed several times in between. It covered readiness at the start and the end, an up-front architecture challenge, a precedent check, and two review rounds. The final round was clean or nits-only. Every stream the phone opens now has an explicit way to end. Only notifications and accounts used the removed guess (unsubscribe method name derived from the subscribe name), and both are in the release table. Mixed versions are safe: every desktop that serves these feeds already accepts notifications.unsubscribe and accounts.unsubscribe with the id it issued. There is no desktop change. The recorded goldens differ from main by exactly this PR's six notification recordings plus one deleted recording.

Testing. Live QA used an iOS simulator paired to an isolated desktop host built from main, running main's phone app first and then this branch's phone app. The desktop's feed registrations and listener counts were watched throughout.

Check main's phone app this PR
Account feeds still on the desktop after 3 visits to the Accounts screen leaked: listeners 1 → 2 → 3 → 4 released each time: back to 1
Phone receives a desktop notification yes yes
Notifications after a hard desktop restart, and after the phone reconnects yes yes
Extra notification listeners left on the desktop none none
Terminal open / send / leave / return, 3 cycles not run every send executed

Accounts screen on this build:
after-pr-accounts-screen-loaded.png

Reconnected after a hard desktop restart:
after-pr-after-host-restart-reconnected.png

Terminal sends after leaving and returning:
after-pr-cycle3-send-R32C3.png

Typecheck (host and mobile) passes, and all CI checks pass on 87e46dd.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Second round of live phone QA on 87e46dd: regression checks for the other feeds this PR's stop path touches. Each was run first with main's phone app, then with this PR's phone app, against the same isolated desktop built from main. Every check passed, and nothing behaved unexpectedly.

Check main's phone app this PR
Browser preview: open, leave and reopen, 3 times, plus leaving by switching tabs renders every time; desktop drops the preview after each leave; desktop "mobile is driving" overlay clears same; one stop per leave, each with that preview's own id
Live worktree name and worktree list: rename and create on the desktop; leave and return 3 times phone updates live; desktop feeds go 0 → 1 → 0 each cycle same
Notification, dismiss on desktop, graceful desktop restart, then notify again delivered once, dismissal reaches the phone, one listener per phone same
Accounts screen, 3 visits desktop registrations 2 → 3 → 4, still 4 after leaving (leak) 2 on every visit, back to 1 after leaving
Home screen: disconnect, connect, remove and re-pair a desktop counts return to baseline each time same; each stop names the current connection's id
Relay connection blocked blocked

Limits of this round:

  • Relay: not tested live. A development build cannot create a relay pairing ("Orca Relay is not available on this desktop"). The relay changes are covered by unit tests only.
  • Notifications: the simulator receives no Apple push notifications, so delivery and dismissal were confirmed on the phone's connection to the desktop, not as system banners.
  • Accounts: the test desktop has no logged-in accounts, so the only switch available was to "System default". Selecting it stuck on both builds.

Browser preview on the phone, second open:
pr-preview-open-2.png

Desktop after the phone left the preview, with no phone-control overlay:
pr-host-after-leave-2.png

The phone header after the worktree was renamed on the desktop:
pr-header-renamed-live.png

@brennanb2025
brennanb2025 merged commit 3793c58 into main Oct 3, 2026
26 checks passed
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