Skip to content

[orchestrator-v2] fix(mobile): Stabilize iOS draft attachments, Hermes sort, and Home#3923

Open
mwolson wants to merge 2 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/ios-v2-attachment-persistence
Open

[orchestrator-v2] fix(mobile): Stabilize iOS draft attachments, Hermes sort, and Home#3923
mwolson wants to merge 2 commits into
pingdotgg:t3code/codex-turn-mappingfrom
mwolson:fix/ios-v2-attachment-persistence

Conversation

@mwolson

@mwolson mwolson commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Keep CTM mobile draft image attachments working when they carry both a local id and a dataUrl.
  • Avoid a Hermes fatal in the queue UI by replacing missing Array.prototype.toSorted with a shared copy-sort helper.
  • Hide orchestration-v2 subagent threads from the mobile Home list (forks stay visible).
  • Stabilize Home native-stack options and callbacks so ordinary Home updates do not re-enter navigation through PreventRemoveProvider.
  • Heal V2 shell archive membership on reconnect so archived threads do not stick on the Home list after a missed archive delta.

Problem and Fix

Problem and Why it Happened Fix
CTM drafts can include image attachments with both a local id and a dataUrl. The start-turn path did not treat those dual-tagged attachments as uploads, so order and persistence broke for mobile screenshots. Treat dual-tagged attachments as uploads, strip local-only fields before persistence, and dispatch server IDs while preserving order with already-persisted attachments.
Hermes 250829098 (RN 0.85.3) does not implement Array.prototype.toSorted. CTM queue UI calls it from deriveThreadQueueWorkflowState / ThreadQueueControl, so queuing a reply or finishing a turn can crash with TypeError: undefined is not a function. Add @t3tools/shared/Array copySorted ([...values].sort) and use it on mobile-reachable call sites (threadWorkflows, ThreadRelationshipsBanner, use-thread-selection, CTM model.ts).
Orchestration-v2 subagent shells appeared in the mobile Home list, unlike the desktop sidebar. Skip threads with lineage.relationshipToParent === "subagent" when grouping Home rows; keep fork threads.
Unstable Home native-stack options and callbacks re-entered setOptions and could hit maximum update depth through PreventRemoveProvider on CTM device launches. Memoize iOS Home header options (filter menu inputs as deps; handlers via ref) and stabilize Settings / New Task callbacks and title option objects.
Warm-cache afterSequence resume could skip a dropped thread.archived shell delta after later events advanced snapshotSequence, leaving archived threads active on Home (reproduced with a paired CTM environment). HTTP-heal the full shell snapshot on every live session before afterSequence resume; if HTTP fails, force a full socket snapshot; normalize active/archive membership from archivedAt; reject stale non-authoritative full snapshots.

Validation

  • Targeted tests: client-runtime attachment command tests; Home subagent filter tests (including fork negative control); shared Array tests.
  • vp check (0 errors).
  • Scoped typecheck: @t3tools/shared, @t3tools/client-runtime, @t3tools/mobile.
  • Shell archive heal unit tests (shell-sync / shellReducer): pass
  • Device: archived threads from a paired CTM environment leave Home after reconnect/heal
  • Device: Release Hermes com.mwolson.t3code.v2.dev from local orchestrator-v2 integration; queued reply send after active turn finished without crash; Home list usable after nav stability fix.

Notes

Note

Fix iOS draft attachments, shell sync membership, and stale closures in mobile Home header

  • Fixes persistAttachments in commands.ts to correctly remap upload attachments to server-assigned IDs while preserving order; local preview-only IDs are no longer dispatched.
  • Fixes shell synchronization in shell.ts to heal membership from server snapshots before resuming and prevent stale full snapshots from reintroducing archived threads.
  • Adds normalizeShellThreadMembership to re-partition threads between active and archive lists based on archivedAt, fixing mis-tagged deltas keeping archived threads in active lists.
  • Fixes stale closures in HomeHeader.tsx by using a propsRef so header action callbacks always read current props.
  • Replaces .toSorted() calls with copySorted from a new Array.ts utility to avoid mutating source arrays; filters subagent threads from home thread groups.

