Skip to content

fix(ios): restore in-flight runs after reconnect#100277

Merged
steipete merged 2 commits into
mainfrom
feat/ios-resume-after-seq
Jul 6, 2026
Merged

fix(ios): restore in-flight runs after reconnect#100277
steipete merged 2 commits into
mainfrom
feat/ios-resume-after-seq

Conversation

@steipete

@steipete steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Part of #100197. Supersedes the stacked afterSeq design in #100267.

What Problem This Solves

When iOS backgrounds, reconnects, changes sessions, or misses an event sequence, it can lose ownership of a run that is still active on the Gateway. The transcript may look idle, Abort disappears, and a second send becomes possible while the first run is still working.

Why This Change Was Made

The Gateway already exposes the canonical active-run snapshot through chat.history.inFlightRun; the TUI already consumes that contract. This rewrite removes every proposed afterSeq protocol/client change and restores ownership from the existing snapshot instead.

The shared Apple chat model now restores run ID, buffered text, tool state, Abort, and the send lock during bootstrap, foreground resume, reconnect, sequence-gap recovery, post-send retries, and completion refreshes. History and live events use independent request/generation ordering, global sessions remain agent-scoped, current iOS offline-cache prepaint/write-through remains intact, and changing the active agent clears all session-owned pending state before rebootstrap.

Codex and Copilot transcript mirrors preserve the Gateway-owned <runId>:user idempotency key while retaining separate provider mirror metadata. This gives optimistic UI, Gateway history, and provider transcripts one stable user-turn boundary.

Direct Codex app-server source confirms a turn becomes active before message deltas, so an active run with an empty buffered string is valid ownership.

User Impact

Returning to iOS or macOS chat no longer loses an active response or permits an overlapping send. Recovery works without a new Gateway protocol/cursor, and older Gateways retain the previous transcript-based completion fallback.

Evidence

  • GitHub Actions run 28763343519 passed on exact head 31cf8b9416c10797dce7e3055cad634add04c0d4, including iOS build, macOS Swift/node, native i18n, Android, Node shards, and QA smoke.
  • Fresh Codex autoreview on the exact rebased tree is clean after accepting and fixing the active-agent ownership finding; confidence 0.72.
  • Prior focused OpenClawKit, Codex mirror, and Copilot mirror suites passed; exact-head simulator background/reconnect recovery and persisted transcript identity were verified.
  • Native i18n inventory and git diff --check passed.
  • Direct Gateway active-run and Codex app-server turn-state contracts were inspected; no protocol change is introduced.

@openclaw-barnacle openclaw-barnacle Bot added app: ios App: ios size: L maintainer Maintainer-authored PR labels Jul 5, 2026

@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: 8b0cb66d9d

ℹ️ 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 Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed July 5, 2026, 9:59 PM ET / 01:59 UTC.

Summary
The PR restores Apple chat in-flight run ownership from chat.history.inFlightRun, updates selected-agent session matching, and preserves Gateway user-turn idempotency through Codex and Copilot mirrors.

PR surface: Source +53, Tests +83, Other +1531. Total +1667 across 22 files.

Reproducibility: yes. source inspection provides a high-confidence path: base Apple chat clears local pending state and lacks inFlightRun decoding, while the PR tests and live simulator proof exercise reconnect restoration. The remaining Watch regression is also source-reproducible from the direct unscoped transport constructors plus the Gateway selected-global contract.

Review metrics: 1 noteworthy metric.

  • Apple chat request params: 5 selected-global request paths changed. The new optional agentId wire parameter must be applied consistently across main iOS, Watch, and macOS chat callers before merge.

Stored data model
Persistent data-model change detected: serialized state: extensions/codex/src/app-server/transcript-mirror.test.ts, serialized state: extensions/copilot/src/dual-write-transcripts.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100197
Summary: This PR is the Apple-side candidate fix for the broader mobile reconnect recovery issue, replacing the earlier afterSeq cursor proposal with the existing in-flight-run snapshot contract.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🐚 platinum hermit
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

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

Rank-up moves:

  • [P2] Fix the Watch selected-global transport path.
  • Store and cancel the macOS WebChat Gateway subscription task.
  • Rerun focused Apple chat/source-guard coverage on the updated head.

Risk before merge

  • [P1] Merging as-is can make Watch chat preview/send for a non-default selected global agent read from or send to the default agent transcript.
  • [P1] The new macOS WebChat Gateway subscription can outlive the window controller until another Gateway push terminates the weak-VM loop.
  • [P1] The PR is labeled maintainer, so even after code fixes it still needs explicit maintainer review rather than cleanup closure.

