c24ff38c51
prompt.submit honored truncate_before_user_ordinal on every request. A client that carried a leftover ordinal into an ordinary send therefore issued something the gateway could not tell apart from a real rewind — same method, same shape, an in-range target — and the cut was applied with replace_messages(), which DELETEs the durable rows. One report lost 244 messages (296 -> 52) with no prompt and nothing to restore from. The existing guard only covered ordinal 0, where the cut empties the transcript; a mid-session ordinal sailed straight through. Only the client knows whether a submit is a rewind, an edit, or a regenerate, so require it to say so: an ordinal without confirm_truncate is refused on 4029 and neither memory nor the DB is touched. Desktop sends the flag from the one place that builds these params, so every rewind path is covered and a stale build fails closed with an actionable error instead of quietly deleting a conversation.