@@ -35,9 +35,10 @@ const (
3535// token_count.total_token_usage is a running SESSION total (not per-turn
3636// scale like turn.completed usage), so each emission is an absolute count —
3737// matching consumers' overwrite-not-sum semantics. Duplicate totals are
38- // suppressed so we only emit on real movement. emitted is set after the
39- // first successful send; the parser uses it to suppress its per-turn-scale
40- // stdout emissions so a single source stays authoritative.
38+ // suppressed so we only emit on real movement. emitted is set immediately
39+ // before each send (never after — see drain) so it is observable no later
40+ // than the Tokens event itself; the parser uses it to suppress its
41+ // per-turn-scale stdout emissions so a single source stays authoritative.
4142//
4243// Returns when stop is closed (the stdout stream ended) — after one final
4344// catch-up drain of the file, so the last token_count codex wrote is not
@@ -126,11 +127,19 @@ func (t *rolloutTail) drain() error {
126127 continue
127128 }
128129 t .lastIn , t .lastOut = in , outTok
130+ // Set emitted BEFORE the send: the parser suppresses its
131+ // per-turn-scale turn.completed Tokens once the tailer has
132+ // emitted, so the flag must be observable no later than the
133+ // Tokens event itself. Storing after the send leaves a window
134+ // where a consumer sees the tailer's Tokens while emitted is
135+ // still false, letting a concurrent turn.completed leak a
136+ // per-turn value and flap the counter between scales.
137+ //
129138 // Unconditional send is safe: the parser waits for the
130139 // tailer before closing the channel, and the run contract
131140 // guarantees the consumer drains until close.
132- t .out <- reviewtypes.Tokens {In : in , Out : outTok }
133141 t .emitted .Store (true )
142+ t .out <- reviewtypes.Tokens {In : in , Out : outTok }
134143 }
135144 }
136145 if readErr != nil {
0 commit comments