489cfee1f0
Operator: "first turn double prints agent's turn." Root cause: v0.8.1 wrote both the streamed Text lines AND the post- Done `Markdown(event.response)` body into the transcript. Same content rendered twice — once as plain streaming, once as a full markdown re-render. The v0.8.1 commit message documented this as "some duplication is acceptable" but the live UX read as a bug. ## Fix Drop the post-Done `Rule + Markdown(response)` writes in non-raw mode. The streamed text IS the response; whatever the model emitted flows into the transcript line-by-line via coalesce-on-newline. Markdown formatting (bold, lists, code blocks) renders as plain text — a known regression from v0.8.1's polished output but the right tradeoff vs the duplication bug. ## What this loses temporarily Pre-v0.8.2 (after Done): [done] turn_id=... ─── ─── (Rule separator) ─── **Bold text** rendered bold, `code` highlighted, lists as bullets, etc. v0.8.2 (after Done): [done] turn_id=... ─── **Bold text** as plain asterisks, `code` as backticks, lists as plain dashes ## v0.9.0 plan Restore markdown rendering via LIVE rendering during the stream (not post-Done re-render). Replace `RichLog#transcript` with a `VerticalScroll` container that mounts a fresh `Markdown` widget per turn; Text deltas update the widget; markdown renders as content arrives. No duplication, no snap, full formatting. Operator-confirmed direction (2026-05-25 AskUserQuestion). ## Tests 287/287 GREEN; ruff clean. Two tests updated for the new shape: - test_done_renders_markdown_after_label → renamed test_done_flushes_tail_and_writes_label; asserts NO Markdown, NO Rule (post-Done) in the writes. - test_happy_text_done_renders_markdown → renamed test_happy_text_done_no_double_print; asserts NO Markdown in the spy. Patch bump (v0.8.1 → v0.8.2): bug fix; no public API change.