A programmatic setDraft commit resets the controlled textarea's caret
(observed landing at the start of the value), so every later insert probed
the reset position and the stack drifted (A|B + C + D became |DACB).
placeComposerCaretAfterInsert puts the caret right after the inserted text
once the value commit lands - the index accounts for the left-side
separating space - and is guarded by a value-sync check plus a two-frame
retry, so a newer edit or a different composer wins untouched.
spliceInsert now reports the caret index together with the spliced draft
so the placement math cannot drift from the join logic. Nothing else moves:
the pure insertAtCaret surface is unchanged.
appendToDraft always spliced at the end of the draft. The conversation
service exposes no caret API, so probe the live composer textarea selection
from the DOM (value-sync guarded) and splice at that position with
whitespace-aware joins; an unknown or stale caret falls back to appending.
The explorer @-reference shares this path, so it inserts at the caret too.