Render+tokenize one SFT row to ids + a prompt boundary.
messages: render full conversation (addGenerationPrompt:false); the
prompt boundary is the render of all-but-last-turn with
addGenerationPrompt:true (so the assistant's response is the unmasked
region). Prefix-match fallback if the boundary render isn't a prefix.
prompt-completion: encode(prompt) is the boundary; full = prompt+completion.
text: bare text, promptLen=0 (no boundary — full-sequence loss).
Render+tokenize one SFT row to ids + a prompt boundary.