Maintainer options:

  1. Fix Apple sibling paths before merge (recommended)
    Pass the selected agent through Watch chat preview/send transports and store/cancel the macOS WebChat subscription task so the new recovery invariant covers all Apple chat surfaces.
  2. Accept the Watch routing risk
    Maintainers could intentionally land the main iOS recovery while accepting that non-default global Watch chat remains misrouted until a follow-up.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Pass `chatAgentId` into Watch `IOSGatewayChatTransport` construction or route Watch chat through the scoped helper, store/cancel the macOS WebChat Gateway subscription task, and add focused source/behavior coverage for both repairs.

Next step before merge

  • [P2] The remaining blockers are narrow, source-visible repairs in Apple chat call sites and subscription lifecycle handling, suitable for an automated repair attempt on the PR branch.

Security
Cleared: The diff does not change CI, dependencies, lockfiles, secrets handling, package scripts, or downloaded code execution paths; no concrete security or supply-chain concern was found.

Review findings

  • [P2] Pass the selected agent into Watch chat transports — apps/ios/Sources/Model/NodeAppModel.swift:336
  • [P3] Store and cancel the WebChat subscription task — apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift:266
Review details

Best possible solution:

Keep the existing inFlightRun-based recovery design, but thread selected-agent scope through every Apple chat transport owner, including Watch, and make the macOS WebChat subscription lifecycle explicit before merge.

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

Yes, source inspection provides a high-confidence path: base Apple chat clears local pending state and lacks inFlightRun decoding, while the PR tests and live simulator proof exercise reconnect restoration. The remaining Watch regression is also source-reproducible from the direct unscoped transport constructors plus the Gateway selected-global contract.

Is this the best way to solve the issue?

No, not yet complete. Using the existing Gateway inFlightRun snapshot is the best layer for this fix, but the implementation must cover Watch sibling callers and cancel the macOS subscription task before it is the maintainable end state.

Full review comments:

  • [P2] Pass the selected agent into Watch chat transports — apps/ios/Sources/Model/NodeAppModel.swift:336
    This only threads globalAgentId through the main chat helper. Watch preview/send still build IOSGatewayChatTransport(gateway:) directly at NodeAppModel.swift:4431 and :4835, so when the active session is literal global for a non-default agent, chat.history and chat.send omit agentId and the Gateway resolves the request to the default agent transcript. Route those Watch paths through the scoped helper or pass self.chatAgentId there too.
    Confidence: 0.9
  • [P3] Store and cancel the WebChat subscription task — apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift:266
    The new Task subscribes to GatewayConnection.shared.subscribe(), whose stream keeps a subscriber continuation until the stream terminates. Because the window controller never stores or cancels this task, closing a WebChat window can leave the subscriber alive until a later Gateway push notices vm is nil. Keep the task in a property and cancel it from the controller teardown.
    Confidence: 0.82

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add merge-risk: 🚨 compatibility: The PR changes native chat request parameters and selected-global routing, so incomplete caller coverage can alter existing non-default agent behavior.
  • add merge-risk: 🚨 message-delivery: The remaining Watch path can send a literal global reply to the default agent transcript instead of the selected agent transcript.
  • add merge-risk: 🚨 session-state: The PR changes pending-run, active-agent, history-refresh, and transcript identity reconciliation across reconnects and session switches.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR discussion includes live iOS simulator proof for background/reopen active-run recovery plus exact-head CI/Testbox evidence for the main touched behavior; no contributor proof action is needed for this gate.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (live_output): The PR discussion includes live iOS simulator proof for background/reopen active-run recovery plus exact-head CI/Testbox evidence for the main touched behavior; no contributor proof action is needed for this gate.

Label justifications:

  • P1: The PR addresses an active chat reconnect/session-state workflow where users can lose visible ownership of an in-flight run or send overlapping turns.
  • merge-risk: 🚨 compatibility: The PR changes native chat request parameters and selected-global routing, so incomplete caller coverage can alter existing non-default agent behavior.
  • merge-risk: 🚨 message-delivery: The remaining Watch path can send a literal global reply to the default agent transcript instead of the selected agent transcript.
  • merge-risk: 🚨 session-state: The PR changes pending-run, active-agent, history-refresh, and transcript identity reconciliation across reconnects and session switches.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🐚 platinum hermit and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (live_output): The PR discussion includes live iOS simulator proof for background/reopen active-run recovery plus exact-head CI/Testbox evidence for the main touched behavior; no contributor proof action is needed for this gate.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR discussion includes live iOS simulator proof for background/reopen active-run recovery plus exact-head CI/Testbox evidence for the main touched behavior; no contributor proof action is needed for this gate.
Evidence reviewed

PR surface:

Source +53, Tests +83, Other +1531. Total +1667 across 22 files.

