feat(apps): review durable approvals on mobile#103912
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 11, 2026, 10:30 PM ET / July 12, 2026, 02:30 UTC. Summary PR surface: Tests +30, Docs +65, Other +11376. Total +11471 across 63 files. Reproducibility: not applicable. This PR adds a new native approval-review capability rather than repairing a reproducible current-main bug; the failing changed Android test is validation evidence, not a user-report reproduction. Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Keep the Gateway-owned durable lifecycle and exact-byte owner model, but merge only after branch-caused checks are fixed, fresh-install and upgrade paths pass, and redacted real-device proof covers pending review, competing resolution, Gateway switching, and ambiguous-write recovery on Android, iPhone, and paired Apple Watch. Do we have a high-confidence way to reproduce the issue? Not applicable. This PR adds a new native approval-review capability rather than repairing a reproducible current-main bug; the failing changed Android test is validation evidence, not a user-report reproduction. Is this the best way to solve the issue? Yes at the architectural level: official clients should consume the Gateway-owned durable record and advertised method catalog rather than create native-local approval truth. Merge readiness still requires clean exact-head checks, upgrade proof, and real-device evidence. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 01fc1ed02a50. Label changesLabel justifications:
Evidence reviewedPR surface: Tests +30, Docs +65, Other +11376. Total +11471 across 63 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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
Review history (5 earlier review cycles)
|
72e8289 to
fdad6d7
Compare
f73c56e to
2ed37ce
Compare
fdad6d7 to
12ec1bc
Compare
2ed37ce to
77a798b
Compare
|
Land-ready update: rebased through the reconciled stack; review findings fixed and revalidated across four structured-review cycles until clean. Fixes since the last head — iOS: gateway switches preserve owner-scoped in-flight write fences and ambiguous outcomes (rapid A→B→A can no longer double-submit or lose a lost-write record); re-presented cards render resolving for the whole active attempt including post-write readback; the Watch pending-retry path unlocks the phone card with the retry message; the Watch snapshot-request decoder accepts the shipped (pre-heldApprovals) request shape during version skew, with a named removal condition. Android: losing first-answer outcomes render as a standalone dismissible banner that survives refreshes and unrelated writes, with publication-distinct atomic dismissal; the legacy already-resolved/epoch race no longer strands in-flight write records. Both v4 fallback selectors carry removal-plan comments; a lint-shape refactor split WatchInboxStore and extracted NodeAppModel helpers (behavior-preserving, swiftlint --strict clean). Validation: full iOS |
12ec1bc to
548cca6
Compare
77a798b to
7d82c13
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7d82c13abd
ℹ️ 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".
| var pendingApprovalCount: Int { | ||
| self.appModel.pendingExecApprovalCount | ||
| } |
There was a problem hiding this comment.
Badge the approvals row from the inbox count
Now that durable approvals can sit in pendingExecApprovalInboxItems without a selected modal prompt, pendingApprovalCount can be >0 while pendingApproval is nil. The Approvals detail uses this count, but the Settings home row still keys its orange state and badge off pendingApproval == nil in apps/ios/Sources/Design/SettingsProTabSections.swift:143-146, so if a user dismisses/suppresses the modal and leaves approvals in the inbox, the Settings list shows the row as green with no badge even though exec approvals are waiting.
Useful? React with 👍 / 👎.
dcf1cb6 to
7f72cbf
Compare
Squash-rebased #103912 segment onto the deep-links tip on current main. Native approval surfaces: iOS approval presentation with gateway-switch lease preservation and resolution fencing, watchOS inbox + approval actions with shipped-shape payload codec, Android approval notices with publication-tokened dismissal. Native i18n inventory regenerated. (cherry picked from commit 428a76670ffeede54248b7bd7aa4438e2589851b) (cherry picked from commit 80225d5707c3645eeea5435f266131037b50ede6) (cherry picked from commit 2a23b714dc30d773a294aa45adc617e46b80732e) (cherry picked from commit 9ff1153827769e2cbab7c11c153f0f8634662c28) (cherry picked from commit 5b25723525bd562e5f97478af492f7b46ad30fd1) (cherry picked from commit 8c80e8467b5fe89aad0d4c74a0573f1600ed3af9) (cherry picked from commit ad4037bc9846bf6f082b41c129ee68aa344576c3) (cherry picked from commit fdf767dd662cff3c8a5a6d571f38f153410651ca) (cherry picked from commit 00c120376ffd992ea68ce29254a9bc0a25ed1740) (cherry picked from commit f36a952) (cherry picked from commit e2c25cbe2baacab44d21871d8cb6734704f065ac) (cherry picked from commit 7c4fda519080486d341a9f4df36d63f9e24b1235) (cherry picked from commit 1b3d4eda3dc5988012124597f9454ae21fb187a1) (cherry picked from commit 2a60619)
2a60619 to
6f0c386
Compare
7f72cbf to
1bf6791
Compare
Squash-rebased #103912 segment onto the deep-links tip on current main. Native approval surfaces: iOS approval presentation with gateway-switch lease preservation and resolution fencing, watchOS inbox + approval actions with shipped-shape payload codec, Android approval notices with publication-tokened dismissal. Native i18n inventory regenerated. (cherry picked from commit 428a76670ffeede54248b7bd7aa4438e2589851b) (cherry picked from commit 80225d5707c3645eeea5435f266131037b50ede6) (cherry picked from commit 2a23b714dc30d773a294aa45adc617e46b80732e) (cherry picked from commit 9ff1153827769e2cbab7c11c153f0f8634662c28) (cherry picked from commit 5b25723525bd562e5f97478af492f7b46ad30fd1) (cherry picked from commit 8c80e8467b5fe89aad0d4c74a0573f1600ed3af9) (cherry picked from commit ad4037bc9846bf6f082b41c129ee68aa344576c3) (cherry picked from commit fdf767dd662cff3c8a5a6d571f38f153410651ca) (cherry picked from commit 00c120376ffd992ea68ce29254a9bc0a25ed1740) (cherry picked from commit f36a952) (cherry picked from commit e2c25cbe2baacab44d21871d8cb6734704f065ac) (cherry picked from commit 7c4fda519080486d341a9f4df36d63f9e24b1235) (cherry picked from commit 1b3d4eda3dc5988012124597f9454ae21fb187a1) (cherry picked from commit 2a60619) (cherry picked from commit 6f0c386)
6f0c386 to
784a585
Compare
115acda to
cc0c3f8
Compare
Squash-rebased #103912 segment onto the deep-links tip on current main. Native approval surfaces: iOS approval presentation with gateway-switch lease preservation and resolution fencing, watchOS inbox + approval actions with shipped-shape payload codec, Android approval notices with publication-tokened dismissal. Native i18n inventory regenerated. (cherry picked from commit 428a76670ffeede54248b7bd7aa4438e2589851b) (cherry picked from commit 80225d5707c3645eeea5435f266131037b50ede6) (cherry picked from commit 2a23b714dc30d773a294aa45adc617e46b80732e) (cherry picked from commit 9ff1153827769e2cbab7c11c153f0f8634662c28) (cherry picked from commit 5b25723525bd562e5f97478af492f7b46ad30fd1) (cherry picked from commit 8c80e8467b5fe89aad0d4c74a0573f1600ed3af9) (cherry picked from commit ad4037bc9846bf6f082b41c129ee68aa344576c3) (cherry picked from commit fdf767dd662cff3c8a5a6d571f38f153410651ca) (cherry picked from commit 00c120376ffd992ea68ce29254a9bc0a25ed1740) (cherry picked from commit f36a952) (cherry picked from commit e2c25cbe2baacab44d21871d8cb6734704f065ac) (cherry picked from commit 7c4fda519080486d341a9f4df36d63f9e24b1235) (cherry picked from commit 1b3d4eda3dc5988012124597f9454ae21fb187a1) (cherry picked from commit 2a60619) (cherry picked from commit 6f0c386) (cherry picked from commit 784a585)
784a585 to
cbf294e
Compare
Squash-rebased #103912 segment onto the deep-links tip on current main. Native approval surfaces: iOS approval presentation with gateway-switch lease preservation and resolution fencing, watchOS inbox + approval actions with shipped-shape payload codec, Android approval notices with publication-tokened dismissal. Native i18n inventory regenerated. (cherry picked from commit 428a76670ffeede54248b7bd7aa4438e2589851b) (cherry picked from commit 80225d5707c3645eeea5435f266131037b50ede6) (cherry picked from commit 2a23b714dc30d773a294aa45adc617e46b80732e) (cherry picked from commit 9ff1153827769e2cbab7c11c153f0f8634662c28) (cherry picked from commit 5b25723525bd562e5f97478af492f7b46ad30fd1) (cherry picked from commit 8c80e8467b5fe89aad0d4c74a0573f1600ed3af9) (cherry picked from commit ad4037bc9846bf6f082b41c129ee68aa344576c3) (cherry picked from commit fdf767dd662cff3c8a5a6d571f38f153410651ca) (cherry picked from commit 00c120376ffd992ea68ce29254a9bc0a25ed1740) (cherry picked from commit f36a952) (cherry picked from commit e2c25cbe2baacab44d21871d8cb6734704f065ac) (cherry picked from commit 7c4fda519080486d341a9f4df36d63f9e24b1235) (cherry picked from commit 1b3d4eda3dc5988012124597f9454ae21fb187a1) (cherry picked from commit 2a60619) (cherry picked from commit 6f0c386) (cherry picked from commit 784a585) (cherry picked from commit cbf294e)
cbf294e to
175b049
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 175b049a88
ℹ️ 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".
| { | ||
| guard self.isExecApprovalPromptCurrent(prompt), | ||
| let inboxKey = Self.execApprovalInboxKey(prompt), | ||
| !self.terminalExecApprovalKeys.contains(inboxKey) |
There was a problem hiding this comment.
Clear terminal tombstones on same-id re-requests
When a gateway restarts or otherwise re-requests an approval with the same id after a terminal result, markExecApprovalOwnerTerminal leaves this owner key in terminalExecApprovalKeys until a gateway switch or tombstone eviction. A fresh pending approval.get then reaches this guard and is dropped instead of being shown or re-added to the inbox/watch cache, so the user cannot review the replacement approval; the Android side explicitly tests this same-id re-request flow. Clear or replace the tombstone when a new pending snapshot/event for the same owner arrives.
Useful? React with 👍 / 👎.
Related: #103505
What Problem This Solves
Operators using the Android, iPhone, or Apple Watch apps cannot reliably review the same Gateway approval that is visible in the Control UI or a chat channel. Lost acknowledgements can leave a native card looking actionable or resolved without canonical proof, and switching Gateways can misroute stale approval state.
Why This Change Was Made
This fourth stacked increment makes the official mobile clients read and resolve the durable Gateway approval record. Android and iPhone use the kind-aware unified RPCs, Watch relays reviewer-safe exec prompts through its paired iPhone, and every client treats Gateway terminal state as authoritative. Shipped Gateway v4 peers retain a narrow exec-method fallback; cross-surface retained terminal truth requires the unified methods.
The clients preserve approval and Gateway IDs as opaque exact identifiers, keep warning and owner context visible, bind credentials and cached prompts to the selected Gateway, and freeze actions after an ambiguous write until a canonical readback classifies the exact owner.
User Impact
Authorized operators can review pending exec approvals from Android, iPhone, or Apple Watch. The first answer from any authorized surface wins, every native surface displays that recorded result, and a lost response or reconnect cannot silently fabricate approval success or reopen execution rights.
Evidence
native-app-i18n.test.tspassed 5/5.