SIGN IN SIGN UP

fix(canvas): keep a new card's first message and its caret

A conversation card with no row yet streams under a virtual runtime id derived
from its connection key. The first send mints the row and swaps the card, so the
message just sent, the reply already answering it, and the `awaiting_persist`
that protects both from the next detail fetch were all left behind in the draft's
session while the arriving card mounted on an empty one. The live sink follows
the inherited connection key, which made that read as a rendering fault rather
than a lost message: the agent's answer streamed in and settled normally, under a
transcript that said there were no messages yet, with the user's own message the
one thing missing.

The arriving card now adopts that session in a layout effect, which is the only
point where the draft is provably gone — ReactFlow applies a changed `nodes` prop
from a passive effect, so the draft card outlives the render that drops it from
the board, and moving the session out any earlier empties a card still on screen.
A send rejected after the hand-off now rolls back against both ids instead of
stranding the failed message on the card that took over.

The draft node also carried no `dragHandle`, so every mousedown anywhere in it
passed d3-drag's filter, and d3 answers by preventing `selectstart` on the window
for the life of the gesture — the same event browsers gate caret placement on.
Clicking into the composer focused the textarea without moving the cursor, and no
text in the card could be selected. It now drags by its title bar, like the
expanded card.
X
xintaofei committed
95456b47ec8c89d3781db76f7fcdb4b055eb38d1
Parent: 86f57fc