View PR surface stats
Area Files Added Removed Net
Source 4 67 14 +53
Tests 4 91 8 +83
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 14 2315 784 +1531
Total 22 2473 806 +1667

Acceptance criteria:

  • [P1] swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests.
  • [P1] focused iOS tests covering IOSGatewayChatTransportTests and RootTabsSourceGuardTests.
  • [P1] macOS Swift/build check covering apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift.

What I checked:

Likely related people:

  • steipete: Live PR metadata assigns this maintainer-labeled item to steipete, and current-main blame/logs show Peter Steinberger recently carried the Gateway in-flight snapshot contract, Apple chat cache/session work, and stale run-state fixes in the affected paths. (role: recent area contributor and likely follow-up owner; confidence: high; commits: aaf5ab910cbe, 4f8eeeaca9a9, 5d8293c1fe40; files: src/gateway/server-methods/chat.ts, src/gateway/chat-abort.ts, src/tui/tui-session-actions.ts)
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 (16 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-05T21:49:45.415Z sha f6804e3 :: found issues before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-05T22:13:00.278Z sha acf2c3f :: needs changes before merge. :: [P3] Remove the release-owned changelog entry | [P3] Cancel the default-agent subscription task
  • reviewed 2026-07-05T22:19:38.242Z sha 7002c17 :: needs changes before merge. :: [P3] Remove the release-owned changelog entry | [P3] Cancel the default-agent subscription task
  • reviewed 2026-07-05T22:36:03.563Z sha 8431515 :: needs changes before merge. :: [P2] Pass globalAgentId through Watch chat transports | [P3] Remove the release-owned changelog entry | [P3] Cancel the default-agent subscription task
  • reviewed 2026-07-05T22:53:05.181Z sha 407d551 :: needs changes before merge. :: [P2] Pass globalAgentId through Watch chat transports | [P3] Remove the release-owned changelog entry | [P3] Cancel the default-agent subscription task
  • reviewed 2026-07-05T23:07:45.569Z sha f8096c8 :: needs changes before merge. :: [P2] Pass globalAgentId through Watch chat transports | [P3] Remove the release-owned changelog edits | [P3] Cancel the default-agent subscription task
  • reviewed 2026-07-05T23:15:38.030Z sha f8096c8 :: needs changes before merge. :: [P2] Pass globalAgentId through Watch chat transports | [P3] Remove the release-owned changelog edits | [P3] Cancel the default-agent subscription task
  • reviewed 2026-07-06T00:28:30.091Z sha fd4d69d :: needs changes before merge. :: [P2] Pass the selected agent into Watch chat transports | [P2] Trim connect detail codes before comparing | [P3] Store and cancel the WebChat subscription task | [P3] Remove the release-owned changelog entry

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 5, 2026
@steipete
steipete force-pushed the feat/ios-resume-after-seq branch from 8b0cb66 to 4030223 Compare July 5, 2026 11:07

@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: 4030223d78

ℹ️ 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 added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jul 5, 2026
@steipete
steipete force-pushed the feat/gateway-chat-history-after-seq branch 3 times, most recently from c9a5ce2 to eb669c2 Compare July 5, 2026 12:34
@steipete
steipete force-pushed the feat/ios-resume-after-seq branch from 4030223 to 20fad5f Compare July 5, 2026 12:42
@steipete
steipete force-pushed the feat/gateway-chat-history-after-seq branch from eb669c2 to 262de5b Compare July 5, 2026 12:50
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui gateway Gateway runtime scripts Repository scripts size: XL and removed size: L labels Jul 5, 2026

@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: 40fec95283

ℹ️ 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 removed the status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. label Jul 5, 2026
@steipete
steipete force-pushed the feat/ios-resume-after-seq branch 2 times, most recently from 622c3b6 to ee14abf Compare July 5, 2026 21:07
@clawsweeper clawsweeper Bot removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 5, 2026
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready rewrite at acf2c3f984d92272d24a721a9c0b4ea20e6efcb6.

What changed:

  • Removed the stacked afterSeq protocol/cursor design; recovery now uses canonical chat.history.inFlightRun.
  • Reconciles bootstrap, foreground, sequence-gap, post-send, delayed-history, terminal-event, session-switch, and agent-switch races in the shared Apple chat model.
  • Keeps startup transport unscoped until the Gateway resolves the actual default agent, including the visible-main/transport-main rebuild edge.
  • Preserves Gateway user idempotency through Codex and Copilot transcript mirrors while retaining provider mirror metadata.
  • Preserves foreground completion haptics when the authoritative recovery snapshot clears pending state.

Proof:

  • swift test --package-path apps/shared/OpenClawKit --filter ChatViewModelTests — 136/136 passed.
  • Blacksmith Testbox Codex transcript/run-attempt tests — 134/134 passed.
  • Blacksmith Testbox Copilot transcript/attempt tests — 129/129 passed.
  • Blacksmith Testbox tbx_01kwt13g1jy7ast7t6zsdz1myn changed gate — exit 0 on range-diff-identical rebased head b4bfadffab9.
  • xcodebuild -quiet -project apps/ios/OpenClaw.xcodeproj -scheme OpenClaw -configuration Debug -destination 'platform=iOS Simulator,id=F8D0EA37-7040-4FA7-8CFA-BA8841C68E1A' -derivedDataPath /tmp/openclaw-100277-b4bf-derived CODE_SIGNING_ALLOWED=NO build — passed on the same range-diff-identical functional tree.
  • SwiftFormat lint for every touched Swift file and git diff --check — clean.
  • Fresh full-branch Codex autoreview — no accepted/actionable findings.
  • Hosted exact-head CI, including the final iOS build: https://github.com/openclaw/openclaw/actions/runs/28756286353

Live simulator proof on iPhone 17 / iOS 26.5: started a delayed tool-backed run, backgrounded the app, reopened while active, and observed exactly one user row plus restored Writing/Stop state. Completion reconciled to exactly one user row and one RECOVERY_FINAL_EXACT_100277 assistant row. The persisted transcript retained the Gateway <runId>:user key and separate mirrorOrigin=codex-app-server metadata.

Dependency contract checked directly against Codex be33f80bc65159c094ecd06bf155afa3061ce23d: codex-rs/app-server/src/bespoke_event_handling.rs:155-183, codex-rs/app-server-protocol/src/protocol/event_mapping.rs:359-367, and codex-rs/app-server-protocol/src/protocol/v2/turn.rs:375-378.

Known proof gaps: none for the touched behavior after exact-head hosted CI completes successfully.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 5, 2026
@steipete
steipete force-pushed the feat/ios-resume-after-seq branch from ee14abf to b4a5cfa Compare July 5, 2026 21:24

@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: 7002c17c8d

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

}

