fix(ios): preserve assistant line breaks in chat#98054
Conversation
|
Codex review: needs changes before merge. Reviewed June 30, 2026, 6:48 AM ET / 10:48 UTC. Summary PR surface: Other +140. Total +140 across 3 files. Reproducibility: no. high-confidence current-main live reproduction was run in this read-only review. The issue is source-reproducible with medium confidence because current main preserves assistant newline bytes into ChatMarkdownRenderer, which then feeds cleaned text directly to Swift AttributedString(markdown:) without newline-specific handling, and the linked issue includes iOS screenshots. Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Security Review findings
Review detailsBest possible solution: Preserve prose newlines immediately before Markdown fence boundaries while leaving fence contents unchanged, refresh focused Swift coverage and iOS simulator proof, then land only one of the two open fix candidates. Do we have a high-confidence way to reproduce the issue? No high-confidence current-main live reproduction was run in this read-only review. The issue is source-reproducible with medium confidence because current main preserves assistant newline bytes into ChatMarkdownRenderer, which then feeds cleaned text directly to Swift AttributedString(markdown:) without newline-specific handling, and the linked issue includes iOS screenshots. Is this the best way to solve the issue? No, not as submitted: the renderer-level hard-break transform is the right layer, but the next-fence guard leaves a visible collapsed boundary in the provided simulator proof. The safer fix is to preserve prose newlines before fences while continuing to leave code-block contents unchanged. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 738b2be4b49b. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Other +140. Total +140 across 3 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Thanks @qingminglong for working on this. The issue has been fixed by #98304, merged as commit 47845e1. This PR was the closest sibling implementation: it used the same display-time hard-break approach and included simulator proof. The final landed patch keeps that root-cause direction but adds the remaining edge-case handling for prose near fenced blocks, table detection versus pipe-containing prose, and stricter fence-close behavior, with focused regression tests and live iOS proof. Closing this as superseded by #98304. |
Closes #98028
What Problem This Solves
Fixes an issue where iOS users reading assistant responses would see multi-line replies flattened into one continuous paragraph when the assistant text contained visible single line breaks.
Why This Change Was Made
The shared native chat renderer now converts visible single newlines in cleaned display text into Markdown hard breaks before Swift Markdown parsing, while leaving paragraph breaks, existing hard breaks, escaped line breaks, fenced code blocks, and indented code blocks unchanged. This keeps the fix local to the chat Markdown rendering path without changing assistant text extraction or provider/gateway behavior.
User Impact
Assistant responses in the iOS chat can display intentional line breaks as separate lines, matching the readable structure users expect from multi-line replies.
Evidence
git diff --checkpassed.python .agents\skills\autoreview\scripts\autoreview --mode localfirst reported an indented-code-block mutation risk; fixed in this branch.python .agents\skills\autoreview\scripts\autoreview --mode localsecond reported a longer-fence Markdown mutation risk; fixed in this branch.python .agents\skills\autoreview\scripts\autoreview --mode localfinal run:autoreview clean: no accepted/actionable findings reported.swift test --package-path apps/shared/OpenClawKit --filter ChatMarkdownPreprocessorTestsattempted locally but Windows does not haveswiftinstalled (swift : The term 'swift' is not recognized...).swift test --package-path apps/shared/OpenClawKit --filter ChatEventTextTestsattempted locally but Windows does not haveswiftinstalled (swift : The term 'swift' is not recognized...).ios-chat-line-break-proof-pr-98054(artifact id7977787938, 211269 bytes) from workflow run28437348097.iPhone 17-ios-chat-line-break-proof.png.92531758b3081fd314e4f76a0f74523af7f2606f.Line one should stay on its own row,Line two should stay on its own row, andLine three should stay on its own rowon separate visible rows. The same screenshot also shows the fenced Swift code contents (let first = "alpha",let second = "beta",print(first + second)) and indented code lines A/B remaining multi-line instead of being collapsed into a single line.