Skip to content

fix(mobile): use the archive eligibility guard when dispatching - #9930

Merged
shivamhwp merged 3 commits into
pingdotgg:t3code/codex-turn-mappingfrom
saphid:fix/v2-mobile-archive-guard-20260905
Sep 5, 2026
Merged

fix(mobile): use the archive eligibility guard when dispatching#9930
shivamhwp merged 3 commits into
pingdotgg:t3code/codex-turn-mappingfrom
saphid:fix/v2-mobile-archive-guard-20260905

Conversation

@saphid

@saphid saphid commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

React Native could offer Archive and then reject it because the action handler used a broader “active” predicate than the menu. Reuse threadCanArchive at dispatch so queued/waiting states follow the existing archive policy while executing turns remain protected.

Verified the mounted native archive callback on an isolated iPhone 16 Pro simulator (iOS 26.5), using the Legacy Thread List and a disposable thread. Before: useThreadListActions.ts from b9fa1399c. After: #9930 head 9f7b9838b, patch-identical in integration fa6a1ab04. Native Debug build: exit 0.

The callback received the same injected runtime.status = "waiting" fixture with a retained active-run ID on both bundles. Before, it showed the incorrect “working” alert. After, it sent the real archive command, the server persisted archivedAt, and the active-list count fell from 3 to 2. Restore through the mounted unarchive callback cleared archivedAt; a repeat archive succeeded.

Before: archive rejected After: archived thread removed
Waiting-state fixture rejected as working Archive succeeds and two active threads remain
Annotated screenshots

archive-image-annotated.png

archive-image-annotated.png

Automation limits: iOS did not expose thread rows as actionable accessibility targets, so the registered React callbacks were invoked through the development runtime. The physical row gesture was not exercised. A real Codex user-question turn still reports running, so the waiting state was explicitly injected at the callback boundary; this is a guard regression fixture, not a claim that that live provider state naturally becomes waiting. The initial direct deep-link entry to Archived Threads mounted a row without displaying it; that existing native presentation gap remains. A supplemental pass through the normal Settings → Archived Threads route displayed the row and exercised restoration as described below.

Supplemental normal Settings route and restoration proof

Normal Settings → Archived Threads shows the archived row (integration fa6a1ab04). On integrated candidate 860f3a6f5, the public Swipeable.openRight() API exposed the row actions, then the actual semantic Unarchive button was tapped. The screen showed “No archived threads”; the server cleared archivedAt and the active-list count returned to 3. Both revisions contain the same #9930 archive hook. This supplements the waiting-state guard fixture above; it does not exercise the physical row swipe or establish that the initial direct deep-link presentation gap is fixed.

Normal Settings route displays the archived thread

Public Swipeable API exposes Unarchive and Delete actions

After tapping Unarchive, no archived threads remain

Validation: all 3 archive-eligibility tests, React Native typecheck, and targeted lint passed in frozen verification. This changes only the React Native archive hook; Android was not separately exercised. Targets Julius’s Orchestrator V2 branch in #2829.

A direct Claude Opus 5 high review attempt exited 1 because OAuth expired before model execution; no Claude review occurred. Implemented and verified with GPT-6 Astra in Codex/T3.


Note

Low Risk
Single guard swap in the React Native archive path; behavior is narrowed to match existing archive policy and tests, with no auth or server contract changes.

Overview
Fixes a mismatch where the thread list could show Archive but the action handler blocked it with a stricter “active runtime” check than the menu uses.

Archive dispatch in useThreadListActions now uses threadCanArchive (same as eligibility elsewhere) instead of threadRuntimeIsActive. Threads in waiting (and other non-executing states) can archive when policy allows; turns still in preparing, starting, or running keep the existing “working—interrupt first” alert.

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

Note

Use threadCanArchive guard instead of threadRuntimeIsActive in useThreadActionExecutor

Replaces the direct threadRuntimeIsActive check with the existing threadCanArchive predicate when deciding whether to dispatch an archive action. The rejected case still shows the same alert and returns false. Risk: threadCanArchive(thread.runtime) may reject archive in states where threadRuntimeIsActive would have allowed it — verify the predicate's conditions in useThreadListActions.ts cover the intended runtime states.

Macroscope summarized 1447ae0.

@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Sep 5, 2026
@macroscopeapp

macroscopeapp Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Macroscope has since reviewed this pull request. An earlier review was skipped by a cost limit; a review has now completed, so that notice no longer applies.

@github-actions github-actions Bot added the size:XXL 1,000+ changed lines (additions + deletions). label Sep 5, 2026
@saphid
saphid force-pushed the fix/v2-mobile-archive-guard-20260905 branch from dae82c8 to 9f7b983 Compare September 5, 2026 05:07
@github-actions github-actions Bot added size:XS 0-9 changed lines (additions + deletions). and removed size:XXL 1,000+ changed lines (additions + deletions). labels Sep 5, 2026
@saphid
saphid marked this pull request as ready for review September 5, 2026 07:19
@macroscopeapp

macroscopeapp Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 9f7b983

Macroscope's review found this PR approvable — This is a focused one-file bug fix that aligns archive dispatch with the existing eligibility policy, allowing eligible waiting threads while continuing to block actively executing turns. No schema, configuration, security-sensitive, or static-analysis changes are involved.

You can add or adjust custom eligibility rules. Learn more.

@shivamhwp
shivamhwp merged commit 315f53f into pingdotgg:t3code/codex-turn-mapping Sep 5, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS 0-9 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants