You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: SwiftUI app stops showing the running turn after a checkpoint-capture error; iOS app keeps updating #13996
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Area
apps/mobile
Steps to reproduce
Open the same thread in both the SwiftUI TestFlight app (0.1.0, build 52) and the iOS app (1.3.0, build 85) on one iPhone. The host is a Windows desktop.
Send a message. During the turn, the host fails a checkpoint: Checkpoint capture failed — VCS process timed out in GitVcsDriver.checkpoints.captureCheckpoint: git (<repo>) after 30000ms.
Watch both apps while the turn continues.
Expected behavior
The checkpoint failure shows as a notice, and both apps keep streaming and then show the finished reply.
Actual behavior
The SwiftUI app shows the checkpoint failure above the sent message and then no reply; the composer stays in its busy state. The iOS app shows the same turn finishing normally ("Worked for 1m 25s") with the full reply. The turn completed on the host.
iPhone, iOS 27; Windows 11 host; direct connection over Tailscale Serve HTTPS
Logs or stack traces
Host trace: GitVcsDriver.checkpoints.captureCheckpoint took 19–44 s on this host this morning, with several failures at the 30 s limit. The Git commands themselves are fast (git write-tree ~0.03 s in the same repo); the host's per-command process cleanup is slow (a taskkill /T /F of a trivial process tree measured 16 s, with WMI queries taking 14–57 s), so this checkpoint failure recurs on this machine. The client-side issue is that the SwiftUI app stops following the turn after the error, while the iOS app does not.
This is a SwiftUI client bug. The Windows checkpoint timeout is real, but it is not what leaves the thread stuck.
The host is doing what the server already specifies. CheckpointReactor catches a failed GitVcsDriver.checkpoints.captureCheckpoint and appends a checkpoint.capture.failed activity (summary: "Checkpoint capture failed", detail = the VCS timeout). That does not fail the turn. The React Native app is following that: same thread, same host, reply finishes ("Worked for 1m 25s"). The timeout text matches VcsProcessTimeoutError (VCS process timed out in GitVcsDriver.checkpoints.captureCheckpoint: git (<cwd>) after 30000ms). The slow taskkill / WMI cleanup is why this machine hits the 30s limit; it is not a second bug in this report.
The client that stops is the SwiftUI TestFlight app (0.1.0, build 52), which is apps/swift-ios on t3code/rebuild-mobile-app-swift (157476f1fb), not apps/mobile. On that branch:
Every error-tone activity, including checkpoint.capture.failed, becomes a transcript row (NativeActivityNotice). Rows are ordered by createdAt, and parseDate uses Date.distantPast when a timestamp does not parse, which places the notice above the user bubble.
A local send that is still only an optimistic row is appended after the server transcript (addingPendingMessages). If the detail the client has contains the failure notice but not the authoritative user message, the notice sits above the bubble that was just sent, and no assistant reply is in that list. That matches the screenshot-less report.
sendMessageResolved does not release the send until a follow-up refreshThread returns. ThreadDetailView.send keeps isSending true for that whole wait, so the composer stays on the busy control while that snapshot read is outstanding. A read blocked behind the same 30s git timeout stays busy for the rest of the turn. The stop control also stays up while session.status is still running (resolveThreadState).
reduceActivity does not keep the activity on the thread; the render cache owns it. A decode miss returns .refresh, which clears activeRawThread and drops pending transcript publishes. Until a later snapshot is applied, further detail events are not reduced. The React Native client uses packages/client-runtimethreadReducer, which appends the activity and keeps applying later events, so the same turn completes there.
Not a duplicate. Related unmerged SwiftUI work, none of which mentions this checkpoint trigger: #10758 (release Send before the optional refresh), #10759 (transcript missing the completed reply), #10763 (selected-thread stream goes silent). Those are the right place to fix the client. The host timeout does not need to be fixed for this issue.
Activity
juliusmarminge commentedon Sep 27, 2026
Triage
This is a SwiftUI client bug. The Windows checkpoint timeout is real, but it is not what leaves the thread stuck.
The host is doing what the server already specifies.
CheckpointReactorcatches a failedGitVcsDriver.checkpoints.captureCheckpointand appends acheckpoint.capture.failedactivity (summary: "Checkpoint capture failed", detail = the VCS timeout). That does not fail the turn. The React Native app is following that: same thread, same host, reply finishes ("Worked for 1m 25s"). The timeout text matchesVcsProcessTimeoutError(VCS process timed out in GitVcsDriver.checkpoints.captureCheckpoint: git (<cwd>) after 30000ms). The slowtaskkill/ WMI cleanup is why this machine hits the 30s limit; it is not a second bug in this report.The client that stops is the SwiftUI TestFlight app (0.1.0, build 52), which is
apps/swift-iosont3code/rebuild-mobile-app-swift(157476f1fb), notapps/mobile. On that branch:checkpoint.capture.failed, becomes a transcript row (NativeActivityNotice). Rows are ordered bycreatedAt, andparseDateusesDate.distantPastwhen a timestamp does not parse, which places the notice above the user bubble.addingPendingMessages). If the detail the client has contains the failure notice but not the authoritative user message, the notice sits above the bubble that was just sent, and no assistant reply is in that list. That matches the screenshot-less report.sendMessageResolveddoes not release the send until a follow-uprefreshThreadreturns.ThreadDetailView.sendkeepsisSendingtrue for that whole wait, so the composer stays on the busy control while that snapshot read is outstanding. A read blocked behind the same 30s git timeout stays busy for the rest of the turn. The stop control also stays up whilesession.statusis stillrunning(resolveThreadState).reduceActivitydoes not keep the activity on the thread; the render cache owns it. A decode miss returns.refresh, which clearsactiveRawThreadand drops pending transcript publishes. Until a later snapshot is applied, further detail events are not reduced. The React Native client usespackages/client-runtimethreadReducer, which appends the activity and keeps applying later events, so the same turn completes there.Not a duplicate. Related unmerged SwiftUI work, none of which mentions this checkpoint trigger: #10758 (release Send before the optional refresh), #10759 (transcript missing the completed reply), #10763 (selected-thread stream goes silent). Those are the right place to fix the client. The host timeout does not need to be fixed for this issue.