fix(ios): avoid transient duplicate final replies - #98117
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 30, 2026, 11:32 PM ET / 03:32 UTC. Summary PR surface: Other +404. Total +404 across 2 files. Reproducibility: yes. Source inspection shows current main can append a live Review metrics: none identified. 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:
Next step before merge
Security Review detailsBest possible solution: Land this shared OpenClawKit reconciliation after maintainer review accepts the message-delivery tradeoff and the current green checks remain valid. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main can append a live Is this the best way to solve the issue? Yes. The duplicate is created where the live chat and canonical session streams converge in AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against fa3c9de45965. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Other +404. Total +404 across 2 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
|
6464227 to
71be307
Compare
|
I pushed a production-grade rewrite of the iOS final-message reconciliation in Fix shape:
Evidence:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
* Fix iOS final reply dedupe * fix(ios): scope final message reconciliation * docs(ios): explain final message reconciliation key --------- Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
* Fix iOS final reply dedupe * fix(ios): scope final message reconciliation * docs(ios): explain final message reconciliation key --------- Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
* Fix iOS final reply dedupe * fix(ios): scope final message reconciliation * docs(ios): explain final message reconciliation key --------- Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com> (cherry picked from commit 5a5913a)
* Fix iOS final reply dedupe * fix(ios): scope final message reconciliation * docs(ios): explain final message reconciliation key --------- Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com> (cherry picked from commit 5a5913a)
Fixes #98116
What Problem This Solves
Fixes an issue where users viewing an iOS Chat conversation could briefly see the same assistant final reply twice when the live final event and canonical transcript event both arrived for the same turn. The later history refresh eventually reconciled the transcript back to one row, but the intermediate UI looked like OpenClaw duplicated and then deleted a final answer.
Why This Change Was Made
The shared chat view model now treats assistant rows inserted from live
chat.finalevents as provisional for the current turn. A matching canonicalsession.messageadopts that provisional row instead of appending a duplicate, and a later live final is skipped when the canonical assistant row is already visible after the latest user message. The match is intentionally scoped to messages after the latest user turn so an older provisionalOK/Doneresponse cannot consume a later identical reply.This does not globally dedupe assistant messages by text, and it does not change the Gateway, Tailscale/Funnel, or pairing behavior.
User Impact
Users on iOS remote-domain or LAN Chat surfaces should see one stable final assistant row per turn while live final, session transcript, and history refresh events reconcile. Repeated identical answers on separate turns remain visible as separate replies.
Evidence
AI-assisted: yes, Codex.
session message adopts provisional final event replycovers livechat.finalfirst, canonicalsession.messagesecond, including a live content id that the canonical transcript does not carry.final event does not duplicate canonical assistant session messagecovers canonicalsession.messagefirst, later matching livechat.finalsecond.later identical session reply does not adopt prior turn provisional finalcovers the important repeated short-answer case so a stale provisionalOKfrom a previous user turn cannot steal the next turn's canonicalOKreply.git diff --check HEAD~1 HEADpassed.swift --versionis not recognized), so the Swift tests could not be executed locally here. They are added for the macOS/iOS CI lane to run.OKregression test. A second autoreview rerun timed out after 6 minutes without a final verdict, so this PR is not claimed as autoreview-clean.