feat(swift-ios): keep failed source control output visible with accessible Retry - #7371
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This introduces a new production recovery workflow for source-control operations, including persistent failure UI, accessibility focus management, single-flight state, and Retry for side-effectful actions. It also changes the mutation and status-refresh boundary, so the scope and runtime behavior warrant human review. You can add or adjust custom eligibility rules. Learn more. |
1f39d72 to
fce7740
Compare
…sible Retry Recoverable source-control failures were invisible whenever a repository status had already loaded: the error string only ever reached the ContentUnavailableView fallback, so a failed commit, push, pull, or pull request silently did nothing. There was also no way to retry the exact failed operation and no accessibility focus handling. Retain the failure content in a banner that survives its own retry, keep a stable "Retry <operation>" accessibility label, replay the failed operation with its commit message, move VoiceOver focus to the retained failure and back to the refreshed repository status on recovery, and stop treating cancellation as a failure.
73a4932 to
27a897e
Compare
…t' into feat/issue87-tool-error-recovery
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 42696d5. Configure here.

Observed problem and reproduction
Open SwiftUI Source Control, let repository status load, then trigger an operation that fails. Before this change, the surface could keep showing stale repository content while silently discarding the recoverable error. There was no operation-specific Retry and no predictable VoiceOver focus.
Cause
Load and mutation failures shared transient view state. The client also hid a follow-up status refresh inside the mutation call, so a refresh failure could be mistaken for mutation failure and retry a completed non-idempotent action.
Change and boundary
A retained failure banner stays above existing repository content and keeps its message while Retry runs. Retry replays the exact failed operation, including commit text. Cancellation does not create a failure. Successful recovery clears the matching failure with one accessibility announcement.
Source-control mutations and their follow-up status refresh now have separate failure boundaries. If the mutation completes and refresh fails, Retry reloads status only. A single-flight state prevents overlapping load, action, and retry races. Long error text scrolls within a capped region so Dynamic Type cannot push Retry off screen.
Conflict resolution used a merge of the live
t3code/rebuild-mobile-app-swifttarget at22b22f146into the contributor branch. The resolution preserves the target's new source-control status event stream and re-expresses only this PR's separate mutation/refresh boundary.Non-goals
This PR does not change git command semantics, server contracts, provider adapters, web, desktop, or React Native mobile. It does not retry automatically or hide the original failure cause.
Affected areas
FeatureClientmutation boundary, and native client implementation.Validation
Current head:
87ce6873a.FeatureToolRecoveryTests: 20 passed, 0 failed, 0 skipped; realxcodebuildexit 0 on iPhone 17 Pro / iOS 26.5 with isolated private DerivedData. The result bundle confirms 20 matched test cases.xcrun swiftc -parseon all six touched Swift files: passed, exit 0.git diff --check: passed, exit 0.22b22f146: exactly the intended six Swift files; 641 additions and 61 deletions.errorMessagealert, which had been superseded by this PR's retained recovery banner.Risks, untested paths, and known gaps
47389c712and must not be treated as exact-head proof. Human review has not been re-requested.Evidence
The following media was captured on pre-merge head
47389c712. It remains useful for historical comparison but is not current-head proof.Before, healthy repository in light appearance
Before, healthy repository in dark appearance
After, retained failure and Retry in light appearance
After, retained failure and Retry in dark appearance
Interaction video
Play or download the MP4.
Owning issue and stack
Owning issue: saphid/t3code-personal#87. Exact-head proof is tracked by saphid/t3code-personal#150. This PR targets the open SwiftUI parent branch and depends on #5178 landing. It is not stacked on #7345. Maintainer edits are enabled.
Note
Add persistent failure banner with accessible Retry to source control UI
FeatureSourceControlViewwith a retained failure banner that shows a scroll-limited message and an accessible Retry button that replays the exact failed operation (including commit messages)FeatureToolFailureStatemanages cancellation-aware failure state with one-time recovery announcements,FeatureToolRunStateprevents overlapping operations via single-flight, andFeatureRecoverableOperationprotocol models retryable operationsperformSourceControlActiononFeatureClientprotocol andNativeFeatureClientto returnVoidinstead ofFeatureSourceControlStatus; callers now refresh status themselves after mutationsFeatureClient.performSourceControlActionmust drop the return value; the source control view now performs an explicit post-action status refresh rather than relying on the method's return valueMacroscope summarized 87ce687.