init(gateway: GatewayNodeSession) {
init(gateway: GatewayNodeSession, globalAgentId: String? = nil) {

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.

P2 Badge Pass globalAgentId through Watch chat transports

Fresh evidence beyond the earlier selected-global path is that NodeAppModel's Watch preview/send paths still instantiate IOSGatewayChatTransport(gateway:) without an agent (apps/ios/Sources/Model/NodeAppModel.swift:4279 and :4683). When the iPhone is focused on literal global for a non-default agent, the Watch snapshot carries sessionKey: "global", but requestHistory/chat.send now include agentId only through selectedGlobalAgentId(for:) populated by this initializer; with the default nil, the gateway resolves global to the default agent (src/gateway/server-methods/chat.ts:3091-3100, src/gateway/session-create-service.ts:50-83). That makes Watch previews, sends, and reply readback hit the wrong transcript, so pass self.chatAgentId into those transports or route them through makeChatTransport.

Useful? React with 👍 / 👎.

@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: fd4d69d3f1

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

}
const code = (details as { code?: unknown }).code;
return typeof code === "string" && code.trim().length > 0 ? code.trim() : null;
return typeof code === "string" && code.trim().length > 0 ? code : null;

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.

P2 Badge Trim connect detail codes before comparing

When a gateway connect error arrives with padding in details.code, this now returns the raw string even though the helper only accepts it based on code.trim().length. Callers compare the returned value to exact constants (PAIRING_REQUIRED, PROTOCOL_MISMATCH, AUTH_TOKEN_MISMATCH, etc.), so padded structured errors fall through to generic formatting and can skip recovery paths such as device-token retry/cleanup in packages/gateway-client/src/client.ts. Return the trimmed code as before so untrusted but otherwise valid detail payloads still drive the intended reconnect behavior.

Useful? React with 👍 / 👎.

steipete added 2 commits July 5, 2026 21:50
Restore active Apple chat ownership across reconnect, foreground, and sequence-gap recovery using the existing chat.history snapshot. Preserve agent/session scoping and Gateway user-turn identity across Codex and Copilot mirrors, including current offline-cache integration.
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Landed as 443c582949e3ec6dfc197ea1d33913a7cd7448f3.

Exact-head CI run 28763343519 passed on 31cf8b9416c10797dce7e3055cad634add04c0d4, including iOS build, macOS Swift/node, native i18n, Android, Node shards, and QA Smoke. Final Codex autoreview on the exact rebased tree was clean with no accepted/actionable findings (confidence 0.72).

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

Labels

agents Agent runtime and tooling app: ios App: ios app: macos App: macos app: web-ui App: web-ui docs Improvements or additions to documentation extensions: codex extensions: copilot gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: XL status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant