feat(ios): word-paced fade-in for streaming assistant prose#100884
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6959ac4d49
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| private func proseText(_ prose: ChatMarkdownProse, index: Int) -> SwiftUI.Text { | ||
| guard let reveal = self.reveal, reveal.blockIndex == index else { | ||
| return SwiftUI.Text(prose.attributed) |
There was a problem hiding this comment.
Restore branded-font coverage for prose Text helpers
When OpenClawTypographyTests.iOS app text and control calls keep branded font boundaries runs, it scans shared chat UI sources and only accepts a Text(...) call when a branded font token or .font(self.font) appears within the next 12 lines. This new helper returns SwiftUI.Text here, and the new concatenated SwiftUI.Text calls in revealedText have the same shape, so the typography audit reports these new lines even though blockView applies the font farther away; keep the font application local to the helper or add a narrow audit allowance before this lands.
Useful? React with 👍 / 👎.
|
Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 10:32 AM ET / 14:32 UTC. Summary PR surface: Other +651. Total +651 across 7 files. Reproducibility: yes. for the review blockers: source inspection and the existing typography audit path show the introduced Text offenders, and a delayed 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:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Land the streaming reveal only after repairing the typography audit and mid-word chunk pacing, adding real simulator/device proof for normal and Reduce Motion paths, and getting maintainer UX acceptance. Do we have a high-confidence way to reproduce the issue? Yes for the review blockers: source inspection and the existing typography audit path show the introduced Text offenders, and a delayed Is this the best way to solve the issue? No as submitted: the shared renderer is a plausible owner boundary, but the patch must fix the typography audit, fade delayed mid-word extensions, and add real visual proof before it is the best merge shape. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 94a0d2ec3b79. Label changesLabel justifications:
Evidence reviewedPR surface: Other +651. Total +651 across 7 files. View PR surface stats
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
Review history (1 earlier review cycle)
|
6959ac4 to
0ad535f
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ad535f7bd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let appendedRanges = ranges.filter { | ||
| $0.lowerBound >= oldCharacterCount && !trackedStarts.contains($0.lowerBound) |
There was a problem hiding this comment.
Fade characters appended within an existing word
When a stream chunk extends the current word after its previous fade deadline has expired, the old range is dropped above and this predicate skips the updated word because its lower bound is still before oldCharacterCount (for example, "hel" followed later by "hello world"). The newly appended characters then render fully opaque while later words fade, so arbitrary token/character chunking still produces visible mid-word pops; treat the expanded trailing word as continued/new fading text instead of only accepting ranges that start after the old character count.
Useful? React with 👍 / 👎.
|
Merged via squash.
|
Related: #100699
What Problem This Solves
Streamed assistant prose in the iOS/macOS chat currently appears in raw chunks — text pops in a delta at a time, which reads as jittery compared to modern chat clients.
Why This Change Was Made
Adds a word-paced fade-in for streaming assistant prose in the shared renderer. The pacing core is a pure, deterministic module (no timers, callers pass
now): appended words get staggered 40ms reveals with a 120ms fade, a burst catch-up rule compresses backlogs so the queue clears within 400ms, reveal is strictly monotonic (a shown word never un-shows), and non-append rewrites (e.g., markdown that reformats earlier text when a**closes) reveal instantly and restart pacing. Only the last prose block of the streaming bubble animates; code, tables, and math keep their existing render-plain-until-complete behavior. Markdown is parsed once per delta and cached — per-frame work is opacity restyling of a bounded 24-word tail only, and the drivingTimelineViewstops when nothing is fading. Reduce Motion bypasses the effect entirely. Final transcript rendering is untouched.User Impact
Streaming responses read smoothly word by word instead of popping in chunks; users with Reduce Motion enabled keep the current instant behavior; completed messages render exactly as before.
Evidence
swift test --package-path apps/shared/OpenClawKit— full suite green (453 Swift Testing + 21 XCTest). NewChatStreamingRevealTests(word boundaries incl. Unicode/CJK, staggered deadlines, burst catch-up cap, monotonicity, rewrite reset);ChatStreamReplayTestsextended with consecutive streamed-turn convergence (final transcript text always equals the full streamed text, no state leaks between turns).xcodebuild build-for-testinggreen; streaming-bubble smoke case added toSwiftUIRenderSmokeTests.swiftformat --lintvia the iOS filelist — clean; i18n inventory unchanged (native:i18n:syncidempotent on this diff).