SIGN IN SIGN UP

fix(chat): keep a forked conversation on the session it forked to

A fork re-points the open row at S2 and inserts a sibling row holding the
pre-fork session S1. The panel learned S2 from the fork response at once,
but resolved the id it reconnects with as
`detail?.summary.external_id ?? runtimeExternalId` — and `detail` still
said S1 until its refetch landed. So the next reconnect asked for S1,
which the new sibling now owned, and the tab silently re-homed onto the
pre-fork history with the [Fork] row abandoned. Forking again forked S1 a
second time; the conversation table records the chain, each row created
at one fork's timestamp and itself forked at the next.

Resolve from the runtime store instead. It is fed by BOTH sources — the
DB value is written into it whenever detail changes, and the live session
id when SessionStarted fires — so it is always the more recently
established of the two, with detail left as the cold-open fallback.

The visible symptom was the composer's model and effort changing after a
fork: the tab had landed on a session it never established, so the
selectors were whatever that session defaulted to. Carry the parent's
selectors across the fork as well, since `session/resume` answers with
the agent's defaults and nothing else re-applies them: read the mode and
config values off the session being left and replay them through the same
preference path a reconnect uses, a no-op per option when the value
already matches.
X
xintaofei committed
039ee6908faa989c6dc9d6f1f8dc122325924c49
Parent: 8b179c8