finalizeTurn freezes the finished turn's wall-clock summary into the status bar (shown at idle until the next submit) and logs the totals. outcome is the finish glyph: ✓ clean, ✗ abort/stall. The bar's avg tok/s divides lastTokens by lastElapsed (wall-clock), so it stays self-verifying against the d
(outcome turnOutcome)
| 877 | m.budget = e.Budget |
| 878 | if e.ContextWindow > 0 { |
| 879 | m.liveContextSize[m.cfg.Active] = e.ContextWindow |
| 880 | } |
| 881 | delta := e.Tokens |
| 882 | if delta == 0 { |
| 883 | delta = m.streamingEstimate |
| 884 | } |
| 885 | m.turnTokens += delta |
| 886 | m.sessionTokens += delta |
| 887 | m.streamingEstimate = 0 |
| 888 | m.connected = true |
| 889 | // Round-level reasoning first (it preceded the answer), then the assistant |
| 890 | // message, then the round metrics, so the log reads in causal order. |
| 891 | if r := m.reasoning.String(); r != "" { |
| 892 | dbgWritef("reasoning", "%s", r) |
| 893 | } |
| 894 | m.reasoning.Reset() |
| 895 | if e.Final != nil { |
| 896 | dbgWriteMessage("assistant", *e.Final) |
| 897 | m.history = append(m.history, *e.Final) |
| 898 | } |
| 899 | budgetNote := "" |
| 900 | if e.Budget.Set { |
| 901 | budgetNote = fmt.Sprintf(" · budget=%.1f%% pass", e.Budget.Remaining*100) |
| 902 | } |
| 903 | // prompt_tokens (server-counted, 0 = not reported) sits beside the request |
| 904 | // record's char/4 estimate so a forensic pass can calibrate the packer's |
| 905 | // undercount on real histories. Log-only; nothing reads it back. |
| 906 | dbgWritef("round_done", "tokens=%d (counted=%d) · prompt_tokens=%d · elapsed=%s · ctx_window=%d%s", |
| 907 | e.Tokens, delta, e.PromptTokens, e.Elapsed.Round(time.Millisecond), e.ContextWindow, budgetNote) |
| 908 | // Tripwire for the packer's blind spot: char/4 undercounts code-heavy |