Skip to content

fix(ios): picker adaptive onChange loop + OSLog string concatenation#40878

Closed
eulicesl wants to merge 6 commits into
openclaw:mainfrom
eulicesl:upstream/fix-picker-oslog
Closed

fix(ios): picker adaptive onChange loop + OSLog string concatenation#40878
eulicesl wants to merge 6 commits into
openclaw:mainfrom
eulicesl:upstream/fix-picker-oslog

Conversation

@eulicesl

@eulicesl eulicesl commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: the iOS chat UI had two SwiftUI/runtime stability issues in the current patchset: the adaptive thinking picker could loop when selection state did not match tags, and streaming scroll updates could fire during the same frame/layout pass.
  • Why it matters: users can see selection churn, repeated per-frame update warnings, and unstable chat-scroll behavior during rapid streaming.
  • What changed: aligned the picker with the adaptive value and deferred the streaming scroll update past the current layout pass.
  • What did NOT change (scope boundary): no gateway protocol changes, no model/runtime changes outside the shared chat UI, and no non-iOS platform behavior changes.
  • AI-assisted: yes (AI-assisted implementation, contributor-reviewed).
  • Testing level: locally built and manually verified on iOS.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: SwiftUI selection/layout behavior was being driven with state that did not fully align to the rendered picker tags and with streaming scroll updates occurring during the active frame/layout cycle.
  • Missing detection / guardrail: there was no focused UI/runtime validation covering the adaptive picker state plus rapid streaming-update scroll behavior.
  • Prior context (git blame, prior PR, issue, or refactor if known): prior body text referenced additional scope, but the current rebased diff is limited to the shared chat UI fixes reflected in the changed files.
  • Why this regressed now: newer adaptive/streaming behavior exposed stricter SwiftUI state/layout timing requirements.
  • If unknown, what was ruled out: no evidence of gateway-side or transport-side faults; this is local UI/runtime behavior.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: manual iOS/simulator verification around ChatComposer and ChatView streaming behavior.
  • Scenario the test should lock in: adaptive picker selection should not loop, and streaming scroll updates should not trigger same-frame multi-update warnings/churn.
  • Why this is the smallest reliable guardrail: this behavior is SwiftUI runtime/layout-sensitive and is most directly verified in an app run rather than pure logic tests.
  • Existing test that already covers this (if any): none sufficient for the UI/runtime symptom.
  • If no new test is added, why not: the bug is tied to SwiftUI runtime behavior rather than isolated pure logic.

User-visible / Behavior Changes

  • Adaptive thinking selection remains stable instead of looping/churning.
  • Chat streaming scroll behavior is more stable during rapid updates.

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? (Yes/No): No
  • Secrets/tokens handling changed? (Yes/No): No
  • New/changed network calls? (Yes/No): No
  • Command/tool execution surface changed? (Yes/No): No
  • Data access scope changed? (Yes/No): No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: iOS local dev/device environment
  • Runtime/container: local app build
  • Model/provider: N/A
  • Integration/channel (if any): iOS chat UI
  • Relevant config (redacted): local iOS build/signing config

Steps

  1. Build and run the iOS app from this branch.
  2. Exercise the adaptive thinking picker.
  3. Stream a reply and watch scroll/update behavior.

Expected

  • Picker selection remains stable.
  • Streaming updates do not cause repeated same-frame churn/warnings.

Actual

  • Matched expected during local verification.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios:
    • local iOS build/install succeeds
    • adaptive picker no longer loops
    • streaming scroll behavior is stable during active updates
  • Edge cases checked:
    • adaptive selection path
    • rapid token-streaming update path
  • What you did not verify:
    • full repository CI matrix
    • non-iOS clients

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No): Yes
  • Config/env changes? (Yes/No): No
  • Migration needed? (Yes/No): No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: SwiftUI timing issues can be device/runtime-specific.
    • Mitigation: the patch keeps scope narrow to the observed selection/update paths and was manually verified in the app.

Copilot AI review requested due to automatic review settings March 9, 2026 10:38

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

