Skip to content

fix: iOS chat streaming stays visually stable as replies arrive#50483

Merged
steipete merged 2 commits into
openclaw:mainfrom
eulicesl:upstream/fix-ios-streaming-layout-flicker
Jul 9, 2026
Merged

fix: iOS chat streaming stays visually stable as replies arrive#50483
steipete merged 2 commits into
openclaw:mainfrom
eulicesl:upstream/fix-ios-streaming-layout-flicker

Conversation

@eulicesl

@eulicesl eulicesl commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Related: #40985

What Problem This Solves

Fixes an issue where iOS and macOS chat could rebuild unchanged completed assistant segments during unrelated view updates and show both the typing indicator and visible streamed text at the same time. The result was avoidable flicker and a contradictory “Writing” state as replies arrived.

Why This Change Was Made

Assistant text parsing now gives semantic segments deterministic positional identities, so SwiftUI preserves unchanged markdown views. Chat rendering also computes visible streaming content once and uses that same fact for the stream bubble, transient-content state, empty state, and typing-indicator suppression.

The earlier branch’s session routing, bootstrap guards, and scroll throttle were intentionally removed during the current-main rewrite: those areas have since been replaced by the current run-state and reader-managed scrolling implementations.

User Impact

Chat replies transition from “Writing” to visible streamed text without rendering both states, and completed assistant content remains visually stable during unrelated updates.

Evidence

  • Regression coverage verifies that repeated parses return the same unique segment identities.
  • Fresh Codex autoreview reported no accepted or actionable findings.
  • Exact-head macOS/Swift and iOS build proof will be recorded before merge.

Thanks @eulicesl for identifying the streaming stability problems and iterating on the original implementation. The rewritten commit preserves contributor credit with a Co-authored-by trailer.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1f9853bc9

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
@greptile-apps

greptile-apps Bot commented Mar 19, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR addresses three root causes behind iOS chat instability: session mis-scoping, stream acceptance / initial-load churn, and repeated layout re-parses. The changes are well-motivated and the majority of the implementation is sound — the stable AssistantTextSegment IDs, the shouldAcceptAgentEvent / matchesCurrentSessionKey routing logic, the load() idempotency guard, the typing-indicator visibility fix, and the streaming scroll debounce all look correct and are backed by good test coverage.

Key findings:

  • Logic issue — errored run can permanently append partial content without history reconciliation: In handleChatEvent, the "error" state shares the same case arm as "final" and "aborted". When a run errors mid-stream, appendFinalAssistantMessage falls through to streamedAssistantMessage(), which synthesizes a message from the partial streamingAssistantText. Because appendFinalAssistantMessage returns true, refreshHistoryAfterRun() is never called. The partial, incomplete response is now permanently in messages with no server reconciliation — on next reload it would silently vanish, creating a visible inconsistency. The "error" branch should be handled separately and should always trigger a history refresh.
  • Style note — hardcoded session-key alias: matchesCurrentSessionKey only handles the "agent:main:main""main" alias pair. Other configurations following the same agent:<name>:<name><name> convention would silently drop events.

Confidence Score: 3/5

  • Mostly safe to merge, but the error-state partial-message bug can cause silent client/server state drift on run failures with partial streaming content.
  • The bulk of the PR is well-implemented and tested. The one logic issue — errored runs bypassing refreshHistoryAfterRun() when partial streaming content exists — is a behavioural regression that creates data inconsistency, though it only fires on the specific path of (run errors) + (partial visible streaming text buffered). All other changes are safe and the new tests cover the happy paths well.
  • apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift — specifically the "error" state arm of handleChatEvent (around line 874) and the matchesCurrentSessionKey alias logic.

Comments Outside Diff (2)

  1. apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift, line 874-889 (link)

    P1 Errored run skips history refresh when partial streaming content exists

    For the "error" state, appendFinalAssistantMessage falls through to streamedAssistantMessage() when chat.message is nil (typical for errored runs). If any partial streaming text was buffered, streamedAssistantMessage() creates a synthesized message and returns true. This causes appendFinalAssistantMessage to return true, which suppresses refreshHistoryAfterRun().

    The result: partial, incomplete content from a failed run is permanently appended to self.messages as if it were a finalized assistant message, and the client never reconciles with the server. On next reload the partial message would disappear (since the server history for an errored run won't include it), creating a visible inconsistency.

    The "final" and "aborted" cases are intentional here — those runs legitimately complete. "error" is different: the server hasn't produced a final message, so skipping the history reconciliation is incorrect.

    Consider separating the error branch so it always triggers a history refresh, even when partial content exists:

    case "final", "aborted":
        let appendedFinalMessage = self.appendFinalAssistantMessage(from: chat)
        self.pendingToolCallsById = [:]
        self.streamingAssistantText = nil
        if !appendedFinalMessage {
            Task { await self.refreshHistoryAfterRun() }
        }
    case "error":
        self.errorText = chat.errorMessage ?? "Chat failed"
        if let runId = chat.runId {
            self.clearPendingRun(runId)
        } else if self.pendingRuns.count <= 1 {
            self.clearPendingRuns(reason: nil)
        }
        self.pendingToolCallsById = [:]
        self.streamingAssistantText = nil
        Task { await self.refreshHistoryAfterRun() }
    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift
    Line: 874-889
    
    Comment:
    **Errored run skips history refresh when partial streaming content exists**
    
    For the `"error"` state, `appendFinalAssistantMessage` falls through to `streamedAssistantMessage()` when `chat.message` is nil (typical for errored runs). If any partial streaming text was buffered, `streamedAssistantMessage()` creates a synthesized message and returns `true`. This causes `appendFinalAssistantMessage` to return `true`, which suppresses `refreshHistoryAfterRun()`.
    
    The result: partial, incomplete content from a failed run is permanently appended to `self.messages` as if it were a finalized assistant message, and the client never reconciles with the server. On next reload the partial message would disappear (since the server history for an errored run won't include it), creating a visible inconsistency.
    
    The `"final"` and `"aborted"` cases are intentional here — those runs legitimately complete. `"error"` is different: the server hasn't produced a final message, so skipping the history reconciliation is incorrect.
    
    Consider separating the error branch so it always triggers a history refresh, even when partial content exists:
    ```swift
    case "final", "aborted":
        let appendedFinalMessage = self.appendFinalAssistantMessage(from: chat)
        self.pendingToolCallsById = [:]
        self.streamingAssistantText = nil
        if !appendedFinalMessage {
            Task { await self.refreshHistoryAfterRun() }
        }
    case "error":
        self.errorText = chat.errorMessage ?? "Chat failed"
        if let runId = chat.runId {
            self.clearPendingRun(runId)
        } else if self.pendingRuns.count <= 1 {
            self.clearPendingRuns(reason: nil)
        }
        self.pendingToolCallsById = [:]
        self.streamingAssistantText = nil
        Task { await self.refreshHistoryAfterRun() }
    ```
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift, line 895-908 (link)

    P2 Hardcoded alias pair may not generalize to other session configurations

    matchesCurrentSessionKey only handles one specific canonical/alias pair: "agent:main:main""main". Any other gateway session key following a similar convention (e.g., "agent:work:work""work", or "agent:staging:staging""staging") would fail the match and silently drop events.

    If the alias pattern is always agent:<name>:<name><name>, a general rule would be more resilient:

    // Generalize: "agent:<name>:<name>" is the canonical form of alias "<name>"
    let parts = incomingNormalized.split(separator: ":", maxSplits: 2)
    if parts.count == 3 && parts[0] == "agent" && parts[1] == parts[2] && parts[2] == currentNormalized {
        return true
    }
    let currentParts = currentNormalized.split(separator: ":", maxSplits: 2)
    if currentParts.count == 3 && currentParts[0] == "agent" && currentParts[1] == currentParts[2] && currentParts[2] == incomingNormalized {
        return true
    }

    If "main" truly is the only valid alias in production today, a comment to that effect would help future maintainers understand the constraint.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift
    Line: 895-908
    
    Comment:
    **Hardcoded alias pair may not generalize to other session configurations**
    
    `matchesCurrentSessionKey` only handles one specific canonical/alias pair: `"agent:main:main"``"main"`. Any other gateway session key following a similar convention (e.g., `"agent:work:work"``"work"`, or `"agent:staging:staging"``"staging"`) would fail the match and silently drop events.
    
    If the alias pattern is always `agent:<name>:<name>``<name>`, a general rule would be more resilient:
    ```swift
    // Generalize: "agent:<name>:<name>" is the canonical form of alias "<name>"
    let parts = incomingNormalized.split(separator: ":", maxSplits: 2)
    if parts.count == 3 && parts[0] == "agent" && parts[1] == parts[2] && parts[2] == currentNormalized {
        return true
    }
    let currentParts = currentNormalized.split(separator: ":", maxSplits: 2)
    if currentParts.count == 3 && currentParts[0] == "agent" && currentParts[1] == currentParts[2] && currentParts[2] == incomingNormalized {
        return true
    }
    ```
    If `"main"` truly is the only valid alias in production today, a comment to that effect would help future maintainers understand the constraint.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift
Line: 874-889

Comment:
**Errored run skips history refresh when partial streaming content exists**

For the `"error"` state, `appendFinalAssistantMessage` falls through to `streamedAssistantMessage()` when `chat.message` is nil (typical for errored runs). If any partial streaming text was buffered, `streamedAssistantMessage()` creates a synthesized message and returns `true`. This causes `appendFinalAssistantMessage` to return `true`, which suppresses `refreshHistoryAfterRun()`.

The result: partial, incomplete content from a failed run is permanently appended to `self.messages` as if it were a finalized assistant message, and the client never reconciles with the server. On next reload the partial message would disappear (since the server history for an errored run won't include it), creating a visible inconsistency.

The `"final"` and `"aborted"` cases are intentional here — those runs legitimately complete. `"error"` is different: the server hasn't produced a final message, so skipping the history reconciliation is incorrect.

Consider separating the error branch so it always triggers a history refresh, even when partial content exists:
```swift
case "final", "aborted":
    let appendedFinalMessage = self.appendFinalAssistantMessage(from: chat)
    self.pendingToolCallsById = [:]
    self.streamingAssistantText = nil
    if !appendedFinalMessage {
        Task { await self.refreshHistoryAfterRun() }
    }
case "error":
    self.errorText = chat.errorMessage ?? "Chat failed"
    if let runId = chat.runId {
        self.clearPendingRun(runId)
    } else if self.pendingRuns.count <= 1 {
        self.clearPendingRuns(reason: nil)
    }
    self.pendingToolCallsById = [:]
    self.streamingAssistantText = nil
    Task { await self.refreshHistoryAfterRun() }
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift
Line: 895-908

Comment:
**Hardcoded alias pair may not generalize to other session configurations**

`matchesCurrentSessionKey` only handles one specific canonical/alias pair: `"agent:main:main"``"main"`. Any other gateway session key following a similar convention (e.g., `"agent:work:work"``"work"`, or `"agent:staging:staging"``"staging"`) would fail the match and silently drop events.

If the alias pattern is always `agent:<name>:<name>``<name>`, a general rule would be more resilient:
```swift
// Generalize: "agent:<name>:<name>" is the canonical form of alias "<name>"
let parts = incomingNormalized.split(separator: ":", maxSplits: 2)
if parts.count == 3 && parts[0] == "agent" && parts[1] == parts[2] && parts[2] == currentNormalized {
    return true
}
let currentParts = currentNormalized.split(separator: ":", maxSplits: 2)
if currentParts.count == 3 && currentParts[0] == "agent" && currentParts[1] == currentParts[2] && currentParts[2] == incomingNormalized {
    return true
}
```
If `"main"` truly is the only valid alias in production today, a comment to that effect would help future maintainers understand the constraint.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "fix(ios): stabilize ..."

Re-review progress:

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a08fd3040

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 21aad88f23

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
@eulicesl
eulicesl force-pushed the upstream/fix-ios-streaming-layout-flicker branch from 21aad88 to 5df7c10 Compare March 19, 2026 18:19

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5df7c10821

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
@eulicesl
eulicesl force-pushed the upstream/fix-ios-streaming-layout-flicker branch from 5df7c10 to aa25cd5 Compare March 19, 2026 20:52
eulicesl added a commit to eulicesl/openclaw that referenced this pull request Mar 19, 2026
P1 review thread fixes for openclaw#50483:

1. History sync after local finals: appendFinalAssistantMessage now always calls refreshHistoryAfterRun() instead of only when the append failed. This ensures tool results from local runs are persisted to canonical history.

2. Multi-client reconciliation: When external client finals arrive while this client has a pending run, immediately append the message AND schedule history refresh instead of deferring refresh until pendingRuns.isEmpty. This prevents cross-client history gaps.

Added test cases:
- appendsFinalAssistantMessageImmediatelyAndRefreshesHistory: validates history sync after local finals
- externalFinalMessageRefreshesHistoryEvenDuringLocalPendingRun: validates multi-client reconciliation

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aa25cd5e5c

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
@eulicesl
eulicesl force-pushed the upstream/fix-ios-streaming-layout-flicker branch from aa25cd5 to 830fb0c Compare March 20, 2026 13:03
@eulicesl
eulicesl force-pushed the upstream/fix-ios-streaming-layout-flicker branch from 830fb0c to ad77e13 Compare March 20, 2026 15:01
@eulicesl
eulicesl force-pushed the upstream/fix-ios-streaming-layout-flicker branch from ad77e13 to 3d5e074 Compare March 21, 2026 21:10
@eulicesl
eulicesl force-pushed the upstream/fix-ios-streaming-layout-flicker branch from 0c32438 to 01acd67 Compare March 23, 2026 02:52

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6f520a890b

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
@eulicesl
eulicesl force-pushed the upstream/fix-ios-streaming-layout-flicker branch from 6f520a8 to 8bfa960 Compare April 17, 2026 12:29
eulicesl added a commit to eulicesl/openclaw that referenced this pull request Apr 17, 2026
P1 review thread fixes for openclaw#50483:

1. History sync after local finals: appendFinalAssistantMessage now always calls refreshHistoryAfterRun() instead of only when the append failed. This ensures tool results from local runs are persisted to canonical history.

2. Multi-client reconciliation: When external client finals arrive while this client has a pending run, immediately append the message AND schedule history refresh instead of deferring refresh until pendingRuns.isEmpty. This prevents cross-client history gaps.

Added test cases:
- appendsFinalAssistantMessageImmediatelyAndRefreshesHistory: validates history sync after local finals
- externalFinalMessageRefreshesHistoryEvenDuringLocalPendingRun: validates multi-client reconciliation
eulicesl added a commit to eulicesl/openclaw that referenced this pull request Apr 17, 2026
Address copilot-pull-request-reviewer feedback on openclaw#50483:
- Track optimistically-appended assistant messages by UUID in
  pendingOptimisticMessageIds so they are not dropped during the
  race window between append and history refresh.
- reconcileRunRefreshMessages now accepts pendingOptimisticIds and
  preserves any previous messages matching those IDs that are absent
  from incoming history.
- refreshHistoryAfterRun clears pendingOptimisticIds for messages
  now confirmed by the incoming history payload.
- bootstrap also passes pendingOptimisticIds to reconcileRunRefreshMessages
  so bootstrap history loads are consistent with the same logic.
- appendFinalAssistantMessage tracks new message IDs on append.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8bfa960895

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1768568561

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbd9bbd46c

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89dab2506c

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 151405b3ff

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff1ecc4249

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelTests.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f5a032f220

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatViewModelTests.swift Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@clawsweeper

clawsweeper Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 9, 2026, 6:58 AM ET / 10:58 UTC.

Summary
The PR changes Swift chat parsing/rendering so assistant text segments get deterministic IDs and the typing indicator is hidden once visible streamed assistant text exists, plus a parser regression test and native i18n line metadata.

PR surface: Other +10. Total +10 across 4 files.

Reproducibility: Source-reproducible: current main gives assistant text segments fresh UUIDs on each parse and renders the typing indicator solely from blocking run activity, so the reported visual instability path is clear from source. I did not run a live iOS streaming session.

Review metrics: none identified.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add a short simulator or device recording, terminal/live output, or redacted logs from a real streaming reply showing that visible streamed text no longer appears with the Writing indicator and completed content stays stable.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR has exact-head CI/Testbox build and parser test proof, but no after-fix real chat streaming recording, logs, or transcript showing the visual behavior; add proof with private details redacted, and updating the PR body should trigger a fresh ClawSweeper review or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The visual streaming behavior has CI, build, and parser-test proof, but no simulator/device recording or live streaming transcript showing the flicker/duplicate Writing state is fixed.

Maintainer options:

  1. Decide the mitigation before merge
    Land the narrowed Chat UI fix after adding a short simulator or device streaming proof that shows visible streamed text replacing the Writing state without flicker.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] No automated code repair is identified; the PR needs real streaming proof or an explicit maintainer proof override before merge.

Security
Cleared: The diff only changes Swift chat UI/parser logic, one Swift test, and generated native i18n line metadata; I found no security or supply-chain concern.

Review details

Best possible solution:

Land the narrowed Chat UI fix after adding a short simulator or device streaming proof that shows visible streamed text replacing the Writing state without flicker.

Do we have a high-confidence way to reproduce the issue?

Source-reproducible: current main gives assistant text segments fresh UUIDs on each parse and renders the typing indicator solely from blocking run activity, so the reported visual instability path is clear from source. I did not run a live iOS streaming session.

Is this the best way to solve the issue?

Yes, this is the best narrow fix I found: it changes parser identity and duplicate-state rendering at the SwiftUI surface where the churn originates, while leaving current-main run-state and scroll ownership untouched.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against c067802cda3a.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR has exact-head CI/Testbox build and parser test proof, but no after-fix real chat streaming recording, logs, or transcript showing the visual behavior; add proof with private details redacted, and updating the PR body should trigger a fresh ClawSweeper review or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This is a normal-priority iOS/macOS chat UI stability bugfix with limited blast radius and no evidence of data loss, security impact, or core runtime outage.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR has exact-head CI/Testbox build and parser test proof, but no after-fix real chat streaming recording, logs, or transcript showing the visual behavior; add proof with private details redacted, and updating the PR body should trigger a fresh ClawSweeper review or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Other +10. Total +10 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 4 34 24 +10
Total 4 34 24 +10

What I checked:

Likely related people:

  • mahmoud: Current-main blame attributes the relevant OpenClawChatUI parser and rendering files in this checkout to commit 32510a3. (role: recent area contributor; confidence: medium; commits: 32510a3225b8; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/AssistantTextParser.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift)
  • Peter Steinberger: History shows prior OpenClawKit Chat UI work in d15b6af and the current PR head was rewritten by this reviewer with contributor credit preserved. (role: feature-history contributor and current reviewer; confidence: high; commits: d15b6af77b49, e01f23abd50c, 72e1ab863487; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/AssistantTextParser.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift)
  • Mariano: Git history for ChatViewModel shows multiple nearby iOS chat streaming and session-key fixes in February 2026, which are adjacent to the older session-routing parts intentionally removed from this PR. (role: adjacent stream/session-state contributor; confidence: medium; commits: 42d11a3ec5f4, fe3f0759b5c4, 6effcdb551a8; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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 keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (7 earlier review cycles)
  • reviewed 2026-07-04T01:04:06.272Z sha 2896ccf :: needs real behavior proof before merge. :: [P1] Pass agentId through agent event routing | [P1] Update the agent event schema with routing fields | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T05:01:11.280Z sha 2896ccf :: needs real behavior proof before merge. :: [P1] Carry agentId through session-key agent routing | [P1] Rebase away the stale raw-agent session flow | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T07:35:57.648Z sha 2896ccf :: needs real behavior proof before merge. :: [P1] Carry agentId through session-key agent routing | [P1] Rebase away the stale raw-agent session flow | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T15:28:02.977Z sha 2896ccf :: needs real behavior proof before merge. :: [P1] Carry agentId through session-key agent routing | [P1] Rebase raw-agent routing onto current main | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T17:30:22.564Z sha 2896ccf :: needs real behavior proof before merge. :: [P1] Carry agentId through agent-event routing | [P1] Rebase the session-stream filter onto current main | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T17:53:20.743Z sha 2896ccf :: needs real behavior proof before merge. :: [P1] Carry agentId through agent stream matching | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-09T06:17:01.498Z sha 2896ccf :: needs real behavior proof before merge. :: [P1] Carry agentId through agent stream matching | [P3] Remove the release-owned changelog entry

@eulicesl

eulicesl commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

Rebuilt this branch on top of current main and force-pushed a clean refresh.

What changed:

  • kept the chat/session-flow fixes
  • dropped the unrelated Windows installer / CI retrigger commits
  • added the missing changelog entry

Local verification:

  • swift test in apps/shared/OpenClawKit

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29f6bd56d9

ℹ️ 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".

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift Outdated
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat.

Where did the egg go?
  • The egg game starts only after the PR passes the real-behavior proof check.
  • Before that, no creature or rarity is rolled. The treat waits for real proof.
  • This is still just collectible flavor: proof affects review readiness, not creature quality.

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

2 similar comments
@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Land-ready review complete at 72e1ab863487ce5badba6e26d0d81c1a4db719ed.

The original stale branch was rewritten against current main. Retained: stable assistant-segment identity and removal of the duplicate typing state once streamed text is visible. Removed as obsolete: old session routing, bootstrap-state, event acceptance, and scroll-throttle changes now owned by current main implementations.

Proof:

  • Exact-head CI run 29012834098: macos-swift passed, including release build, Swift lint, and Swift tests.
  • Exact-head CI run 29012834098: ios-build passed.
  • Exact-head CI run 29012834098: native-i18n passed.
  • Blacksmith Testbox tbx_01kx35rs5ramy75wvs0jn0v4kt: focused native:i18n:check passed after synchronizing shifted source-line metadata.
  • Fresh Codex autoreview: no accepted or actionable findings.

Contributor credit remains on the PR and in the implementation commit’s Co-authored-by trailer. No physical-device streaming run was performed.

@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants