ff22b18913
Routing the branch create to the parent's owning connection was only half the job. The child then landed in the sidebar as a row that lied about who owned it, so the chat pane spun forever on "draft: branch #1" and never hydrated — the create was right, the row was wrong. upsertOptimisticSession stamps the row's profile from $activeGatewayProfile and omits connection_id entirely when no owner is passed (utils.ts:1318-1342), and it also skips setSessionOwnerHint. The branch call site passed no owner, so the child got NEITHER a row tag NOR a hint. resumeSession's owner ladder starts at `capturedOwner || getSessionOwnerHint(storedSessionId)` and forkBranch calls it without a capturedOwner, so the missing hint alone was enough to send the resume to whichever backend happened to be active. Pass the parent's route as the owner argument, restoring both mechanisms. The two sibling routed creates in this file already did exactly this. The tile path had the same defect one rung further out. A branch of a session that is not the open chat opens a tile instead of resuming, and SessionTileChrome resolved its owner from the tile route alone. openSessionTile is called for a branch child with no workspaceScope, and session-states.ts only persists a tile ownerRoute in bots mode, so that tile had no owner at all and its model + composer RPCs fell back to the ambient socket. Use the same tile-route-then-row ladder its sibling in session-tile-actions.ts already uses, resolved per render so it cannot go stale against the tile store, the recents/cron/messaging rows, or the hint map, with only the resulting identity memoised on primitives. An untagged parent row still reproduces the previous ambient behaviour exactly, so single-connection users are unaffected. Verified end to end against two real gateways: a session owned by a remote connection, branched through the actual sidebar context menu in a running dev app. The remote gateway served the create (ws closed ... messages=11 detached_sessions=1) and the resulting row polled stable at connection_id = the remote for the full 8s window. Before the fix the same gesture produced a row with no connection_id.