Copy link
Copy Markdown

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: aca0cd114c

ℹ️ 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/ChatView.swift
@greptile-apps

greptile-apps Bot commented Mar 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR delivers two independent bug fixes for the iOS app: adding the missing "adaptive" tag to the thinkingPicker in ChatComposer.swift (which prevented a selection-loop when the backend returned "adaptive" as the thinking level), consolidating multi-part OSLog string literals in NodeAppModel.swift (fixing a compile error under Xcode 17C / iOS 26 SDK), and deferring the streaming-scroll update in ChatView.swift via Task { @MainActor in } to suppress "onChange tried to update multiple times per frame" warnings.

  • ChatComposer.swiftText("Adaptive").tag("adaptive") correctly fills the gap in the picker; without a matching tag SwiftUI may fire onChange repeatedly, which aligns with the loop described in the PR title.
  • NodeAppModel.swift — The three OSLog sites that concatenated OSLogMessage values with + are now single-line interpolations. The fix is correct and the logged content is unchanged.
  • ChatView.swift — The Task { @MainActor in } deferral is a valid pattern for this situation, but the isPinnedToBottom guard is checked before creating the task rather than inside it, leaving a small window where the condition could change before the deferred mutation runs (see inline comment).
  • The PR description references MessageComposerView.swift and GatewaySettingsStore.swift as changed files, but neither appears in the actual diff — the description appears to be outdated relative to the final commit.

Confidence Score: 4/5

  • This PR is safe to merge with one minor style improvement recommended in ChatView.swift.
  • All three changes are well-scoped and target genuine bugs. The OSLog fix and the "Adaptive" tag addition are straightforwardly correct. The ChatView.swift Task deferral resolves a real SwiftUI warning but has a minor edge case where the isPinnedToBottom guard is not re-checked inside the deferred task body, meaning a stale guard value could cause an unintended scroll-to-bottom if the user scrolls away in the brief window between the onChange closure and the task execution.
  • apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift — the guard condition inside the streaming-scroll Task should be re-evaluated inside the Task body.

Last reviewed commit: aca0cd1

Comment thread apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift

Copilot AI 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.

Pull request overview

This PR contains two independent bug fixes for the iOS app targeting iOS 26 SDK compatibility and a SwiftUI rendering issue.

Changes:

  • Added the missing "adaptive" tag to the thinkingPicker in ChatComposer.swift, preventing a SwiftUI Picker onChange loop when the backend returns thinkingLevel = "adaptive" (an unknown tag caused SwiftUI to revert to a fallback selection and loop)
  • Wrapped the streamingAssistantText onChange scroll update in Task { @MainActor in } in ChatView.swift to defer it past the current layout pass and suppress "onChange tried to update multiple times per frame" warnings during rapid token streaming
  • Collapsed multi-line OSLog string concatenation in NodeAppModel.swift into single-line interpolations, fixing compile errors with Xcode 17C (iOS 26 SDK) where OSLogMessage does not support + between operands

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift Adds the missing "adaptive" picker tag to prevent the selection-fallback loop
apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift Wraps the streaming scroll update in a deferred Task to avoid same-frame multi-update warnings
apps/ios/Sources/Model/NodeAppModel.swift Merges three multi-line +-concatenated OSLog strings into single-line string interpolations

The PR description lists Sources/Chat/MessageComposerView.swift and Sources/Gateway/GatewaySettingsStore.swift as changed files, but neither has a corresponding diff. MessageComposerView.swift does not exist anywhere in the codebase. GatewaySettingsStore.swift does exist and uses Logger.info with a single-argument form (no + concatenation), so no fix was needed there — but the PR description incorrectly states it was changed. The description appears to have been generated with inaccurate file references (noted as AI-assisted).


You can also share your feedback on Copilot code review. Take the survey.

Comment thread apps/ios/Sources/Model/NodeAppModel.swift Outdated
@eulicesl

eulicesl commented Mar 9, 2026