Macroscope summarized a5467d3.


Note

Medium Risk
Touches shared turn-start attachment persistence and client-runtime shell bootstrap/healing used by mobile and desktop; incorrect heal or snapshot rules could show wrong thread lists, but behavior is heavily unit-tested.

Overview
Fixes several mobile orchestration-v2 issues: draft image turns, Hermes crashes, Home list noise, navigation loops, and ghost threads after archive.

Attachments: persistAttachments now treats any attachment with a dataUrl as an upload (including dual-tagged local preview ids), strips local-only fields before assetsPersistChatAttachments, and remaps persisted server ids in original order alongside already-stored attachments.

Hermes: Adds @t3tools/shared/Array copySorted and replaces Array.prototype.toSorted on mobile-reachable paths (queue UI, thread relationships, thread selection, model option comparison) to avoid runtime fatals on RN Hermes.

Home: Skips threads with lineage.relationshipToParent === "subagent" when building Home groups (forks remain). HomeHeader memoizes native stack options and routes toolbar handlers through propsRef; HomeRouteScreen stabilizes Settings/New Task callbacks and title option objects to reduce setOptions / PreventRemoveProvider update depth.

Shell sync: On each live session, heals membership via HTTP full snapshot before afterSequence resume (warm disk cache alone no longer drives resume). Adds normalizeShellThreadMembership and prefers archivedAt over mis-tagged location on deltas; rejects stale non-authoritative full snapshots; when HTTP heal fails, accepts the next socket full snapshot authoritatively.

Reviewed by Cursor Bugbot for commit a5467d3. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 28130f2d-4228-4187-acde-827f58a22ba8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Jul 12, 2026
Comment thread apps/mobile/src/features/home/HomeHeader.tsx
@mwolson mwolson marked this pull request as ready for review July 12, 2026 21:35
Comment thread packages/shared/src/Array.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR bundles significant runtime behavior changes including shell sync strategy refactoring (HTTP heal before socket subscription, authoritative snapshot acceptance), subagent thread exclusion from home list, and draft attachment handling fixes. The shell sync changes in particular alter core state synchronization logic and warrant human review.

You can customize Macroscope's approvability policy. Learn more.

@mwolson mwolson force-pushed the fix/ios-v2-attachment-persistence branch from 2857eb3 to 76a88a0 Compare July 12, 2026 21:41
@mwolson mwolson changed the title fix(mobile): Stabilize CTM iOS draft attachments, Hermes sort, and Home [orchestrator-v2] fix(mobile): Stabilize CTM iOS draft attachments, Hermes sort, and Home Jul 12, 2026
Persist dual-tagged draft image attachments, replace Hermes-missing toSorted
with copySorted on mobile-reachable paths, hide subagent threads from Home,
and stabilize Home native-stack options to avoid PreventRemove max-update-depth.
Comment thread packages/client-runtime/src/state/shell.ts Outdated
@mwolson mwolson force-pushed the fix/ios-v2-attachment-persistence branch from 33a612d to 10513f1 Compare July 13, 2026 02:19
Comment thread packages/client-runtime/src/state/shell.ts

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 10513f1. Configure here.

Comment thread packages/client-runtime/src/state/shell.ts
Port the ios-fixes-main shell reconnect heal to orchestration V2: always
HTTP-heal (or force a full socket snapshot) before afterSequence resume,
reject stale full snapshots, and normalize active/archive membership from
archivedAt so dropped archive deltas cannot stick threads on the home list.
@mwolson mwolson force-pushed the fix/ios-v2-attachment-persistence branch from 10513f1 to a5467d3 Compare July 13, 2026 02:27
@mwolson mwolson changed the title [orchestrator-v2] fix(mobile): Stabilize CTM iOS draft attachments, Hermes sort, and Home [orchestrator-v2] fix(mobile): Stabilize iOS draft attachments, Hermes sort, and Home Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant