SIGN IN SIGN UP

fix(stream): detect a divergent retry instead of splicing two generations (#402)

StreamPrintSink tracked only a character-count high-water mark. It assumed a
retried generation reproduces the same prefix, so it emitted
content[emittedCount...] of the new attempt. Nothing compared the characters --
only the counts. When the retry produced different wording, which is the normal
case at any temperature above 0, the user saw attempt one's prefix welded to the
tail of attempt two: text the model never generated.

Silent output corruption on the CLI's primary streaming path, with exit code 0
and prose that looks plausible, so neither a human nor a script could tell. That
is strictly worse than the duplicated output #182 fixed -- that was visible,
this was not.

The sink now keeps the emitted text, not just its length, and compares prefixes.
A convergent retry behaves exactly as before; a divergent one emits a visible
marker and then the new response in full.

The marker goes in-band on stdout rather than to stderr, which is a real
trade-off and deliberate. Attempt one's partial text has already been printed
and cannot be recalled, so the corruption is in the stdout byte stream either
way; putting the notice there is what makes it detectable by whatever consumes
that stream, instead of leaving a clean-looking splice. Keeping stdout pure
would mean a silent concatenation of two generations, which is the bug.

Diff taken from candidate PR #415.

Closes #402

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011ccLBbEaVVd4sJyUd5wyhA
A
Arthur Ficial committed
f45d04f98df93e5af9a6472cceec2c0053184c28
Parent: d0984ad