Copy link
Copy Markdown
Contributor Author

Screenshots — iPhone 17 Pro Max (iOS 26.3)

Adaptive Picker

Thinking Level Picker Model Picker
thinking model

Picker renders correctly without onChange loop. Selection persists across sheet dismissal.

Tested on-device with dev build.

@eulicesl eulicesl force-pushed the upstream/fix-picker-oslog branch from aca0cd1 to f80073a Compare March 16, 2026 17:32
@openclaw-barnacle openclaw-barnacle Bot removed the app: ios App: ios label Mar 16, 2026

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

Copy link
Copy Markdown

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: f80073a1fb

ℹ️ 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/ChatView.swift
@eulicesl eulicesl force-pushed the upstream/fix-picker-oslog branch 2 times, most recently from 9d31c3a to 96dae44 Compare March 17, 2026 18:03

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

Copy link
Copy Markdown

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: 96dae44bbd

ℹ️ 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/ChatView.swift
@eulicesl eulicesl force-pushed the upstream/fix-picker-oslog branch from 96dae44 to be9e16c Compare March 19, 2026 14:42
@eulicesl eulicesl force-pushed the upstream/fix-picker-oslog branch 12 times, most recently from fb63d73 to 47f5a83 Compare March 23, 2026 16:01
@clawsweeper

clawsweeper Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as superseded: current main already replaced the picker path with metadata-driven thinking options through the merged native metadata fix, while the remaining streaming-layout work is covered by the broader open iOS chat streaming PR. Keeping this conflicting stale branch open would duplicate the canonical path and risk regressing the current picker contract.

Canonical path: Close this stale branch, keep the merged metadata-driven picker implementation, and handle any remaining streaming layout/session work on #50483.

So I’m closing this here and keeping the remaining discussion on #50483.

Review details

Best possible solution:

Close this stale branch, keep the merged metadata-driven picker implementation, and handle any remaining streaming layout/session work on #50483.

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

No high-confidence live current-main reproduction was established in this read-only review. Source and PR history explain the old static-picker conflict, but current main has the metadata fix and the streaming warning still lacks runtime diagnostic proof.

Is this the best way to solve the issue?

No, this branch is no longer the best way to solve the issue. The maintainable path is the merged metadata picker fix plus the broader streaming-layout branch, not keeping this conflicting duplicate PR open.

Security review:

Security review cleared: No concrete security or supply-chain concern found; the live diff is limited to SwiftUI chat UI files and does not touch dependencies, workflows, secrets, permissions, networking, or code execution.

What I checked:

Likely related people:

  • BunsDev: Authored and merged the native thinking metadata follow-up that removed the fixed picker list, added metadata-driven options, and explicitly referenced this PR's review feedback. (role: recent picker metadata contributor; confidence: high; commits: 89304de93653, 9ffe290a170b; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSessions.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift)
  • ImLukeF: Merged the model selector and thinking persistence work that introduced the earlier native thinking picker and session-aware picker state this PR originally modified. (role: feature-history contributor; confidence: medium; commits: 061b8258bc35; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSessions.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel.swift)
  • mbelinky: Recent GitHub path history shows iOS chat UI stabilization work touching ChatView.swift and the shared chat UI surface affected by the streaming-scroll part of this branch. (role: adjacent chat UI contributor; confidence: medium; commits: 9476dda9f617; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift)
  • steipete: Local blame attributes the current checked-out snapshot around the picker and streaming-scroll handlers to a recent broad main commit, useful for routing current-main state but weak for original authorship. (role: recent current-main contributor; confidence: low; commits: dd07fb400fc5, b294f7c46763; files: apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift, apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift)

Codex review notes: model gpt-5.5, reasoning high; reviewed against d7a078f1962b.

@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Apr 26, 2026
@eulicesl eulicesl force-pushed the upstream/fix-picker-oslog branch 2 times, most recently from fe157e5 to 1327fbf Compare April 27, 2026 12:45
Two independent fixes:

1. **Picker adaptive tag onChange loop**: prevent infinite loop when
   picker selection triggers onChange which re-triggers state update

2. **OSLog concatenation**: Swift doesn't support '+' between
   OSLogMessage operands. Combined 3 multi-line log strings into
   single-line interpolations in NodeAppModel pending action logging.
Follow up on PR review by re-checking the pin-to-bottom state inside the deferred streaming scroll task. This keeps queued tasks from yanking the list back down after the user scrolls away during token streaming.\n\nAlso rebase the branch onto current origin/main and validate with a simulator build.
@eulicesl eulicesl force-pushed the upstream/fix-picker-oslog branch from 1327fbf to 1220fc7 Compare April 27, 2026 14:30
@chatgpt-codex-connector

Copy link
Copy Markdown

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

@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 5, 2026
BunsDev added a commit that referenced this pull request May 7, 2026
Decode gateway-provided thinking metadata for native iOS/macOS chat picker options, preserving extended and legacy thinking levels without leaking default-model options across sessions.\n\nVerification:\n- swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests --no-parallel\n- swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests --no-parallel\n- pnpm lint:swift\n- pnpm check:changed\n\nFollow-up maintainer fix for #40878 review feedback.
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Decode gateway-provided thinking metadata for native iOS/macOS chat picker options, preserving extended and legacy thinking levels without leaking default-model options across sessions.\n\nVerification:\n- swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests --no-parallel\n- swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests --no-parallel\n- pnpm lint:swift\n- pnpm check:changed\n\nFollow-up maintainer fix for openclaw#40878 review feedback.
rogerdigital pushed a commit to rogerdigital/openclaw that referenced this pull request May 9, 2026
Decode gateway-provided thinking metadata for native iOS/macOS chat picker options, preserving extended and legacy thinking levels without leaking default-model options across sessions.\n\nVerification:\n- swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests --no-parallel\n- swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests --no-parallel\n- pnpm lint:swift\n- pnpm check:changed\n\nFollow-up maintainer fix for openclaw#40878 review feedback.
lykeion-dev pushed a commit to lykeion-dev/openclaw--rev that referenced this pull request May 14, 2026
Decode gateway-provided thinking metadata for native iOS/macOS chat picker options, preserving extended and legacy thinking levels without leaking default-model options across sessions.\n\nVerification:\n- swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests --no-parallel\n- swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests --no-parallel\n- pnpm lint:swift\n- pnpm check:changed\n\nFollow-up maintainer fix for openclaw#40878 review feedback.
@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. labels May 16, 2026
@clawsweeper

clawsweeper Bot commented May 20, 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.

@clawsweeper

clawsweeper Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

@clawsweeper clawsweeper Bot closed this May 23, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
Decode gateway-provided thinking metadata for native iOS/macOS chat picker options, preserving extended and legacy thinking levels without leaking default-model options across sessions.\n\nVerification:\n- swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests --no-parallel\n- swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests --no-parallel\n- pnpm lint:swift\n- pnpm check:changed\n\nFollow-up maintainer fix for openclaw#40878 review feedback.
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
Decode gateway-provided thinking metadata for native iOS/macOS chat picker options, preserving extended and legacy thinking levels without leaking default-model options across sessions.\n\nVerification:\n- swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests --no-parallel\n- swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests --no-parallel\n- pnpm lint:swift\n- pnpm check:changed\n\nFollow-up maintainer fix for openclaw#40878 review feedback.
sablehead pushed a commit to sablehead/openclaw that referenced this pull request Jun 10, 2026
Decode gateway-provided thinking metadata for native iOS/macOS chat picker options, preserving extended and legacy thinking levels without leaking default-model options across sessions.\n\nVerification:\n- swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests --no-parallel\n- swift test --package-path apps/macos --filter WebChatSwiftUISmokeTests --no-parallel\n- pnpm lint:swift\n- pnpm check:changed\n\nFollow-up maintainer fix for openclaw#40878 review feedback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants