Repository navigation
fix: confirm fixed Paykit requests directly - #1014
ben-kaufman wants to merge 30 commits into
Conversation
|
Triage: milestone 3.1.0, the iOS twin of synonymdev/bitkit-android#1581. Fixed Paykit requests go straight to confirmation instead of a mostly disabled amount screen. It isn't a release blocker, and it closes no issue, so this PR carries the milestone itself. |
[Medium impact] The changes reach incoming Paykit request preparation and payment confirmation. The PR appears safe to merge, with a non-blocking issue where direct on-chain confirmation ignores the saved coin-selection algorithm. Findings
SummaryFixed quoted Bitcoin requests now bind their exact payment terms before opening confirmation, skipping the locked amount screen when no enabled USDT choice is offered.
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Resolve incoming request] --> B{USDT enabled and offered?}
B -->|Yes| C[Choose asset and review amount]
B -->|No| D[Bind exact Bitcoin terms]
C --> E[Confirmation]
D --> E
E --> F[Wait for wallet readiness]
F --> G[Review fee and approve]
G --> H[Recheck request and send]
Reviews (1) · Last reviewed commit: "fix: confirm fixed Paykit requests direc..." · Reviewed by Greptile |
talosmachina
left a comment
There was a problem hiding this comment.
1 finding (1 P2). Opens a fixed-quoted Bitcoin Paykit request straight on Confirm by preparing the payment terms during scan handling. Reviewed 72d89f3, full tier, reasoned from the code and CI (iOS does not build here).
What I checked, and 3 candidates I ruled out
Read in full: handleScannedData (asset-selection branch), PaymentNavigationHelper.openPaymentSheet / appropriateSendRoute / contactPaymentRoute, PaykitRequestPricing.payment(requested:endpoint:period:at:quoteId:), the incoming-request preparation block in AppScene.swift, SendSheet.shouldShowSyncOverlay and the post-setup validation
Call sites traced: every handleScannedData(_, claimedContactPaymentContext:) caller (AppScene, SubscriptionsView, SendSheet retry, SendContactSelectView, AddContactView, PaymentNavigationHelper)
CI: validate, detect-changes and Greptile green. Run Tests, Integration Tests and build-local were still pending when I reviewed.
Ruled out
- Sync overlay bypassed on Confirm:
shouldShowSyncOverlaynow exempts asset selection only whilecurrentRoot == .amount, so Confirm waits for the node. The renamedtestBelowMinimumQuotedRequestWaitsForSyncBeforeFallbackasserts that. - Stale terms after a wallet switch: the send path rechecks
terms == app.paykitPaymentTermsandisValidbefore paying (SendConfirmationView.swift:1688), andresetSendStateclears both fields (asserted in the new test). - USDT-capable requests losing the asset picker: the block is gated on
!canSelectUsdt, andtestDollarRequestOffersAssetSelectionOnlyWhenUsdtIsEnabledcovers both settings.
Merge confidence: 4/5, one P2 on a narrow path, and the test suites had not finished at review time.
jvsena42
left a comment
There was a problem hiding this comment.
Requesting changes: one MEDIUM (Back from the manual coin picker), inline with a failing test.
Checked and clean:
contactPaymentRoutemaps.quickpayand.amountto Confirm for incoming requests, so QuickPay can't auto-pay a request whose terms are now bound.- Scanner and Enter Manually call
appropriateSendRoutewithout a claimed context, so the terms branch never runs there. - Converted initial subscriptions stay manual (
conversion == nil). returnToAmountReviewIfNeededre-validates terms on a wallet switch.- The rate-unavailable case is fixed by 963d810.
The android twin synonymdev/bitkit-android#1581 prepares coin selection at swipe, so this shape is absent there.
fixed-quoted-confirmation.xml is byte-identical to Android.
Device gate: not run (MEDIUM open).
|
@ovitrif Fixed the Spending/Savings switch in 6c79bae. Already-reviewed Bitcoin requests stay on Confirm with the selected rail’s exact quoted amount, refreshed fees and a required swipe. Missing/expired terms and amounts below the Lightning minimum return to Amount; BTC/USDT selection and hardware safeguards remain. The hosted test switches between 2,500 and 5,000 sats and verifies fee preparation, with separate fallback cases. The journey now matches Android and also covers Back from manual coin selection. All 47 focused tests pass; SwiftFormat and translation validation passed with no introduced diagnostics. |
jvsena42
left a comment
There was a problem hiding this comment.
The MEDIUM is fixed at 6c79bae6. Back from the manual coin picker now stays on Confirm, and manual selection still runs before paying. I resolved the thread.
Wallet-switch rebind in the same commit, clean:
- It needs USDT off, no hardware wallet, not submitting, the previous BTC terms equal to
paykitReviewedAmount, valid new terms andmeetsMinimum. - It sets
paykitPaymentTerms,paykitReviewedAmountandsendAmountSatstogether. acceptsPaymentAmountandacceptsLightningInvoiceAmountstill re-check at pay time.- Unavailable or expired terms, or an amount below the minimum, return to Amount.
fixed-quoted-confirmation.xml is byte-identical to synonymdev/bitkit-android#1581.
Device gate (partial): not run yet. Pending: payment-requests/fixed-quoted-confirmation.xml, cross-device with synonymdev/bitkit-android#1581, plus Back from the manual coin picker on device. Code scan: no HIGH/MEDIUM open. The approval follows the device run.
|
@ben-kaufman thanks, rechecked at 6c79bae. On a Spending ↔ Savings switch, |
|
Fixed the Xcode 16.4 type-checking failure in The custom-fee lifecycle test also now allows SwiftUI to cancel and restart preparation during navigation. It still requires exactly one successful preparation, rejects cancelled results, and checks the final manual-UTXO or confirmation route. Validation: local simulator build and all 50 confirmation, swipe, lifecycle and pricing tests passed; SwiftFormat passed on all eight PR Swift files. Translation validation has no errors and no added warnings compared with master. Every PR commit verifies locally and on GitHub. Local validation used Xcode 27; the Xcode 16.4 CI rerun is pending. The cross-device journey remains a separate reviewer device gate. |
|
The hosted Xcode 16.4 compiler still timed out on the remaining confirmation modifier chain. In 05beeb5 I split that expression into smaller private computed views. Inlining them reproduces the original expression byte-for-byte, preserving task IDs, modifier order, state and payment safeguards. All 50 focused confirmation, lifecycle and pricing tests pass locally. SwiftFormat is clean for all eight changed Swift files; full translation/compiler diagnostics contain no findings introduced by this fix. Independent review is clean, and all six PR commits are verified. Reviews are re-requested; the new hosted CI run still needs to confirm the Xcode 16.4 build. |
jvsena42
left a comment
There was a problem hiding this comment.
The delta since my last review, b58c196, is clean. It only moves code: confirmationContent → confirmationLayout with the same modifier chain in the same order, so payment and authorization behaviour is unchanged. The testCustomFeeWalletSwitchSurvivesFeeScreenNavigation relaxation (successfulCoinPreparations == 1) is safe, because cancelled preparations throw before they assign anything.
CI is red because of this change, so I'm holding the approval. Unit tests on Xcode 16.4 (run 39308712256) still stop at the compiler is unable to type-check this expression in reasonable time, now at confirmationLayout (SendConfirmationView.swift:393), so no test ran. The ~15-modifier chain is still one expression. Splitting the onChange/.task group into its own computed property or a ViewModifier should get it under the limit.
Device gate (partial): not run yet. Pending: payment-requests/fixed-quoted-confirmation.xml cross-device with synonymdev/bitkit-android#1581, and Back from the manual coin picker.
|
@jvsena42 The latest commit |
Preserve actor-isolated backup subscriptions and writer-drain tracking while integrating stale-start and scheduled-backup generation guards.
|
Resolved the new master conflict in The exact combined tree The previous |
|
QA for c915e10: 🟢 Below-minimum Savings quotes stay on Amount; 547 confirmsBelow-minimum Savings quotes stay on Amount; 547 confirms A Savings-only $2.50 request quoted at 546 sats opened Amount with Continue disabled. The sheet was still open 18 seconds after setup, and Back closed it. A request also offering a 600,000-sat BOLT11 invoice, which Spending could not pay, opened Amount with Savings selected at 546 sats and Continue disabled, and stayed open the same way. A Savings-only quote of exactly 547 sats opened directly on Confirm. It was closed without paying.
🟢 Back after a coin-preparation failure closes the sheetBack after a coin-preparation failure closes the sheet A Savings-only quote for 1,049,900 sats, which the 1,049,999-sat balance covers but not with its fee, opened Confirm. Automatic coin selection then failed ("Coin selection failed" in the app log), and the sheet fell back to Amount. One tap on the header Back closed the sheet without reopening Amount. Reopening the unpaid request repeated the same fallback once, and Back closed it again. The issuer's address received nothing.
🟢 Fixed Savings request pays from ConfirmFixed Savings request pays from Confirm A fixed $2.50 Savings-only request opened straight to Confirm at ₿100,000 with no Amount step. The swipe paid it, and the issuer's address received exactly 0.001 BTC.
🟢 Switch between Spending and Savings, pay over LightningSwitch between Spending and Savings, pay over Lightning A request accepting BOLT11 Spending and Savings opened directly on Confirm at ₿2,500 Spending. Switching to Savings stayed on Confirm with ₿100,000, and switching back restored ₿2,500. The swipe settled the issuer's 2,500-sat invoice.
🟢 Back from below-minimum Savings after a switch, reopenBack from below-minimum Savings after a switch, reopen Switching from the ₿2,500 Spending Confirm to the 546-sat Savings quote opened Amount with Continue disabled. Header Back closed the sheet without reopening Amount. Reopening the unpaid request returned to Confirm at ₿2,500 Spending.
🟢 Backups resume after restartBackups resume after restart After these payments the app was relaunched. Balances were intact at ₿949,857 Savings and ₿497,500 Spending, and the wallet, activity and metadata backups each succeeded with no backup failures logged.
🟠 Interactive edge-swipe BackInteractive edge-swipe Back Not run: on the fallback Amount, a full drag from the left edge again started no native transition, so neither a cancelled nor a completed pop could be shown. The attempt is in the fallback Back recording above. Device tests skipped
|
There was a problem hiding this comment.
Verdict: ⛔️ Request changes — a queued stop can discard a newer backup start and leave wallet changes unobserved.
Findings:
- MEDIUM — Preserve the newer backup start.
Bitkit/Services/BackupService.swift:291: a start requested while an older stop is queued captures the old foreground generation. The stop increments it, so the newer start is rejected and observation stays off. This regression arrived through the master merge.
QA for c915e10: Built with Xcode 27.0 and tested on an iPhone 17 Pro simulator running iOS 26.5, using disposable identities, Bitcoin regtest and an isolated USDT fixture. No payment was authorized. Videos play at 2×.
Newer backup restart survives a queued stop ❌ A controlled XCTest left observation disabled and missed the next wallet-change notification.
The test holds Bitkit.ServiceQueue while requesting stop, then restart. The inverse ordering passed. Both diagnostics passed when only BackupService was replaced with its 0801b4f version. The recordings show the hosted app; XCTest assertions and the captured generation/state establish the result. No ThreadSanitizer report occurred.
| Current implementation | Parent implementation control |
|---|---|
gated-restart.2x.mp4 |
parent-control.2x.mp4 |
Queued lifecycle diagnostics.
Backup observation survives cancellation and restart ✅ The existing foreground-recovery regressions passed under ThreadSanitizer.
XCTest assertions cover upload-drain change capture, preservation of restarted listeners and repeated observation restart. These controlled checks do not cover the failing queued-stop ordering above.
backup.2x.mp4
Hosted sanitizer regression run.
Fixed request confirmation survives the master merge ✅ The linked fixed request confirmed at 5,000 sats with a 143-sat fee and reopened unpaid.
The request was for 2.50 USD; preparation opened Confirm directly. Show Details displayed the fee. Closing and reopening preserved the quoted amount, with the swipe still required.
confirmation.2x.mp4
Fixed Savings confirmation, details and reopening.
Unfunded USDT wallet can disable payments ✅ Settings switched USDT off and on, including disabling it after the wallet displayed $0.00.
Accessibility snapshots verified the switch value and enabled state. This fresh fixture result does not establish the cause of the earlier displayed-zero report.
usdt-toggle.2x.mp4
USDT setting changes and the unfunded wallet.
Interactive Back from fallback Amount ⏭️ Short, full-width and preset edge drags did not initiate a visible native pop.
The real coin-selection failure returned the 699,819-sat quote to Amount. A mid-drag capture and accessibility snapshots also left it unchanged, so neither cancellation nor completion is verified. Header Back closed the sheet and the unpaid request reopened at the same amount. The clip repeats those controls; no gesture defect is established.
native-back.2x.mp4
Edge-drag attempts, header Back and reopening.
Earlier passing evidence is retained for implementations this delta leaves unchanged:
- Minimum routing, manual coin fees and failure/header-Back checks.
- Locale and USDT preparing/locked-Amount checks.
- Request/subscription editing, serialized amounts and exact USDT/bridge review.
- One-micro request and six-decimal subscription display.
- Direct decimal entry and quote-error retention.
- Saved automatic selection and preparation cancellation.
- Manual Bitcoin settlement, insufficient funds and expiry/fresh terms.
- App-lock restoration and fresh payment authorization.
Reviewed the contiguous 0801b4f..c915e10 delta, all 24 changed files, reached callers and previous open checks. The imported master changes also received source review, and the CI helper tests passed. No native channel-close journey, physical signing/biometric check, production-provider USDT settlement or protected recovery-fixture run is claimed. Full J1/J2 completion remains unclaimed.
Twin: bitkit-android#1581 fix: confirm fixed Paykit requests directly matches direct Bitcoin confirmation. The later bitkit-android#1638 fix: keep fixed paykit requests on confirmation with an asset switch extends confirmation to USDT; iOS retains Amount for USDT and mixed LNURL/Savings selection.
Reviewed by gpt-6.1-sol-high
|
@ben-kaufman e2e on c915e10 fails Once synonymdev/bitkit-e2e-tests#288 merges, re-running e2e here should clear it. No change is needed in this PR. |
Register start/stop requests synchronously and reject stale queued transitions. Preserve writer-drain completion even when a newer request supersedes a stop. Cover queued stop/start ordering, repeated starts and held-writer stop completion.
|
Published 8aabaf77 for the queued backup stop/restart finding. Invocation order is now preserved without dropping the writer-drain contract or a newer listener. The addressed inline thread contains the implementation and negative-control evidence. Final local validation on tree Ovi’s simulator c915 QA remains attributed to that revision; it adds real regtest payment and automatic-fallback evidence, while native interactive Back and the stated missing cases remain unproven. New-head CI is pending. Parent unit/UI passed Ovi’s second workflow attempt after the camera-alert failure; the first result remains retained. Parent integration passed 30 cases. Parent E2E failed the inherited Connections-to-HeaderMenu expectation in all three built-in steps; multi-address notification failed once before recovery. The existing external harness #288 correction matches the inspected failure and Ovi’s latest comment. No production workaround, duplicate harness change or owner CI retry was made. Owned-head E2E validation remains required after that dependency is available. Existing Piotr/Ovi requests are preserved; João’s deferral is unchanged. No human approval or complete J1/J2, protected-fixture, native interactive Back, production-provider or physical-signing acceptance is implied. QA attribution correction (October 29): the linked c915 report explicitly used an iPhone 17 Pro simulator on iOS 27.0. Physical-device coverage remains unverified. |
There was a problem hiding this comment.
Verdict:
Findings: None in this delta. The queued backup restart finding is fixed at 8aabaf7.
QA for 8aabaf7: Built this exact head with Xcode 27.0 and tested an iPhone 17 Pro simulator on iOS 26.5. Backup checks used controlled uploads under ThreadSanitizer; the linked-request check used disposable identities and Bitcoin regtest. No payment was authorized. Videos play at 2×.
Backup observation honors the latest lifecycle request ✅ XCTest assertions passed for both queued request orders, repeated starts and a superseded stop waiting for an active upload.
A newer start preserves wallet-change observation after a queued stop; a newer stop rejects an older queued start. The held-upload assertion confirms that the superseded stop does not finish before its writer drains. No sanitizer report occurred. The video shows the hosted app; assertions establish these states.
backup-ordering.2x.mp4
Recorded lifecycle-ordering diagnostics.
Backup cancellation preserves pending changes and restarted listeners ✅ The existing foreground-recovery regressions passed under ThreadSanitizer.
Assertions cover change capture while an upload drains, preservation of newer listeners, repeated observation restart and pending-backup recovery. No sanitizer report occurred. The recording shows the hosted app; assertions establish the result.
backup-recovery.2x.mp4
Recorded recovery regressions.
Interactive Back from fallback Amount ⏭️ Short, full-width and preset edge gestures did not establish a cancelled or completed native pop.
Real coin preparation failed for the 699,819-sat quote against 700,000 sats and returned to Amount. Fresh screenshots and accessibility snapshots retained Amount after the edge drags. Header Back closed the sheet, and the same unpaid request reopened at its quoted amount.
The focused replay contains blank early frames that fresh screen captures did not reproduce; those frames establish neither an app defect nor successful native navigation. This case remains unverified.
| Initial gesture attempts | Repeated gestures, header Back and reopening |
|---|---|
interactive-initial.2x.mp4 |
interactive-back.2x.mp4 |
Native Back attempts and the header control.
Fresh screen capture after the full edge drag still shows Amount.
Earlier passing evidence remains applicable to payment implementations unchanged by this delta:
- Previous exact-head review: direct confirmation, unpaid reopening and the unfunded USDT toggle; its failed backup ordering is rerun above.
- Minimum routing and preparation-failure review: Savings/LNURL boundaries, automatic/manual failure controls, manual fees and header Back.
- Request and subscription review: editing, serialized values, exact USDT/bridge review and accepted methods.
- Locale and USDT preparation review: Classic Bitcoin decimals, USD trailing separators and locked USDT Amount.
- Linked regtest payment report: manual Bitcoin settlement, insufficient Savings and expiry followed by fresh terms.
- Saved-selection and cancellation review: automatic selection and cancellation during preparation.
Reviewed the contiguous c915e10..8aabaf7 delta: all three changed files and reached lifecycle, writer, scheduling and wipe callers, plus the prior open finding. The backup behavior received controlled runtime coverage; no full recovery, production-provider USDT settlement or physical signing/biometric case was driven. Full J1/J2 completion remains unclaimed.
Twin: bitkit-android#1581 fix: confirm fixed Paykit requests directly matches direct Bitcoin confirmation. The later bitkit-android#1638 fix: keep fixed paykit requests on confirmation with an asset switch also keeps USDT asset choice on confirmation; iOS retains Amount for USDT and mixed LNURL/Savings selection.
Reviewed by gpt-6.1-sol-high
|
QA for 8aabaf7: 🟢 Backups resume after restart and follow a paymentBackups resume after restart and follow a payment The app was relaunched, and backup observation started again. A fixed Savings request then paid exactly 0.0005 BTC. The wallet, activity and metadata backups that followed each succeeded, with no backup failures logged.
🟢 Fixed Savings request pays from ConfirmFixed Savings request pays from Confirm A fixed $2.50 Savings-only request opened straight to Confirm at ₿100,000. The swipe paid it, and the issuer's address received exactly 0.001 BTC.
🟢 Back from below-minimum Savings after a switch, reopenBack from below-minimum Savings after a switch, reopen Switching from the ₿2,500 Spending Confirm to the 546-sat Savings quote opened Amount with Continue disabled. Header Back closed the sheet without reopening Amount. Reopening the unpaid request returned to Confirm at ₿2,500 Spending.
Device tests skipped
|
|
Audited E2E run 40949848203 for All three failure screenshots and sampled video endings remain on Lightning Connections after channel closure. The executed harness All job logs, both artifact digests, three simulator logs, screenshots and sampled videos were inspected. Checkout Unit/UI, integration and formatting results remain as recorded. Native interactive Back, full J1/J2 and protected-fixture/provider/physical acceptance limits and human-review requirements remain open. |
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Scope: full reassessment of the complete PR diff at 06d3bd2b against merge base b23f305a, because the comparison base changed and no usable baseline coverage was supplied. No coverage was inherited.
Code review completed with unverified earlier concerns.
Validation: source inspection of production callers, regression assertions and cross-platform/protocol contracts; git diff --check and parsing all three changed journey XML files passed. Swift/Xcode is unavailable here, so the app and XCTest suites were not run. The pinned unit, integration and E2E runs were still in progress when checked.
J1/J2 remain runtime validation work, including native interactive Back, funded two-wallet quotes and fixture-provided six-decimal USDT terms. Device testing: not performed in this review.
Suggested additional test cases
- iOS, disposable wallet and controlled VSS connection: interrupt a backup upload, stop/restart the node, change backed-up wallet data, then restore connectivity. Verify the latest data reaches backup and survives a sequential restore.
Earlier findings reconciled at this revision: 1 still present, 14 verified fixed, 1 not substantiated, 11 could not be verified.
Reconciliation incomplete: the following earlier concerns remain unverified. This report does not establish that they are fixed or invalid, or establish approval or device readiness.
Could not verify earlier concern — USDT toggle reportedly cannot be disabled at displayed zero balance: The original report still lacks its active guard state. A later reviewer reports successful toggling with a fresh unfunded fixture at c915e10, explicitly without establishing the original cause. Current guards match the supplied base, but unchanged code and another fixture do not disprove the symptom or establish introduction. Code-only execution cannot settle the missing runtime state.
Could not verify earlier concern — Native interactive fallback Back remains unverified: Source handles committed navigation changes but cannot establish cancelled/completed native interactive transitions. Latest attributed tests still report gestures that never started a visible transition. This establishes neither a product defect nor a native Back pass. Device execution was prohibited.
Could not verify earlier concern — Camera-permission CI failure has no established cause: The permission-alert failure has no established cause. Later success does not prove a permanent fix; a newer report also records another first-attempt camera failure. The pinned unit run remains in progress, and local Swift/Xcode reproduction is unavailable.
Could not verify earlier concern — Remaining provider and physical-hardware acceptance is incomplete: Full acceptance remains incomplete. Attributed Bitcoin settlement, header Back and backup restart checks on older heads do not establish a current-head J1/J2 pass, production-provider USDT settlement, physical signing/biometrics or protected recovery-fixture coverage. Incoming USDT terms are intentionally locked; the journey correctly separates creator USD editing from fixture precision. Code-only execution cannot supply the missing evidence.
Could not verify earlier concern — Native interactive fallback Back remains unverified: This separately listed item remains unverified. Current source covers committed navigation changes, while latest attributed gestures establish neither cancellation nor completion of a native transition. Device execution was prohibited.
Could not verify earlier concern — Camera-permission CI failure has no established cause: This separately listed item retains an unproven cause. Success on another attempt does not establish a permanent fix or explain the earlier camera failure. Current-head CI remains pending and local runtime reproduction is unavailable.
Could not verify earlier concern — Remaining provider and physical-hardware acceptance is incomplete: This separately listed item remains an execution limitation. Older attributed payment and backup checks do not complete current-head J1/J2, provider settlement, physical signing/biometrics or protected recovery coverage. No device execution occurred.
Could not verify earlier concern — Historical launch and E2E retry failures have unresolved causes: Historical launch and RBF success-toast timeouts retain unproven causes. Later success/retries do not establish a fix. The separately corrected channel-close harness mismatch does not explain those timeouts, a transient notification failure or unattributed runtime diagnostics. Missing historical runtime state and unavailable local Xcode prevent resolution.
Could not verify earlier concern — Historical launch and E2E retry failures have unresolved causes: This separately listed item remains unresolved. Source corrections for identified races and the channel-close harness mismatch do not establish the causes of historical launch/RBF timeouts or other transient diagnostics. Current-head runtime validation is still pending.
Could not verify earlier concern — Historical launch and E2E retry failures have unresolved causes: This separately listed item remains unresolved. Later passes and retries do not explain the original launch/RBF failures. The external harness correction addresses another concrete mechanism. Code-only execution cannot recover the missing historical runtime state.
Could not verify earlier concern — Historical Xcode 16.4 confirmation type-check timeout: The modifier expression was split into smaller computed views and the author links a historical passing hosted build. This environment cannot independently type-check the pinned source, and its unit run remains in progress. The original failure is not asserted to persist; a current compiler pass is not invented.
Existing concerns
- [LOW] Align fixed-quote journey wording across platforms — still unresolved; already tracked.
Reviewer model: gpt-6.1-sol
Reasoning effort: high
|
Current-head validation update for 06d3bd2, including the changed comparison base:
Complete logs, artifact digests, all execution summaries and nested diagnostics were inspected. The 286 duplicate-symbol diagnostics/571 emissions remain. Unit retains two State warnings at the owned static test-builder boundary and 48 CoreGraphics NaN notices; neither is claimed base-existing, fixed or harmless. Symbolication limits, negative/recovery-case messages, integration runtime notices and the version-probe broken pipe remain disclosed. Current success does not establish causes or permanent fixes for historical camera, launch, backup-crash or E2E failures. E2E41021179435 is still running its first built-in test step on workflow attempt 1. Harness #288 has merged; its availability alone does not establish which revision this run executed or supply an E2E pass. No manual CI retry was requested. For review 5709560349: the LOW wording thread is resolved/outdated, with the existing explicit Android #1610/3.1.0 deferral. This is a documented deferral, not a claim that platform wording is now aligned. The suggested interrupted-upload/sequential-restore journey is not claimed covered by unit success. Native interactive Back, full J1/J2, protected recovery, provider USDT and physical signing/biometric acceptance remain incomplete. Previous Ovi/automated QA retains its original 8aab simulator/TSan attribution. This update supplies current compiler/test evidence; it does not turn the code-only review into device QA or human approval. |
There was a problem hiding this comment.
Verdict:
Reaudit: diff, 15 changed files and reached callers.
Findings: None.
QA for 06d3bd2:
Built this head with Xcode 27.0 and tested on an iPhone 17 Pro simulator running iOS 26.5. Payment checks used Bitcoin regtest and a staging request issuer; no payment was authorized. Videos are at 2× speed.
Inbox refresh respects payment review and wallet replacement ✅ Hosted assertions passed.
The XCTest result bundle confirms receive-before-observe ordering, background deferral during payment review, and cancellation/identity/wallet replacement handling. The video shows the test host; those assertions establish the result.
sdk-refresh.2x.mp4
Hosted refresh and activity regressions.
Failed request preparation refreshes safely and can recover ✅ Hosted assertions passed.
The XCTest result bundle confirms background deferral, forced snapshots, failed acceptance recovery and replacement identity handling without losing retry ownership.
request-refresh.2x.mp4
Hosted request-manager regressions; assertions establish the result.
Restored payment loading keeps the spinner in its knob ✅ The rendered control stayed centered.
The hosted rendering assertion and exported initial/restored screenshots confirm the spinner stays inside the loading knob after restoration, without starting authorization.
loading-spinner.2x.mp4
Hosted loading-control check.
Foreground requests preserve review and sheet ownership ✅ A second request did not replace the active review.
After foreground resume, the 21,000-sat confirmation retained its 143-sat fee while a 5,000-sat request arrived and payment PIN was cancelled. Receive stayed open while polling loaded the second request; closing Receive presented it. The pending rows retained distinct request IDs and amounts, and the first request reopened unpaid. An earlier 1,000/2,000-sat run also passed.
review-arrival.2x.mp4
Foreground arrival, PIN cancellation, competing Receive sheet and request reopening.
Interactive Back from fallback Amount ⏭️ Cancelled and completed native pops remain unverified.
A real coin-selection failure sent a fixed 699,819-sat quote to Amount with a 700,000-sat balance. Short, full-width and preset edge gestures did not establish either native transition. Header Back closed the sheet once and the unpaid request reopened with its quote. Geometry, mid-drag captures and accessibility state were checked; some video frames were blank while accessibility still reported Amount. Those frames establish neither a product failure nor a passing native gesture.
interactive-back.2x.mp4
Fallback Amount and attempted edge gestures; native cancellation/completion is still the QA gap.
Interrupted backups resume and restore the latest wallet data ✅ The production restore recovered the latest record.
App and transport traces confirm that real encrypted VSS writes were held and failed, the Lightning node stopped and restarted, and automatic backup then saved successive wallet-data changes. Decrypted reads through the real VSS client confirmed the newest marker. After clearing the local watch-only record, the production full-restore entry point restored that marker; the Server Accounts screen displayed it.
A local, unpublished action hook controlled timing and invoked the production operations. This used isolated VSS/auth services and a transport hold/503 fault, with production backup capture, encryption and restore. This establishes same-install sequential restoration of the test record; fresh-install, channel and USDT recovery were not driven.
| Backup interruption and recovery | Restored record |
|---|---|
backup-interruption.2x.mp4 |
![]() |
The recording shows the app during the fault/recovery check; traces establish the background operations, and the still shows the restored record afterward.
Earlier passing evidence retained for implementations this delta leaves unchanged:
- Previous backup ordering, recovery and sanitizer report at 8aabaf7.
- Amount boundaries, manual fees, real preparation failure and header Back.
- Request/subscription edits, serialization and USDT bridge checks.
- Locale and USDT preparation checks.
- Regtest settlement report.
- synonymdev/bitkit-ios#1066 proof-display deferral results, supplemented by the current integration assertions.
- synonymdev/bitkit-ios#1070 native progress and inbox results; the request service, Pubky service and spinner implementations match.
- synonymdev/bitkit-ios#1081 failure-recovery results; the request service and Pubky wrapper implementations match.
The delta review covers 8aabaf7..06d3bd2, including the new refresh integration and CI guard. The CI guard and journey-document changes were checked in code; full end-to-end journeys, physical biometric/hardware authorization and production USDT settlement were not rerun.
Pair PR synonymdev/bitkit-android#1581 matches direct confirmation for fixed Bitcoin requests. synonymdev/bitkit-android#1638 also moves USDT selection to confirmation; iOS retains Amount for USDT and mixed Lightning/Savings selection.
Reviewed by gpt-6.1-sol-high
|
Integrated actual master Final local validation on Xcode 26.1/iOS 26.5 passed 2,880 unit and 39 UI executions, with four explicit fixture skips and no failures or retries. Total: 2,923 executions, including 30 launch configurations; 2,894 unique cases include the four skips. The new pre-send backup/restore regression, all 16 backup lifecycle cases and camera case passed. The protected native USDT recovery class was excluded before fixture contact and remains unvalidated. SwiftFormat reports 0/824 violations, 100 skips; translations report zero errors and 15 warnings whose inputs match actual master. Complete structured, nested and runtime diagnostics were inspected. Retained: 21 structured QoS issues and one State issue, 22 raw QoS stacks, two raw State notices, 24 NaN notices, AppIntents metadata notices and symbolication limits. No introduced blocking finding was established; lower warning counts or passing tests do not establish a permanent fix for prior camera, launch, backup or runtime failures. The prior The existing native interactive Back, full J1/J2, fresh-install/channel/USDT recovery, provider and physical signing/biometric gaps remain explicit. Earlier human and automated QA keeps its reported revision and environment. Ovi's request and João's announced deferral through November 1 are preserved; Piotr's code-only review is not an approval. No merge or human-approval gate is claimed satisfied. |
|
Focused device evidence for A fixed 10,000-sat, Bitcoin/Savings-only payment request, Savings 0 sats, and a paired Trezor emulator with 1,000,000 sats reproduce both funding-selection concerns. Paykit enabled, USDT disabled. The issuer uses the existing
Expected: funding selection should settle before Savings coin preparation; a payable hardware request should remain on usable Confirm without the Savings failure toast, Amount detour or empty Savings picker. These observations need fixing or explaining before sign-off. Baseline runtime was not tested, so the evidence alone does not establish the first affected revision.
Automatic selection recording: hardware-auto-evidence.mp4Manual selection recording: hardware-manual.mp4Relevant runtime log: The final QA review will consolidate these results with the passing controls and remaining gaps. Logs from session: bitkit_logs_2026-10-30_12-23-07.zip |
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Focused device result: two failed hardware-funding checks; approval is not established. The insufficient-Savings/no-hardware control and controlled background/foreground backup recovery passed. Native interactive Back remains unverified.
Tested fc916488, base 04a0a1f8, on the existing iPhone 17 / iOS 26.0 simulator with its wallet preserved. Installed the current CI app, artifact 12969464148, Bitkit 3.0.1 (202). Verified synthetic merge c1cbd167 and PR head have the same tree, 0a462801. Local Docker regtest; no app source modifications or payment authorization.
Actionable runtime finding: Savings coin preparation races hardware funding selection
Reproduction, screenshots, recordings and log excerpt.
Setup: Paykit enabled, USDT disabled, a fixed 10,000-sat BTC/Savings-only request, 0 sats Savings, and a paired Trezor emulator funded with 1,000,000 sats.
- Autopilot / Branch and Bound — failed: Confirm briefly opens, then “Please try again — Insufficient funds” appears and navigation falls back to Amount. The Trezor subsequently becomes selected, showing 999,890 sats available. Continue reaches confirmation. Reopening reproduced the Amount detour.
- Manual — failed: opening the same request pushes an empty Savings Coin Selection screen: required 10,000, selected 0, Continue disabled. Header Back reaches confirmation. A funded hardware source should not require this Savings picker.
The automatic log records onSwitchToOnchainWallet failing Savings UTXO selection at SendConfirmationView.swift:1908, alongside SendSheet.selectHardwareFundingSourceIfNeeded at line 933. This is consistent with confirmation starting Savings preparation before asynchronous hardware selection settles. That ordering is the suspected mechanism; no base-build runtime comparison was performed. Fix or explain these observed failures and retest both modes before sign-off.
Fixture boundary: these are real linked fixed-BTC requests from the existing rc65-shared issuer fixture. They are not USD-conversion quotes. The exact USD-quoted variants and physical hardware signing remain untested; the fixed-BTC failures are independently reproducible controls, not claimed completion of J1.
Other focused results
- Insufficient Savings, no hardware — passed for fixed BTC: after removing the disposable Trezor association, opening the same request twice produced one “Insufficient Savings” message per open and closed the sheet. The request stayed available. No extra Amount detour or generic failure toast was observed in the recording.
- Header Back / reopen / no payment — passed controls: header Back closed the automatic coin-failure fallback without looping; manual-picker Back returned to confirmation. Balances stayed Savings 0 and Spending 500,498 sats. The issuer still recorded the test request as
Proposed, with no payment proofs. No signing or payment swipe was performed. - Backup during quick background/foreground — passed controlled recovery: used this build's existing E2E localhost VSS/auth endpoint overrides to delay backup transport. After observing a SETTINGS write in flight, changed Manual back to Autopilot, pressed Home, and tapped Bitkit's Home-screen icon to resume the same process. In the final eight-second-delay run, the SETTINGS request was held at 12:06:36.499 UTC; the second setting change began at 12:06:36.607, Home at 12:06:37.896, and resume completed at 12:06:42.797, before the held response completed at 12:06:44.662. Logs show the active SETTINGS backup succeeding, then another SETTINGS write succeeding for the later change. Data Backups showed Settings recently synced, with no stale failure banner. The transient “Required” label was not captured; pending work is evidenced by the subsequent write. An earlier launch-command attempt cold-restarted the app and is excluded from this foreground-resume result; a longer-delay run also exercised transport retries. These controls do not prove restore, wallet-switch or production-network acceptance.
- Native interactive Back — blocked/unverified: short and longer edge-swipe attempts from the genuine automatic coin-failure Amount fallback did not establish a native transition. Touch-down hit target/interactive callbacks were not established. Neither cancellation nor completion is a pass, and no native-gesture product defect is inferred.
Retained code assessment and CI reconciliation
The saved full code assessment at fc916488 against 04a0a1f8 is retained: quoted-term binding, confirmation routing/lifecycle, coin and fee preparation, payment-time validation, backup observer generations/callers and exact amount formatting were reviewed. This device update does not claim a new full source review or erase earlier unverified concerns. The runtime finding above supersedes the earlier summary's implication that the proposed hardware cases had no demonstrated failure.
- Current-head unit/UI and integration passed.
- E2E #288, harness
611509ee, fixes the Connections-to-HeaderMenu navigation mismatch. It does not explain the current E2E run's two Lightning failures waiting 30 seconds for~Channelto disappear after channel close and mining six blocks. That assertion is atlightning.e2e.ts:281, before #288's NavigationBack step. Lightning passed the third built-in test attempt on the same app/harness tree. This is an intermittent failure, not a proven permanent fix. - Failure screenshots/recordings were generated on the runner but not uploaded after the final pass; only the app artifact is available. App/backend/harness root cause remains unproven. Prior device evidence at 06d3bd2b keeps its original revision and limits.
- The LOW journey-wording difference is already deferred to Android #1610, with the original discussion resolved. It is not an additional payment defect here.
Remaining gaps, without duplicate historical entries
- Fix/explain and retest both hardware-funding failures above; repeat their exact USD-quoted variants with a compatible issuer.
- Demonstrate cancelled and completed native interactive Back transitions after coin-preparation failure.
- Complete the outstanding J1/J2, provider USDT settlement, physical signing/biometrics and protected fresh-install/channel/USDT recovery coverage. The Trezor emulator and backup transport controls close only their stated cases.
- Reproduce the displayed-zero USDT toggle report with active eligibility/guard state captured. Unchanged guards and a successful fresh-fixture toggle do not diagnose that report.
- On another channel-removal failure, retain failure artifacts and channel/node state. Historical camera, launch and RBF-toast failures keep their original evidence; current passes do not establish their causes or permanent fixes.
The saved full-code-review model metadata below identifies that retained assessment. Focused device execution and this evidence reconciliation were performed in Codex. This is a COMMENT review, not approval or complete device acceptance.
Reviewer model: claude-opus-5-5
Reasoning effort: high
|
Master comparison: both hardware-funding navigation failures are regressions in #1014; the generic “Please try again” toast is pre-existing. This updates the baseline-attribution limit in the focused review and original reproduction/evidence. Tested master
The logs distinguish the paths:
The likely common cause is Savings preparation starting before hardware fallback finishes: the new Keep the two navigation failures on this PR, with both modes required for retesting. Treat the generic initial fee-estimation toast separately as an existing issue. The other testing gaps in the focused review remain open. Limits: master was locally built from clean pinned source; #1014 used its original CI artifact, so these are not identical-toolchain builds. Dependency pins and |
There was a problem hiding this comment.
Verdict: ⛔️ Request changes — the reported hardware-funding failures remain unresolved; native interactive Back is still unverified.
Findings: No new findings in this delta. The current-head hardware-funding report remains actionable: automatic selection detours to Amount after Savings preparation fails, and manual selection opens an empty Savings picker despite a funded Trezor emulator. The subsequent master comparison reproduces both navigation regressions and separates the pre-existing generic toast. I checked the competing preparation paths in the source; I did not repeat those device cases or duplicate the finding inline.
QA for fc91648:
Built the pinned head with Xcode 27.0 and tested on an iPhone 17 Pro simulator running iOS 26.5. The linked-request check used Bitcoin regtest and a staging issuer. No payment was authorized. Videos play at 2×.
Restore a manual Lightning payment from its pre-send journal ✅ Hosted assertions reconcile the restored attempt as successful.
The exact-head XCTest run captures the journal before sending, restores it through the production backup conversion, supplies successful node history and verifies the recorded outcome. Related assertions preserve attempts while node history is unavailable and reject duplicate admission. The recording shows the test host; the result bundle establishes these states. Node history and the SDK are controlled test doubles, so this does not prove fresh-install or channel recovery.
recovery.2x.mp4
Hosted journal and recovery regression.
Interactive Back from fallback Amount ⏭️ Neither a cancelled nor a completed native transition was established.
Real coin selection failed for a fixed 699,819-sat quote against 700,000 sats, returning to Amount. Short, full-width and preset edge gestures left Amount visible; the mid-drag capture and accessibility snapshots did not establish a native transition. Header Back closed the sheet once, and the unpaid request reopened with the same quote, checked in accessibility snapshots. Logs establish the coin-selection failure. The issuer still reported Proposed with zero proofs. These attempts establish neither a native Back pass nor a new product defect.
interactive-back.2x.mp4
Edge-gesture attempts on the established fallback and the header Back control; reopening was checked separately in accessibility snapshots.
Retained evidence for behavior unchanged by this delta:
- Previous review at 06d3bd2: refresh ordering, loading spinner, incoming requests during review and interrupted backup/sequential restore.
- Minimums, manual fees and preparation-failure Back.
- Request/subscription editing, serialization and exact USDT/bridge review.
- Locale and USDT preparation.
- Earlier regtest settlement and expiry/fresh-term results; no new settlement is claimed here.
Reviewed the contiguous 06d3bd2..fc91648 delta, all four changed files and reached callers. The confirmation-to-journal hash forwarding was checked in code; the executor/restore behavior ran above. Physical signing/biometrics, production-provider USDT settlement and fresh-install/channel/USDT recovery were not driven. Full J1/J2 completion is not claimed.
Pair PR synonymdev/bitkit-android#1581 matches direct fixed-Bitcoin confirmation. synonymdev/bitkit-android#1638 also keeps USDT selection on confirmation; iOS retains Amount for USDT and mixed LNURL/Savings selection.
Reviewed by gpt-6.1-sol-high
Keep fixed and quoted request confirmation idle until initial or fallback funding selection settles. Preserve saved Savings selection and hardware preview behavior without premature Amount or empty UTXO navigation. Preserve upstream backup subscription and metadata ordering safeguards, including metadata upload drain for superseded observation stops.
|
Fixed the two hardware-funding navigation regressions from review 5712051079 in Confirmation now waits for initial/fallback funding selection before preparing Savings coins. When hardware is selected, it stays on Confirm and calculates the hardware preview; when Savings remains selected, its saved automatic/manual selection resumes. The existing amount, expiry, authorization and cancellation checks remain. The generic fee-unavailable toast reported on master is separate and unchanged. A new controlled confirmation test reproduced the premature preparation before the payment fix on the staged integration (one failing method, four automatic/manual × fixed/quoted cases). The repaired candidate passed all 60 focused tests, including that regression and extended Savings/backup cases. Final canonical validation passed 2,945 unit and 39 UI executions, with five documented skips, no failures and no whole-test retries/restarts; XCTest retried one tap inside a passing USDT receive case. Complete logs and structured/nested diagnostics inspected; 28 structured QoS and one existing State notice, 32 raw QoS stacks, 72 NaN notices, three AppIntents metadata warnings and symbolication/runtime/simulator limits remain disclosed. SwiftFormat 0.64 reports 0/827 violations and 102 skips; translations report zero errors and 15 warnings with localization, validator and warning callsites identical to actual master This signed normal merge also integrates master The new hardware test uses controlled wallet/signer doubles and performs no PIN authorization, signing or broadcast. It does not replace the full SendSheet hardware, native interactive Back, provider/funded or full J1/J2 journeys. Those acceptance gaps and historical CI failures/recoveries remain disclosed. João’s deferral through November 1 and Ovi’s pending request remain intact. |
There was a problem hiding this comment.
Verdict: ⛔️ Request changes — pending funding setup still allows payment authorization before coin and fee preparation.
Findings:
- MEDIUM — Block authorization until request setup finishes.
Bitkit/Views/Wallets/Send/SendConfirmationView.swift:420: the new wait suppresses preparation while the explicit swipe remains usable. A controlled real-swipe test reached the payment-PIN callback with setup pending and no selected coins. The explicit submission path can proceed with an unreviewed fee and default coin selection. No payment was sent.
The previous hardware-navigation failures are fixed in the live checks below, including the added USD-quoted variants.
QA for 659a7c0:
Built 659a7c0 with Xcode 27.0 and tested an iPhone 17 Pro simulator on iOS 26.5. Live requests used linked disposable identities and Bitcoin regtest. Savings started empty; the paired Trezor emulator held 599,441 sats. No signing or payment was authorized. Videos play at 2×.
Payment stays disabled while funding setup is pending ❌ A real swipe reached the payment-PIN callback before setup finished.
An unpublished XCTest hosts the production confirmation with pending setup, valid quoted terms, a loaded fee rate and automatic Largest First selection. The recording shows the swipe and missing displayed fee; assertions establish the callback and state. The helper returns false at PIN, so it cannot send a payment.
setup=true pinRequests=1 preparations=0 selectedCoins=nil
XCTAssertTrue failed: Pending funding setup reached payment authorization before coin/fee preparation
This uses a controlled wallet and does not claim a completed send.
pending-authorization.2x.mp4
Unpublished diagnostic patch
diff --git a/BitkitTests/SendConfirmationLifecycleTests.swift b/BitkitTests/SendConfirmationLifecycleTests.swift
index d444e63e..599bb59b 100644
--- a/BitkitTests/SendConfirmationLifecycleTests.swift
+++ b/BitkitTests/SendConfirmationLifecycleTests.swift
@@ -867,6 +867,47 @@ final class SendConfirmationLifecycleTests: XCTestCase {
XCTAssertTrue(isSubmittingPayment, "The original payment owns the retained submission flag")
}
+ func testPendingRequestSetupMustNotAuthorizeDiagnostic() async throws {
+ snapshotAppDefaultsDomain()
+ snapshotAppGroupDefaults("home_screen_display_currency_code_v1", "home_screen_display_currency_symbol_v1")
+ let request = try onchainRequest()
+ let wallet = ControlledSendWallet(operation: .selection)
+ wallet.totalOnchainSats = 700_000
+ let app = AppViewModel()
+ let sheets = SheetViewModel()
+ sheets.activeSheetConfiguration = SheetConfiguration(id: .send, data: nil)
+ app.scannedOnchainInvoice = invoice
+ app.selectedWalletToPayFrom = .onchain
+ app.contactPaymentContext = ContactPaymentContext(publicKey: request.counterparty, incomingPaymentRequest: request)
+ app.paykitPaymentTerms = try request.payment(using: app.paykitPaymentMethod)
+ app.paykitReviewedAmount = app.paykitPaymentTerms?.amount
+ wallet.sendAmountSats = app.paykitPaymentTerms?.amount.atomic
+ let settings = SettingsViewModel.shared
+ let previousPin = settings.pinEnabled
+ addTeardownBlock { @MainActor in settings.pinEnabled = previousPin }
+ settings.pinEnabled = true
+ settings.requirePinForPayments = true
+ settings.useBiometrics = false
+ settings.coinSelectionMethod = .autopilot
+ settings.coinSelectionAlgorithm = .largestFirst
+ let setup = SendConfirmationTestSetup()
+ let navigation = SendConfirmationTestNavigation()
+ navigation.path = []
+ let window = host(app: app, wallet: wallet, sheets: sheets,
+ path: Binding(get: { navigation.path }, set: { navigation.path = $0 }),
+ navigation: navigation, setup: setup, confirmationIsRoot: true)
+ defer { close(window); wallet.resume(); ToastWindowManager.shared.hideToast() }
+ try await navigation.waitForAppearance(.confirm)
+ wallet.selectedFeeRateSatsPerVByte = 2
+ print("V4_PENDING_READY setup=\(setup.isPending) preparations=\(wallet.preparationCount)")
+ let deadline = ContinuousClock.now + .seconds(100)
+ while setup.pinChecks.isEmpty, ContinuousClock.now < deadline {
+ try await Task.sleep(for: .milliseconds(100))
+ }
+ print("V4_PENDING_RESULT setup=\(setup.isPending) pinRequests=\(setup.pinChecks.count) preparations=\(wallet.preparationCount) selectedCoins=\(wallet.selectedUtxos == nil ? "nil" : "set")")
+ XCTAssertTrue(setup.pinChecks.isEmpty, "Pending funding setup reached payment authorization before coin/fee preparation")
+ }
+
private func host(
app: AppViewModel,
wallet: WalletViewModel,The existing host denies its PIN callback. Production payment guards are unchanged.
Request funding waits for setup ✅ Hosted assertions passed for fixed BTC/USD requests in both coin modes.
The existing hardware-readiness regression confirms no Savings preparation before setup settles, then hardware fee preview without a Savings picker. Wallet and signer doubles are used; the result bundle establishes the assertions.
setup-readiness.2x.mp4
Fixed Bitcoin request selects hardware automatically ✅ The 10,000-sat request opened and reopened directly on Confirm.
Accessibility snapshots confirmed Trezor funding and the 141-sat fee. No Amount detour occurred; the request remained unpaid. The clip is the focused reopen.
hw-btc-auto.2x.mp4
Manual fixed Bitcoin request selects hardware ✅ Manual mode kept hardware Confirm without an empty Savings picker.
The coin-mode setting and accessibility snapshots confirmed Manual, 10,000 sats, Trezor funding and the 141-sat fee. Closing and reopening preserved the unpaid request; the clip shows the focused reopen.
hw-btc-manual.2x.mp4
USD quote selects hardware automatically ✅ The fixed 2.50-USD quote reopened directly at 10,000 sats.
Issuer terms fixed the BTC amount. Accessibility snapshots confirmed the selected Trezor and its 141-sat fee; no Amount detour occurred.
hw-usd-auto.2x.mp4
Manual USD quote selects hardware ✅ The same quote reached hardware Confirm without a Savings picker.
Manual mode was checked in Settings; accessibility snapshots confirmed 10,000 sats and the 141-sat hardware fee. The request stayed unpaid.
hw-usd-manual.2x.mp4
Empty Savings without hardware fails safely ✅ Both openings showed Insufficient Savings and closed.
After removing the disposable hardware association, the same plain-BTC request stayed available. No Amount detour or payment was observed.
no-hardware.2x.mp4
Savings preparation respects automatic and manual coins ✅ Saved selection and manual Back preserved the reviewed fee.
With 500,000- and 200,000-sat outputs, logs confirm Largest First selected the larger output; accessibility showed a 143-sat fee. Manual-picker Back retained Confirm and another swipe required coins. Selecting both outputs produced 212 sats on the second Confirm and after returning through the picker to the original root, checked in accessibility snapshots. No payment was submitted.
| Automatic selection | Manual selection |
|---|---|
savings-auto.2x.mp4 |
savings-manual.2x.mp4 |
Merged backup and address safety regressions ✅ Current-composition backup assertions passed.
Foreground recovery, backup service and Android backup normalization ran at this head. These controlled tests cover the merged observer/metadata-drain composition; the recording shows the host and XCTest assertions establish the result. They do not prove fresh-install recovery.
backup-integration.2x.mp4
Interactive Back from preparation-failure Amount ⏭️ Neither native cancellation nor completion was established.
Real coin selection failed for a 699,819-sat quote against 700,000 sats. Preset and short/full coordinate edge drags left Amount visible in accessibility snapshots and did not establish a native transition. Header Back closed the sheet once, and the unpaid quote reopened. These attempts establish neither a native Back pass nor a new product defect.
native-back.2x.mp4
Physical authorization and complete recovery acceptance ⏭️ Physical signing, provider settlement and full recovery remain unverified.
This run used disposable simulator/regtest state and stopped before signing. Physical biometric/hardware acceptance, mainnet-provider USDT settlement and fresh-install/channel/USDT recovery were not driven. Earlier supported in-place restore reports retain their stated limits.
Earlier passing evidence retained for implementations this delta leaves unchanged:
- Request/subscription editing, serialization and exact USDT/bridge review.
- Locale and locked USDT preparation.
- Savings/LNURL minimums and preparation-failure controls.
- Refresh ordering, review ownership and interrupted backup/sequential restore.
- Imported public/private sharing, rotation and supported restore results. Relevant sharing implementations and dependency pins match; the backup composition was exercised above.
- Imported Android-to-iOS restore results. Normalization and settings writers match.
- Earlier regtest settlement; no new settlement is claimed here.
Reviewed the contiguous fc91648..659a7c0 delta, all 62 changed files and reached callers, including the imported master changes and prior open hardware report. CI artifact-retention changes and journey wording were checked in code. Full J1/J2 completion is not claimed.
Twin comparison:
- bitkit-android#1581 fix: confirm fixed Paykit requests directly matches direct fixed-Bitcoin confirmation.
- bitkit-android#1638 fix: keep fixed paykit requests on confirmation with an asset switch also retains USDT selection on Confirm; iOS retains Amount for USDT and mixed LNURL/Savings selection.
Reviewed by gpt-6.1-sol-high
jvsena42
left a comment
There was a problem hiding this comment.
Re-reviewed to 659a7c0. No new findings.
0801b4f8: a below-minimum initial quote stays unbound on an Amount root, and a coin-prep failure goes throughreturnToAmountReview(). Every Back and cancel path from that Amount screen ends either by hiding the sheet or on a Confirm whose terms equalwallet.sendAmountSats: header Back, edge swipe, Continue → Confirm → Back → Back, X, the Amount-root pop, and the funding tap.3d48ab10and8aabaf77: the backup observation lifecycle traces clean.- Merge
659a7c07: addsisRequestSetupPending, and takes master'sBackupObservationSubscriptionsin theBackupServiceconflict.
On ovi-reviewer's open MEDIUM at SendConfirmationView.swift:420 (the swipe isn't blocked while setup is pending): the fix should gate submitPayment itself. Once .pin is pushed, the setup-complete .task can no longer prepare coins, because confirmationContext needs path.last to be nil or .confirm.
Device gate (partial): 659a7c0, not run yet. fixed-quoted-confirmation.xml now has a new action 4, which renumbers the old 2–6 to 2, 3, 5, 6, 7.
- My 629a874 results for 5, 6 and 7 stand.
- 2 and 3 have to be re-run, because
659a7c07re-times preparation. - Still pending: 4 (Trezor), 8–11, 13 (LNURL minimum), 14 (fee-shortfall Back), and all of
paykit-quoted-usdt.xml. - 12 needs a conversion-capable issuer, so it is left to e2e CI.
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Scope: Full reassessment of the entire PR at 659a7c07 against merge base 3f14ea05, because the comparison base changed. No earlier coverage was inherited.
Code review completed with unverified earlier concerns.
Validation: Inspected hosted unit-test logs and integration logs for merge 03ec70c5, whose parents match these pins and whose tree equals the reviewed head. The affected regression tests passed; they do not exercise swiping during pending request setup. Local diff checks and parsing of all changed journey XML passed. Android and E2E comparisons were limited to the affected contracts at 6d99ad38 and 611509ee.
Device testing: not performed in this review. Local Swift/Xcode execution was unavailable; authored J1/J2 runtime acceptance and visual equivalence were not verified. Prior-findings reconciliation is deferred to the separate stage.
Suggested additional test cases
- iOS: with a running, funded Savings wallet, a fixed USD-to-BTC request, a non-default automatic coin algorithm and payment PIN disabled, hold the setup availability check after loading the fee rate. Attempt the confirmation swipe: no authorization or send should occur. Release setup and verify the saved coins and fee are prepared before the swipe enables; use a fee above 50% of the payment to verify its warning before sending.
Earlier findings reconciled at this revision: 1 still present, 14 verified fixed, 11 could not be verified.
Reconciliation incomplete: the following earlier concerns remain unverified. This report does not establish that they are fixed or invalid, or establish approval or device readiness.
Could not verify earlier concern — USDT toggle reportedly cannot be disabled at displayed zero balance: The original displayed-zero report still lacks its active eligibility state. Unchanged guards and the reported fresh-fixture success do not diagnose that state or disprove the symptom. Code-only execution cannot settle it; no introduction or fix is claimed.
Could not verify earlier concern — Native interactive fallback Back remains unverified: Committed navigation writes are handled, but current-head reports establish neither cancelled nor completed native interactive transitions. Failed gesture initiation proves neither a defect nor a pass. Device execution is prohibited here.
Could not verify earlier concern — Camera-permission CI failure has no established cause: The matching test passes on the pinned tree, but the historical failures retain an unproven cause. Current success does not establish a permanent fix, and code-only execution cannot recover the missing runtime state.
Could not verify earlier concern — Remaining provider and physical-hardware acceptance is incomplete: Current-head hardware fallback and backup reports narrow the gaps but do not complete J1/J2, provider settlement, physical authorization or full recovery. These remain execution limitations.
Could not verify earlier concern — Native interactive fallback Back remains unverified: This separately retained item remains unverified. Source covers committed path changes, while current reports establish neither native cancellation nor completion. Device execution is prohibited.
Could not verify earlier concern — Camera-permission CI failure has no established cause: This separately retained item still has no established cause. Passing current CI does not explain the historical camera failures or verify a permanent fix.
Could not verify earlier concern — Remaining provider and physical-hardware acceptance is incomplete: This separately retained item remains an execution limitation. Attributed hardware-emulator and controlled backup checks do not complete the outstanding journeys, provider settlement, physical authorization or recovery coverage.
Could not verify earlier concern — Historical launch and E2E retry failures have unresolved causes: Historical launch and RBF-toast timeouts retain unproven causes. Current successes and retry recovery do not establish permanent fixes. The channel-navigation harness correction addresses a separate mechanism.
Could not verify earlier concern — Historical launch and E2E retry failures have unresolved causes: This separately retained item remains unresolved. Later passes and the known harness correction do not recover the historical runtime state or establish the timeout causes.
Could not verify earlier concern — Historical launch and E2E retry failures have unresolved causes: This separately retained item remains unresolved. Code-only inspection and later successful executions do not explain the earlier launch, RBF-toast or transient runtime failures.
Could not verify earlier concern — Contact-payment preparation latency remains unmeasured: The PR retains the latency concern without claiming a current reproduction or fix. Diagnostic timing hooks do not establish actual latency. No staging timing run occurred here.
Existing concerns
- [MEDIUM] Disable request payment until setup and coin preparation finish — still unresolved; already tracked.
- [LOW] Align fixed-quote journey wording across platforms — still unresolved; already tracked.
Reviewer model: gpt-6.1-sol
Reasoning effort: xhigh
There was a problem hiding this comment.
Verdict:
Findings: None in this delta. The pending-setup authorization finding is fixed at 1607a10.
QA for 1607a10:
Built this head with Xcode 27.0 and tested an iPhone 17 Pro simulator on iOS 26.5. Live requests used linked disposable identities and Bitcoin regtest; USDT entry used an unfunded test wallet. No payment or subscription was authorized. Videos play at 2×.
Payment waits for request setup ✅ Swipes during held setup reached no authorization.
An unpublished diagnostic hosts the production confirmation with valid quoted terms, a loaded fee rate and controlled wallet/setup state. Real swipes with payment PIN enabled and disabled left preparation at zero and selected coins unset. XCTest assertions establish those states; the recording shows the disabled/loading control.
pending-setup.2x.mp4
Payment waits for selected coins and fee ✅ The held preparation blocked authorization; a ready swipe reached the denied PIN callback.
While automatic coin selection was suspended, a swipe reached no PIN. After release, assertions verified Largest First, selected coins and fee preparation before the positive-control swipes reached the deliberately denied PIN callback. The callback always returned false, so this diagnostic could not authorize a payment.
coin-preparation.2x.mp4
Prepared high fee warns before payment ✅ The 1,500-sat fee on a 2,500-sat request triggered the over-50% warning.
With payment PIN disabled, Show Details displayed the controlled fee. A real swipe opened the fee warning, and Cancel returned to confirmation without sending.
high-fee-warning.2x.mp4
Manual selection and funding setup regressions ✅ The committed lifecycle and swipe assertions passed.
The result bundles cover automatic/manual and fixed-BTC/USD hardware setup, manual-picker Back, cancellation, minimum fallbacks and fee recovery. The focused replay shown here exercises the hardware setup wait and pending swipe-state test; XCTest assertions establish the broader result.
confirmation-regressions-focused.2x.mp4
Fixed request prepares the saved Savings coins ✅ The fixed $2.50 request opened and reopened directly at 5,000 sats with a 143-sat fee.
Settings and the device log confirmed Largest First selected the 500,000-sat output from the funded Savings wallet. The displayed fiat equivalent used the wallet rate. The request remained unpaid; the clip shows its reopen and details.
live-confirmation-focused.2x.mp4
Request denomination and receiving-method controls ✅ The USD/BTC control preserved 150.50 USD and method selection behaved independently.
Full-resolution captures verified one dark filled orange denomination control with its swap icon, and available Savings/USDT chips below expiry. Deselecting Savings changed its X to a dimmed plus while USDT stayed selected. Removing all methods disabled Send Request. The initial selection is shown separately; translated wrapping retains the earlier passing report below.
| Denomination and selection | Initial receiving methods |
|---|---|
request-layout-focused.2x.mp4 |
![]() |
USDT request sent state preserves exact USD amount ✅ Sent, the outgoing card and details all showed 150.50 USD.
The linked peer stored numeric 150.5 usd, only usdt-arbitrum-address, and zero proofs. A new creator retained typed 10.00 USD, verified in its accessibility snapshot. The recording shows the outgoing card/details and new entry; the still shows Sent.
| Card, details and trailing zeros | Sent |
|---|---|
outgoing-request-focused.2x.mp4 |
![]() |
Subscription defaults and receiving-method layout ✅ Creation and incoming review preserved 150.50 USD with USDT selected.
USD/BTC round trips and editing retained the exact amount. The creator placed USDT-selected/Savings-unselected chips below frequency, with description and icon side by side. Its sent proposal and peer record preserved the numeric amount. A separate incoming monthly proposal showed 150.50 USD on its card and review, USDT-only methods and a teal subscribe control. It was closed without subscribing.
| Creator controls | Incoming recurrence and review |
|---|---|
subscription-create-focused.2x.mp4 |
subscription-incoming.2x.mp4 |
Private USDT amount matches direct Send layout ✅ Private entry offered only USDT and labeled the balance AVAILABLE.
The device log confirms a private payment list was opened. At 0.01 USDT, full-resolution captures verified matching shared amount, balance, chip, keypad and Continue typography and bottom layout against direct Send. No quote or payment was started.
private-usdt-layout-focused.2x.mp4
Interactive Back from fallback Amount ⏭️ Neither a cancelled nor a completed native transition was established.
Actual coin selection failed for a 699,819-sat quote against 700,000 sats and opened Amount. Short and full coordinate edge drags and the native gesture preset left Amount in place without an observable transition. Header Back closed the sheet. These attempts establish neither a native Back pass nor a new product defect.
native-back-focused.2x.mp4
Earlier passing evidence retained for implementations this three-file delta leaves unchanged:
- Hardware fallback, saved/manual selection and backup composition. Its failed pending-setup case is replaced by the current-head checks above.
- Savings/LNURL minimums and preparation-failure controls.
- Request/subscription serialization, exact USDT/bridge review and translated wrapping.
- Locale and locked USDT preparation.
- One-micro request and six-decimal subscription display.
- Refresh ownership and supported interrupted-backup/sequential restore.
- Earlier regtest settlement; no new settlement is claimed here.
Reviewed the contiguous 659a7c0..1607a10 delta, all three changed files and reached preparation, fee, authorization and cancellation callers, plus the prior open finding. The early setup-to-task submission guard was also checked in code. Native interactive Back remains the unrun journey subcase; full J1/J2 completion is not claimed. Physical authorization, provider USDT settlement and fresh-install recovery were not driven.
Twin comparison:
- synonymdev/bitkit-android#1581 fix: confirm fixed Paykit requests directly matches direct fixed-Bitcoin confirmation.
- synonymdev/bitkit-android#1638 fix: keep fixed paykit requests on confirmation with an asset switch also keeps USDT selection on Confirm; iOS retains Amount for USDT and mixed LNURL/Savings selection.
Reviewed by gpt-6.1-sol-high





Description
resolveMsandsetupMs) to separate endpoint resolution from subsequent setup without logging payment details.Out of Scope
Cross-platform fixed-quote journey wording and LNURL/Savings coverage: Align fixed-quote journeys with both payment flows bitkit-android#1610 (review thread). Android #1581 is already merged; the remaining gap is in the shared test instructions and platform notes.
Preparation latency (Contact payment latency on staging with the shared Paykit runtime: pin paykit-rs#171 and re-measure #868): the reported several-second delay has not been reproduced with timings. Endpoint resolution and fee/balance preparation are possible contributors; this PR does not claim to fix their latency.
Initial subscription authorization: this does not remove the extra review required for converted subscription terms.
Design
Reuses the existing send confirmation without changing its layout. Android's screen map identifies
Send (Paste) (On-chain) → Confirm Send Onchainin the Bitkit design file. The exact current frame node is unverified.Preview
Before: Preparing → Amount (locked) → Confirm.
After, when no separate funding choice is required: Preparing → Confirm. LNURL + Savings keeps its existing selection step.
Current validation — published
1607a10cPending setup blocks swipe/submission before authorization. An early post-setup swipe starts missing-coin preparation and cancels submission. J1 action 2 covers this; older journeys do not prove it.
Local
73f1b9a5: 2,945 unit + 39 UI passes, five fixture skips, zero failures; one recovered UI tap retry. 33 focused passes; two independent scoped reviews passed. SwiftFormat 0/827; translations zero errors/15 verified actual-base warnings. 30 current-base signatures valid locally/on GitHub.Earlier full run: exit 73 after 2,804 passes/one recovery skip, before UI. Disk exhaustion observed; cause unproven. Incomplete result and two diagnostics without a delivered swipe retained.
Prior
659a7c07: 2,984 hosted unit/UI passes/five skips; 30 integration passes; E2E 13 unique passes/14 executions after QRCode timeout/built-in recovery, one hardware skip. Failure visuals, warnings and unproven cause remain; no manual CI retry.Hosted
e36edc23/45e99e62combinesf3e97b08/1607a10c: formatting 0/828; translations zero errors/15 verified base warnings; unit/UI 2,992 passes/five skips; integration 30 passes/no skips. No failures/test retries. E2E: 13 eventual passes/14 executions after Boost toast-dismissal timeout/built-in recovery, one hardware skip; no manual CI retry. Local results on3f14ea05remain separate. Linker/runtime/fixture/State/NaN/QoS/frame/symbolication diagnostics and 85 reported harness findings (7 critical) remain; no base-runtime or warning-free claim.Automated QA at
1607a10reports held-setup/coin-selection blocked real swipes, ready swipes reached denied PIN, and high-fee Cancel returned safely. Earlier QA retains its revision. Native interactive Back, full J1/J2, physical/provider settlement and full recovery remain unverified. João deferred through Nov 1; zero current human approvals. Gates remain open.QA Notes
Setup
Use the existing fixed-quote journey prerequisites: two disposable identities, a fresh fixed $2.50 Bitcoin quote, funded regtest Savings and a usable Spending channel for live switching. For the minimum boundary, use controlled rates yielding exactly 546 and 547 Savings sats as specified in
journeys/paykit-quoted-usdt.xml. Owner validation remains unfunded; the linked reviewer-reported regtest payments retain their recorded revision and environment. For the added J1 hardware subcase, reuse an explicitly owned, already funded regtest hardware-emulator wallet with empty Savings; check automatic/manual selection for both fixed BTC and quoted requests, then close without signing or sending.The XCTest USDT fixture is separate:
UsdtWalletUITestsnow defaults to unavailable loopback endpoints. An explicitly owned disposable fork must be selected through test-runnerBITKIT_TEST_USDT_RPC_URL/BITKIT_TEST_USDT_BUNDLER_URL; its test funds its wallet.BITKIT_TEST_USDT_OFFLINE_RPC_URLmust be unavailable. Never use another task's shared fixture. Seejourneys/README.md.Journeys
J1: new
journeys/payment-requests/fixed-quoted-confirmation.xml— LNURL/Savings selection, quoted amount and wallet valuation, saved/manual coin selection and initial hardware fallback, cancel/reopen, delayed preparation, insufficient funds, expiry and BTC/USDT choice. Partial linked-regtest execution is reported in Ovi’s d181 QA, including payment, wallet switching, manual coins, header Back/reopen and expiry/fresh terms. Native interactive Back remains unverified; earlier LNURL evidence retains its original revision. Manual failure, plain-BTC failure and fresh-review controls retain their earlier programmatic evidence.J2: updated
journeys/paykit-quoted-usdt.xml— iOS dot-decimal checks in comma-region settings preserve exact values, cents, trailing zeros and six-decimal precision. Partial d5e reviewer QA covers six-decimal review, request/subscription serialization and the 546/547-sat boundary; full J2 is not claimed. Incoming fixed USDT terms stay locked: action17 now separately checks editable USD creator amounts and fixture-provided six-decimal USDT review. Android retains confirmation but disables authorization below its equivalent minimum.Manual Tests
N/A
Models used
For this repair and validation update (verified session metadata; earlier implementation attribution is not inferred):
gpt-6-astra(reasoning:xhigh)gpt-6-astra(reasoning:xhigh)gpt-6.1-sol(reasoning:high)Earlier validation, failures and diagnostic history
Exact USDT review amounts —
629a874e(October 28): Fixed the six-decimal display finding from review 5678141014. The actual payer confirmation header and Show Details payment, fee, recipient amount and maximum total now use the existing exact USDT formatter. Request/subscription amount text also preserves all six decimals. Quote values, serialized amounts and payment authorization are unchanged; balance overviews retain their established formatting.The rendered regression reproduced
$0.12/$<0.01for0.123456/0.000001before the fix (one failed test, ten assertions). All ten focused amount/display tests now pass. Saved native screenshots show exact headers, fee0.000001, and totals0.123457/0.000002. These tests host the real production review builders directly and verify static rendering; they bypass full view lifecycle/navigation/quote loading and do not authorize or send a payment. Their new SwiftUI constant-binding warning is retained as an explicit test boundary, not a production-race or warning-free claim.Final canonical local validation passed 2,934 unit and 39 UI executions, with four documented fixture skips and zero failures or retries. Complete diagnostics were inspected: two AppIntents warnings, ten structured QoS warnings plus the new static-builder State warning, eleven raw QoS backtraces, and 72 NaN notices remain explicitly retained alongside symbolication and simulator notices; this is not a warning-free claim. Full SwiftFormat 0.64.0: 0/846 files require formatting, 83 skipped. Translation validation: zero errors, 15 warnings matching the verified actual-base warning multiset. Two independent source perspectives covered the component and actual payer path; an initial component-only coverage gap was caught before publication and the actual payer regression added. Required source signatures: all 20 commits in the current-base PR range verified locally and matched the exact GitHub set with
verified=true/reason=valid. Validation applies to local PR tree88d9c2e3295b93490a3395510ed3605f1ce1b565, not a new combined master tree. Master68bede62added only disjoint profile journey documentation since the earlier base; no unrelated integration was performed.J1/J2 retain their IDs. Their six-decimal request case now explicitly needs fixture-provided USDT terms, because the iOS editor creates BTC/USD terms. Full linked-request, native Back, fresh-terms retry, provider/funded/hardware/settlement acceptance remains incomplete. No pending human request was recreated; João's announced absence through November 1 is preserved. Current work: implementation
gpt-6-astra/xhigh, scoped independent reviews and diagnostic auditgpt-6.1-sol/high, verified from execution metadata.Hosted checks for
629a874eare complete on workflow attempt 1: unit passed 2,960 unit and 39 UI executions, with four fixture skips and no failures; integration passed 30 tests once each, with four existing Blocktank staging skips. Verified checkouta52bbce2/ treeefec63fbcombines actual master68bede62with629a874e; this differs from local PR tree88d9c2e3. Complete logs, artifact digests, execution trees, case summaries and nested diagnostics were inspected. The payer display regression passed in 11.611 seconds. Its two introduced State/constant-Binding messages remain explicit: direct builder hosting proves static text, not the full view lifecycle or authorization flow. The 286 structured / 571 raw duplicate-symbol warnings match the verified prior warning multisets. Runtime/mock/fixture/tooling notices, symbolication limits, and two passing integration tests' internal sync/deposit recoveries remain recorded; no fresh-base runtime or warning-free claim.E2E ultimately passed 13 unique cases across 14 executions: 12 passed initially, while Lightning timed out after 30 seconds waiting for
ActivityShort-0to show9 000after restored-channel closure. The selective second built-in step passed Lightning; step 3 was skipped. One existing hardware-wallet case remained disabled. This was not a first-pass clean run or a manual retry. Failure screenshots/video were generated on the runner, but their upload was skipped after recovery; no downloadable failed visuals, device/app logs or runtime report were available. Root cause remains unproven, with no actual-base reproduction or permanent-fix claim. All five job logs, pinned harness4c0cbef0, cases and app-artifact provenance were inspected. The 76 stale-element notices, five log-stream restarts and pinned-harness dependency findings remain explicit. Formatter and translations were already inspected: 0/850 files needed formatting (87 skipped); zero translation errors and 15 verified base-matching warnings.Automated reviewer QA at this head reports exact six-decimal and one-micro request displays, a six-decimal subscription, and Savings-only proposal selection using linked test wallets and a local fixture, without authorization. This is reviewer-reported evidence, not an independent rerun or human approval. Neither edge gesture established an interactive Back transition; expiry removed the request before fresh-terms retry could be exercised. Editing/serialization, live bridge, provider, hardware and settlement gaps remain. No new delta defect was reported. Shared-navigation ownership coordination and the existing remaining acceptance gates are still required.
Current documentation correction —
9dacc089(October 28): Corrected stale J2 comma-decimal expectations to the existing iOS dot-decimal convention, including comma-region settings. All 19 actions and exact-value, trailing-zero, six-decimal and serialized-value checks remain. No app behavior changed. XML/action/reference checks,git diff --check, full SwiftFormat 0.64.0 (0/846), and one independent documentation review passed. All 19 current-base commits verify locally and on GitHub. App tests were not rerun for this documentation-only delta; earlier local/hosted results keep their original inputs. Automated review 5676643246 reports additional partial device evidence at20cfeffa, not human approval or independent execution by this monitor. Native Back, expiry retry and full J1/J2 acceptance remain incomplete. The former comma-expectation result is preserved as a failure of the earlier journey wording, not converted into a completed new journey run.Current repair —
20cfeffa(October 27): The initially-unreviewed Back assertion reported in automated review 5670593898 reproduced independently on unchangedb53e300ewith Xcode 27.1/iOS 26.5. The four-line fix observes Amount being popped to an empty navigation path and reuses the existing invalid-terms, presentation-owned dismissal guard. All 15 unchanged lifecycle tests now pass. No assertion or production payment guard was weakened; the journey also names interactive Back as an acceptance check.Final canonical validation on Xcode 26.1/iOS 26.1 passed 2,932 unit executions and 39 UI executions, four fixture skips, zero failures, including all 35 watch-only tests. Full SwiftFormat 0.64 passed (0/846; 83 exclusions); translations report zero errors and 15 warnings whose individual call/missing-language sets match actual master
543d9389. Complete structured/action/raw diagnostics and an independent frozen correctness/quality review were inspected. Eight aggregate QoS warning cases represent 19 warning-bearing executions; three raw Paykit/pubky initialization backtraces, two AppIntents build notices, simulator/negative-case/runtime messages and the unavailable-fork skip remain explicit. All 18 current-base commits verify locally and match GitHub's exactverified=true,reason=validset. Tested local PR tree:e286b0d9; the new hosted unit and integration results below cover the combined tree. No warning-free or fresh-master-runtime claim.Hosted checks at
20cfeffa: Unit 40559037614 and integration 40559037349 passed on workflow attempt 1. Unit: 2,953 unit + 39 UI executions passed, four fixture skips, zero failures, including all 15 confirmation lifecycle and 35 watch-only tests. The repaired initially-unreviewed Back regression passed. Integration: 30 unique passes in 30 executions, four existing Blocktank staging skips, zero failures or test-case reruns. Both checked out verified merged1ec3668(543d9389/20cfeffa), tree370b70b7, which differs from the local PR tree; 21 additional upstream unit cases account for the count difference. Full archive hashes, test trees, all UI/integration case summaries, build/action/runtime diagnostics and job logs were inspected. The three Trezor opt-in cases and isolated Arbitrum case remain skipped; integration retains the four staging skips.The 286 structured and 571 build-log duplicate-symbol warning multisets match the previously inspected hosted result. Runtime output still includes the keyboard queue timeout with
Last Exception Backtrace: No stack!, socket/haptic/launch notices, injected negative-case diagnostics, integration RGS/node/address-search/teardown messages and the version-probe broken-pipe exception. Associated source comparisons are retained; this is not a warning-free run or a fresh actual-base runtime reproduction. E2E 40559038210 also passed on workflow attempt 1: 13 unique passes in 13 executions, one existing hardware-transfer skip, zero failures. The first built-in test step passed; steps 2/3 were skipped. Build and runtime used the same verifiedd1ec3668/370b70b7combined tree. The executed harness was4c0cbef0(two commits beyond the previous harness), on iPhone 17/iOS 26.2. The exact pinned hardware spec retains its Blocktank-staging skip. All five full logs, case outcomes and artifact provenance were inspected. Artifact12761095558SHA-256b59616212d303b5441c1053ac883fbd32ba4af1593cb9c98e93c85816accc1a6matches API/upload/runner download; no local ZIP or runtime-report/video artifact was inspected. Retained diagnostics include 66 stale-element notices, four log-stream restarts, an address-type tap helper retry that reached its expected toast, Node/npm/tool/AppIntents notices and 76 pinned-harness dependency findings. No manual CI retry or warning-free claim. These hosted passes do not close the supplementary native gesture or other acceptance gaps below.Supplementary native check remains partial: an unpublished animated test host used real Amount with fixed-quote terms that were valid at a historical time and expired before appearance. Header Back closed the owned sheet state with an empty path and no preparation, authorization or submission. The first diagnostic execution failed an exclusive-visible-route readiness assumption and timed out before an edge gesture was delivered. One bounded rerun corrected only that temporary readiness check; actual Amount/path assertions passed, but two edge swipes did not pop Amount and the diagnostic timed out. Both failures and full diagnostics/screenshots are retained. The cause is unproven; completed/cancelled interactive Back, real linked-request setup, dismissal animation and reopening are not accepted by this check. Temporary test code was restored byte-for-byte before signing. No funds, payment, wallet reset or shared-fork access occurred. The repaired existing lifecycle regression is green; this additional gesture gap is not presented as a pass.
A later bounded prerequisite check on the same isolated iOS 26.5 simulator found two native controllers, an enabled recognizer,
allowSwipeBack=trueand a key window. The temporary host's 390×844 window differed from the 402×874 screen. After correcting only that host geometry and observing native transition state, one cancel-shaped edge drag and one full edge swipe both produced recognizerfailedstate before any interactive transition. The 100-second diagnostic ended with one failed case/four assertions: Amount/path and sheet state remained, no completed or cancelled pop occurred, and routing/preparation counts stayed zero. The geometry change did not resolve the gap; the reason for gesture rejection is still unproven, and no production defect or fix is inferred. Complete xcresults, action logs, state trace and screenshots are retained. Temporary code was restored byte-for-byte; published source remains20cfeffa. Further gesture acceptance needs the production sheet presentation to reach that boundary, rather than another unchanged synthetic-host retry.At
b53e300e, the bot reported rendered confirmation, saved/manual coin selection (143/212-sat fees), manual-picker Back, 546-sat fallback/Back/reopen, 547-sat confirmation, cancellation during preparation and LNURL/Savings selection, stopping before payment. Those remain reviewer-reported partial J1/J2 results at that head. Piotr's fee-refresh thread is externally resolved. On October 27, Ovi dismissed João's older changes request, noting its resolved threads and João's absence until November 1; this monitor did not dismiss it. Piotr/Ovi requests remain pending, João's comment retains assignment and his absence is respected, and there are zero current-head human approvals. A bot comment or resolved thread is not approval. Current shipped/provider/funded/physical-hardware/full-linked-request/two-wallet settlement acceptance remains incomplete.Earlier validation —
b53e300e(October 27): The conflict with then-current masterd2d9d28dis resolved in a signed normal merge, tested tree4516c8e1. Master's cache display and test-preference isolation changes are preserved; the USDT UI helper retains its explicit endpoint overrides and unavailable defaults. Final canonical validation passed 2,932 unit tests and 39 UI executions, four fixture skips, zero failures. The previously failing launch test passed locally, which does not establish the cause or a permanent fix for its earlier hosted timeout. Full SwiftFormat 0.64.0 passed (0/846); translations found zero errors and 15 warnings with all 20 inputs identical to actual master. Complete diagnostics and an independent frozen integration review were inspected. All 17 current-base commits verified locally and match GitHub's exact set withverified=true,reason=valid. Hosted unit 40519925128 and integration 40519925139 passed on workflow attempt 1. Unit/UI: 2,932 unit and 39 UI executions passed, four fixture skips, zero failures; all 35 watch-only account tests passed, and the earlier launch case passed in 13.385s. Integration: 30 unique passes in 30 executions, four existing Blocktank staging skips, zero test failures or test-case reruns. Both used verified checkout3c59760a(d2d9d28d/b53e300e), tree4516c8e1, exactly matching final local validation. Full artifact digests, execution trees, UI/skip summaries, structured diagnostics and compile/action/runtime logs were inspected. Hosted E2E 40519926046 also passed on workflow attempt 1: 13 unique passing cases in 13 executions, one existing hardware-case skip, zero failures. Its first test step passed; steps 2/3 were skipped. Build and runner checked out the same3c59760a/4516c8e1tree, with pinned harnessec01c02f. No manual CI retry. All three existing human requests are preserved; João's changes request remains. The later fee-thread disposition is recorded above. No approval, merge readiness or funded/provider acceptance is inferred.Final diagnostics retain 16 structured QoS warnings, three AppIntents compile notices, 12 UIKit appearance events, 24 CoreGraphics NaN lines in app stdout, and platform/negative-case runtime messages. Full address stacks are saved; no raw symbolicated backtrace was exported. No fresh base runtime or warning-free claim. Effective runner/helper and built endpoints were verified at unavailable 295xx ports; the fork skipped before funding. J1/J2, physical hardware, full linked-request/two-wallet settlement and rendered 546/547 gaps remain as documented below.
Hosted diagnostics retain the exact prior 286 structured / 571 build-log duplicate-warning multisets. Integration's existing sync helper recovered from a first-attempt Taproot sync timeout inside a passing test; no whole test was repeated. Unit runtime logged a keyboard-queue timeout with
Last Exception Backtrace: No stack!, plus socket/haptic and negative-case messages. These observations are retained without a cause or permanent-fix claim. Integration's 22 associated inputs match actuald2d9d28d; of 40 unit-runtime source files, 38 match and AppViewModel/SendConfirmationView retain this PR's changes. No fresh actual-base runtime or warning-free claim.E2E diagnostics retain 66 stale-element notices, four log-stream restarts (statuses 143/137/124/149), Node/npm deprecations and the pinned harness's 76 dependency-audit findings (8 low, 17 moderate, 44 high, 7 critical). Build/action output retains AppIntents metadata, destination/tool and ignored-base-input notices. All five job logs and 14 case outcomes were inspected. App artifact
12741962657(141,017,046 bytes) has SHA-25681978458fa352095f683215ca76521bd97cd1c7fe1a8e73e62477a4e59891883, matching API metadata, upload and runner download logs; the archive was not downloaded locally. The successful workflow did not upload runtime-report/video artifacts. These results do not establish a warning-free run or erase earlier failures and acceptance gaps.Actual master at the latest audit is
85e9d4c6: three commits and eight paths beyond the hosted base543d9389. The only overlap with the PR diff is AppScene's foreground-notification hunk, disjoint from this PR's request-preparation timing changes. The PR remains mergeable; no integration was performed. Hosted unit/integration/E2E results cover543d9389/20cfeffa; the newer85e9d4c6combined tree is unvalidated. Local results retain their separate repaired PR-tree attribution.Earlier validation —
20f54449(October 27): The unit CI crash at811b4335was traced to concurrent access in the watch-only test fake: an assertion read its tracking Set while the authorization task inserted into it. The two affected tests now await the existing actor-isolated gate after tracking has finished. All assertions and all 35 tests remain; production code is unchanged. The coordinated repair passed 35 focused tests, 2,928 unit executions and 39 UI executions, with four explicit fixture skips and zero failures. Full SwiftFormat 0.64.0 passed (0/845 files need changes); translation validation found zero errors and 15 warnings with unchanged actual-base inputs. Complete diagnostics and independent frozen review were inspected. All 16 commits against actual masterb666ccb1verify locally and match GitHub’s exact commit set withverified=true,reason=valid. Hosted integration 40501754529 passed on attempt 1: 30 unique tests passed in 30 executions, four existing Blocktank staging skips, zero failures or retries. Verified checkouta7cb2f52(b666/20f54449) has treec1e3cd27, exactly matching final local validation. The archive digest, all 34 full case summaries, tree, action/runtime output and compile/test log were inspected. Structured warning/error arrays are empty; retained 571 duplicate-symbol compile warnings match the prior integration multiset, alongside the version-probe broken-pipe exception, tool/destination notices and embedded RGS/node/address-search/teardown/fixture/launch-metric messages. All 22 associated source inputs match actual base; no fresh base runtime or warning-free claim. Hosted unit40501754193subsequently failed on attempt 1: all 2,928 unit executions (including all 35 watch-only tests) passed, but UI had 38 passes, four skips and one failure inBitkitUITests/testExampleatapp.launch(). XCTest timed out acquiring a background assertion; the failure video shows splash then Terms. Root cause remains unproven. E2E40501754542passed 13 unique cases in 13 executions on its first step, with one existing hardware skip and zero failures. The complete logs, artifact digests, test trees, failure video and diagnostics were inspected; no manual CI retry. Both use the verifieda7cb2f52/c1e3cd27checkout. The 286 structured/571 compile warnings match the preceding unit run; E2E retains 70 stale-element notices, log-stream restarts and pinned-harness dependency warnings. All three existing human requests are preserved; João’s changes request and Piotr’s fee-refresh thread remain in force.Earlier validation at
9a807ef3(October 27): Conflicts with actual masterb666ccb1are resolved in signed normal merge9a807ef3, tested tree0ce4fc92. The combined tree preserves fixed-quote amount/expiry/dust/fee and authorization safeguards, duration-only diagnostics, and master's SDK/request/proof lifecycle changes. Final local gates passed: 15 focused tests, 2,928 unit executions and 39 UI executions, four fixture skips, zero failures. Full SwiftFormat 0.64.0 reports 0/845 files needing changes (81 skipped); translations report zero errors and 15 warnings whose inputs match actual master. Complete test trees, compile/action logs, 19 structured QoS warnings, 21 raw backtraces and remaining platform notices were inspected and retained; this is not a warning-free claim or runtime baseline reproduction. All 14 commits against actual master verified locally and matched GitHub's exact set, with every signatureverified=true,reason=valid. Hosted unit, integration and E2E workflows all passed on attempt 1 at the exact locally tested merge tree. Hosted unit/UI: 2,928 unit and 39 UI executions passed, with four fixture skips. Integration: 30 passed and four Blocktank skips. E2E: 13 passed and one existing hardware-case skip; its first test step passed and steps 2/3 were skipped. Full diagnostic and helper-retry limits are recorded below. Full evidence is recorded below. All three existing human review requests remain pending; no changes request was dismissed.The canonical run verified built RPC/bundler endpoints at unavailable 29545/29546 and the fork skip before app launch or funding. No shared fork access, funding or transfer occurred. Funded/provider/hardware/two-wallet and rendered 546/547 acceptance gaps remain; the historical incidents and hosted retry/skip limits below retain their original attribution.
Earlier validation (October 26, retained at its original head): Conflicts with actual master
b8b7f3d9are resolved in signed normal merge63ea2034(tested tree21fb1809). The combined tree preserves master's wallet-switch lifecycle fix and this PR's quoted-payment guards. Final local validation passed: 2,894 unit executions and 39 UI executions, with four fixture skips and no failures. All 13 current-base PR commits verify locally and on GitHub. Hosted unit/integration checks passed. E2E completed successfully after two built-in retries of the Lightning case; 13 unique cases passed and one hardware-transfer case stayed skipped. The two earlier Lightning timeouts remain unexplained. J1/J2 and the funded/provider/hardware acceptance gaps below remain open.Fixed quoted Bitcoin requests open in the existing confirmation screen when no separate funding-source selection is needed. A fixed $2.50 Savings request skips the amount screen with disabled controls. Requests offering LNURL Spending alongside Savings retain the existing funding-choice screen because LNURL confirmation has no wallet selector.
Earlier master integration and local validation —
63ea2034The normal integrations retain the previous dust and fixture-endpoint fix, merged #1003's Receive coverage, and merged #1098's single wallet-switch run and resumed-preparation behavior. Quote identity, exact amounts, expiry, selected-rail minimums, routing-fee cancellation and authorization checks remain intact. No assertions were removed or weakened, and no new exclusion or authored test was added by conflict resolution.
b8b7f3d9tree, using Xcode 26.1 and an iPhone 17 Pro Max simulator on iOS 26.1, one worker and private build/package paths. The six canonical integration exclusions match the workflow; separate integration, E2E, provider or hardware completion is not claimed by this local run.b8b7f3d9matched the local range and reportedverification.verified=true,reason=validon GitHub. Both integrations are additive signed commits, with authors and prior work preserved.The earlier
536abb44candidate also passed its own canonical run before master advanced, but that result is distinct from the final run above. The earlier shared-fork incident and incomplete rendered 546/547-sat boundary, provider, physical-biometric, hardware and two-wallet settlement journeys remain explicitly unvalidated.Earlier dust/fixture fix validation —
9acc68e2Quoted Savings terms now require at least 547 sats before confirmation can rebind them. Exact valid amounts, expiry, quote identity and authorization guards are preserved. This addresses Piotr's finding.
test_fundWallet, and observed 1,000 fake USDT. Quote preparation failed before confirmation; no transfer/settlement is evidenced. This was an isolation mistake, not accepted funded QA. No fixture repair, reset or compensating write followed.2ce21025verify locally and asverified=true,reason=validon GitHub. This is an additive signed commit, with no history rewrite. At that point hosted CI was blocked by the master conflict; the current signed integration above supersedes that hold.J1/J2 and live provider, physical biometric, hardware and two-wallet settlement gaps remain open. The final safe fixture skip does not validate the failed funded journey.
Automated Checks
PaymentNavigationHelperTests.swift— exact converted amount, expiry, real BTC/USDT choice, routing, unavailable/expired-rate fallback and reviewed-term mismatch protection.PaykitPaymentRequestServiceTests.swift— hosted confirmation waits for wallet sync before rejecting a below-minimum quote.SendConfirmationLifecycleTests.swift— hosted fixed-request preparation, rail-specific quoted amounts and fees, invalid-term fallback, manual picker Back/retry, UTXO failure and fee failure/recovery.Historical validation before
ad30f8be: the 48-test focused result above predates this integration. The prior all-target compile, whitespace-only ActivityRow formatting repair, 14 verified base translation warnings and CoreSimulator boot blocker remain historical evidence.Historical author validation at
ad30f8be(tested treef76406a5, integrated master53c5ec0d):xcodebuildmcp simulator test --jsonfocused selection: 439 passed, zero failures/skips. The canonical direct Xcode fallback used the same six CI integration exclusions and one worker: 2,881 units plus 43 UI executions (39 passed, four fixture skips), zero failures. The UI skips require the disabled Trezor emulator or local Arbitrum fixture; they are not passes. Existing unfunded iPhone 17 Pro simulator, iOS 26.1.53c5ec0d. Independent combined integration review found no verified issue; PR patches and master recovery/sign-out behavior are preserved.e4bf44a2through maintainer merges of fix: unify usdt balance and amount presentation #1077/fix: reuse received payment artwork layout #1092. Those 36 paths are disjoint from this PR's 13-path delta; a clean read-only merge retained the exact PR blobs and all current-base changes. Local runtime evidence applies to the published tree. Hosted unit and integration checks subsequently passed on CI mergea6deea4d, whose tree053473bcexactly matches that reviewed combination withe4bf44a2.e4bf44a2verified locally and the exact GitHub commit set reportsverified=true,reason=validfor every commit.Hosted validation for head
ad30f8be:e4bf44a2run 40028545050. AppIntents metadata notices also occur on both. Project, workflow and dependency pins match that base; no new warning was found. The hosted xcresult records no runtime warnings.@lightning_1timed out after 30 seconds waiting for “Transfer Initiated” after closing a restored channel (lightning.e2e.ts:276at pinned E2E revisionbcf91fee). The second attempt reran only that case and passed; the other 13 were skipped and attempt 3 did not run. Complete workflow logs and per-case reporters were inspected. The close-confirmation view, transfer/wallet view models, Lightning service, toast components and E2E workflow match actual basee4bf44a2; this comparison does not prove that the timeout is pre-existing or establish its cause. After the successful retry, the workflow skipped runtime/screenshot/video artifact upload; only the built app artifact remains, so the saved failure visuals and app logs could not be inspected. Startup log-stream wrapper restarts are separate from the test retry. No manual workflow retry or code change was made, and the passing retry does not establish a permanent fix. All CI workflows for that earlier tested revision passed; this historical result does not describe the latest head. The full payment-journey limitations below remain.External device QA at exact head
ad30f8beis attributed to review 5635086275, which reports no introduced finding. On an iPhone 17 Pro / iOS 26.5 simulator with regtest funds, the reviewer checked direct 5,000-sat confirmation and a 143-sat fee, Largest First selection, manual-picker Back, cancellation during preparation, LNURL/Savings choice, LNURL-only direct confirmation, BOLT11/Savings switching at 2,500/5,000/2,500 sats, the fixed $2.50 BTC/USDT choice, and insufficient/expired-term guards. Swiping after expiry left both Bitcoin balances unchanged; fresh terms required confirmation. Hosted assertions covered invalid-term and fee/UTXO failure recovery. Videos and exact limitations are in that review.This external subset does not report a completed two-wallet fixed-quote settlement. USDT funding/submission, subscription authorization and hardware-wallet signing were not exercised; provider and physical-biometric validation remain incomplete. The full journey above stays unchecked. That earlier author-validation pass made no funded payment or wallet reset. Simulator data was preserved and the native window released.
Hosted unit/integration completion —
63ea2034, 2026-10-26Unit40410064946 and integration40410064928 succeeded on workflow attempt 1. Both checked out merge
a9eb51a06724ccd6a0cbff62487fcd8b5bf0bc77, with verified parents actual masterb8b7f3d9/ published63ea2034and tree21fb1809bb1af4f626c437015f8780139a9320b7, exactly matching the locally tested published tree. Unit: 2,894 passed. UI: 43 executions, 39 passed / four fixture skips / zero failures. Integration: 30 passed / four existing Blocktank staging-retirement skips/zero failures, with no retry execution. The four integration guards are byte-identical to actual master. Skips are not successful provider/hardware journeys.Artifact ZIP digests, all execution refs/skip reasons, complete logs and structured build/action reports were inspected. Unit has 286 structured duplicate-symbol warnings and 571 build-log warning messages; the structured multiset equals the historical b261 baseline. Project/pin/unit/integration workflow inputs match actual b8, but no actual b8 runtime baseline was run. Both full compile logs retain 571 duplicate-symbol warnings plus tool/multiple-destination notices; the integration version probe retains its broken-pipe exception. RuntimeWarnings/testFailures arrays and action warning/error nodes are empty. Integration's test-without-building status does not prove warning-free compilation. Xcode 16.4 compile paths, iPhone 16 / iOS 26.2.
E2E workflow 40410065359 completed on workflow attempt 1 using the same verified
a9eb51amerge/tree above, Xcode 26.2 (17C52), iPhone 17 / iOS 26.2 and E2E revisionec01c02ff611797c112e65b5c87c936d25720bac. Of 14 selected cases, 13 unique cases passed across 15 executions and three built-in test attempts. Attempt 1: 12 passed,@lightning_1failed, and hardware-wallet transfer-to-Spending stayed skipped. Attempt 2 reran only Lightning and failed; attempt 3 passed it. Both failures timed out after 30 seconds waiting forActivityShort-0to contain9 000after closing the restored channel (lightning.e2e.ts:287). No root cause or actual-base runtime reproduction is established; passing the third attempt does not establish a fix. The hardware skip is explicit in the pinned test source because Blocktank staging no longer creates orders.All five job logs, per-case reporters and complete available diagnostics were inspected. The workflow marks the first two steps successful through
continue-on-error; their raw exit-1 failures remain recorded here. Failure screenshots/videos were named in the runner log but were not uploaded after final success; only the app artifact remains, so those visuals and runtime reports could not be inspected. Log-stream restarts (143/137/124/124/143/143), 80 stale-element warnings, the address-type helper retry, dependency notices/audit output and the AppIntents/multiple-destination build notices remain retained. No new source change or manual CI retry was made. Rendered 546/547, funded/provider/hardware/two-wallet and other documented acceptance gaps remain explicit.Hosted integration completion —
9a807ef3, October 27Integration workflow40453530944 passed on attempt1: 30 unique tests /30 passing executions, four existing Blocktank skips, zero failures. All34 case summaries and the full execution tree confirm no retry execution. Empty runtimeWarnings/testFailures arrays and no structured action warning/error nodes. Embedded action output still contains RGS gossip failures, node/address-search/teardown diagnostics and the orphaned-RN-keychain fixture: all45 exact diagnostic groups were inspected, and all nine associated source/test files match actualb666. Hierarchy copies duplicate these log lines; this is not a warning-free or actual-base runtime reproduction claim. Skipped refund-address lifecycle/create-CJIT/orders/channel-purchase cases cite the closed staging service; their source and workflow match actual master.
The job checked out merge
a27dd5a89eba7dd6c2fd9e753131800383c565cc, with verifiedb666ccb1/9a807ef3parents and tree0ce4fc92, exactly matching the locally validated tree. Artifact digest, full job log, test trees and structured diagnostics were inspected. Compile output retains571 duplicate-symbol warnings (286 unique), the same complete multiset as the earlier actual-cc5 baseline. Current project/pins match actualb666, but no new b666 runtime reproduction is claimed. Test-without-building buildStatus=notRequested/no exported build log is not warning-free evidence; the full separate compile output is retained. The version-probe broken-pipe exception and tool/destination notices remain explicit. Runner: Xcode16.4 compile environment, iPhone16/iOS26.2; local26.1 results remain distinct.Unit and E2E completion is recorded in the following addendum; no manual retry. Funded/provider/hardware/two-wallet/rendered546/547 acceptance and historical retry/skip limits remain. Full report:
/private/tmp/usdt-monitor-20261027-0534/ci/completion-report.md.Hosted unit and E2E completion —
9a807ef3, October 27Unit 40453530938 and E2E 40453531272 passed on workflow attempt 1. Unit, E2E build and E2E runtime logs identify merge
a27dd5a89eba7dd6c2fd9e753131800383c565cc, with verified actual-masterb666ccb1/ published9a807ef3parents and tree0ce4fc929ce5dcb22d64b5800dc7451466705bb3, matching final local validation.ec01c02f. This does not establish physical-hardware acceptance.The unit archive digest, complete execution trees, all UI summaries, structured build/action diagnostics, all six unit/E2E job logs and available artifact metadata were inspected. Unit structured runtimeWarnings/testFailures are empty. Its 286 structured duplicate-symbol warnings and 571 build-log warning messages exactly match the recorded actual-cc5 multisets; current build inputs match b666, but no fresh b666 runtime baseline was run. Embedded action output retains negative-case offline/auth/storage/identity/hardware/durable-recovery and fee/UTXO diagnostics, synthetic Blocktank UUID-order failures, and simulator haptic/socket notices. Associated source comparisons and complete groups are retained; this is not a warning-free or blanket pre-existing claim.
E2E retains 68 stale-element notices, log-stream restarts 143/137/124/124, and one address-type tap/toast helper retry, separately from test retries. Tool/AppIntents/Node/npm notices remain; the pinned external E2E harness reports 76 dependency vulnerabilities (8 low, 17 moderate, 44 high, 7 critical), identical to its earlier same-revision log, with no uploaded advisory report. Only the app artifact was uploaded, and its metadata digest matches the build-upload and runner-download logs; no runtime-report or video artifact was available after success. Unit used Xcode 16.4 / iPhone 16 / iOS 26.2; E2E used Xcode 26.2 / iPhone 17 / iOS 26.2.
No manual CI retry or source change. Earlier Lightning failures/recovery and fixture incidents retain their original attribution. Funded/provider/physical-hardware/two-wallet settlement and rendered 546/547 acceptance remain incomplete. Full evidence:
/private/tmp/usdt-monitor-20261027-0636/ci/completion-report.md.Quoted review Back fix —
811b4335, October 27Returning from fallback Amount to a fixed quoted request’s Confirm root now closes that presentation, so Back no longer immediately pushes Amount again. The first fallback—including initially unreviewed terms—still requires amount review; valid terms reset the marker. The existing presentation-scoped dismissal preserves a replacement sheet. Seven production lines changed; two existing lifecycle tests were extended with a true Confirm-root host, with no new/removed tests. The existing journey now includes the iOS fallback Back and manual-coin return steps.
Unchanged
9a807ef3failed the Back/dismiss assertions for all four invalid quote variants; the frozen fix passed all 15 focused lifecycle tests and the workflow-selected canonical suite: 2,928 unit + 39 UI executions passed, four fixture skips, zero failures. Three Trezor cases remain opt-in; the isolated fork skipped at unavailable29546before app launch/funding. Exact helper/runner forwarding and built endpoints were checked. SwiftFormat 0.64: 0/845 files need changes; translations: zero errors/15 warnings, with all 21 relevant inputs identical to actualb666ccb1. Independent frozen-diff review found no verified issue. All 15 current-base PR commits verified locally and match GitHub’s exact set withverified=true/reason=valid. Normal additive push; no history rewrite.Complete logs, execution trees and 47 warning/UI/skip summaries were inspected. The 13 structured QoS warnings and 16 raw backtraces are different diagnostic surfaces; raw traces cover Pubky/mainline initialization and LDK status/sync. Two AppIntents compile notices, 11 UIKit appearance notices, simulator haptic diagnostics and 48 CoreGraphics NaN notices during passing USDT Receive/manual-entry cases remain recorded. No NaN backtrace or fresh actual-base runtime reproduction is available; those cases do not enter the changed quoted Bitcoin Confirm path. The changed source’s UTXO-unavailable logs come from an unchanged negative-case method. No blanket warning-free/pre-existing claim. Test-without-building metadata is not compile-clean evidence.
The manual-coin regression also passed with Confirm as the actual navigation root: after Continue to the second confirmation and Back through the picker, the original root recalculated using the selected coin without a fee-rate change. This proves the controlled fee-preparation call, not rendered fee text or a funded/provider journey. New-head hosted CI is pending; full linked-request/provider/physical-hardware/two-wallet settlement and rendered 546/547 acceptance remain incomplete. Previous evidence retains its original head attribution. Planning/implementation/review for this fix:
gpt-6-astra, reasoningxhigh, verified from actual execution metadata.Hosted integration at 811b433
Integration 40486729719 passed on workflow attempt 1: 30 tests passed in 30 executions, four existing Blocktank staging skips, zero failures or retry executions. Checkout
156e44dbhas actualb666ccb1/811b4335parents and treee5409e4f, exactly matching final local validation. The archive digest, all 34 case summaries, test tree, action/runtime output and full compile/test logs were inspected.Structured warning/error arrays are empty, but test-without-building is not proof of warning-free compilation. Retained 571 duplicate-symbol compile warnings (matching the prior hosted integration multiset), the version-probe broken-pipe exception, tool/destination notices and embedded RGS/node/address-search/teardown/fixture diagnostics. Associated inputs match actual base; no fresh base runtime reproduction is claimed. The subsequent unit failure and E2E completion for this parent are recorded in the crash-repair addendum below. Provider/funded/physical-hardware/full linked-request/two-wallet/rendered-fee acceptance limits and Piotr's open finding remain unchanged.
CI crash repair and diagnostic limits —
20f54449At parent
811b4335, unit workflow 40486729701 built successfully but had 2,927 unit passes and one crash intestAuthorizationSerializesReconciliationUntilTrackingStateIsPersisted; UI had 39 passes/four skips. The crash report showsXCTAssertEqualreadingtrackedAccountIndexesconcurrently with the fake’s insertion. The test and service inputs match actualb666ccb1, but no actual-base runtime reproduction is claimed. The narrow synchronization repair was coordinated with the file’s owning work before editing. Parent E2E 40486730476 passed 13 unique cases in 13 executions, with one existing hardware-case skip and no failures. Both checked out merge156e44db/ treee5409e4f(b666/811b); these results retain that parent attribution, not the new head.Final local repair validation used tree
c1e3cd27, Xcode 26.1 and the owned iPhone 17 Pro Max / iOS 26.1 simulator with one worker and private products. The complete execution tree confirms 2,928 unit + 39 UI passes; the summary groups 30 launch configurations into one. Three Trezor opt-in cases and the unavailable isolated fork skipped. Built endpoints and runner/helper forwarding were verified; runtime fork availability failed at unavailable29546before app launch or funding. No shared fixture was accessed.Full reports retain 16 structured QoS warnings and 16 raw backtraces (14 Paykit/Pubky initialization, two LDK status), two AppIntents compile notices, UIKit appearance and simulator keyboard/haptic/graphics/network notices, and negative-case storage/auth/recovery/fee diagnostics. Relevant QoS wrappers/pins match actual
b666ccb1; no fresh base runtime or warning-free claim. The passing UI run emitted 24 CoreGraphics NaN notices; the earlier identical-production811brun retains 48. No causal or permanent-fix claim is made for those notices. Hosted parent E2E retains 68 stale-element notices, helper/log-stream retries, pinned-harness dependency warnings and absent runtime-report upload. These checks do not complete J1/J2, production-provider, physical-hardware, funded settlement, full linked-request or rendered 546/547 acceptance.Native Back prerequisite diagnostic — October 27, 21:24 UTC
A temporary, isolated diagnostic at
20cfeffanow mounted the productionSendSheetthrough the same modal binding asMainNav, with setup-complete state seeded and unavailable fixture endpoints. This excludes real linked-request setup and persistence, authorization, and funded/provider acceptance. The modal, two-controller stack, enabled native recognizer, key window and hit-test were verified. One cancellation-shaped drag and one completion swipe still failed before any interactive transition began; the diagnostic failed all four relevant assertions. Adding the modal wrapper did not close the gap or establish a production defect.A standard UIKit navigation control on the same iOS 26.5 simulator did reach and cancel a genuine interactive Back transition. Its first run and one bounded recovery both expired before the completion gesture could be delivered because of turn interruption/context compaction; both remain failed, with two assertions each. No completed native pop or J1 acceptance is claimed. Full logs, nested diagnostics, failed assertions and screenshots are retained, including UIKit transition fallback and platform/accessibility notices. The temporary source was restored byte for byte, the checkout is clean, and scoped simulator services are stopped with data preserved. No production edit, source push, CI rerun or additional review request was made.
Native Back control follow-up — October 27, 22:28 UTC
The final bounded recovery of the interrupted UIKit control passed using identical built products: both cancelled and completed native transitions were observed, and the stack returned to its root. Fresh UI and log guards kept both gestures inside one live test window. Earlier interrupted failures remain retained.
The remaining prerequisite also fails in minimal SwiftUI and UIKit modals with hidden navigation bars and no payment/request/wallet objects (four and three assertions respectively). Each received one cancellation drag; the guard withheld completion when no interactive transition began. Separate SendSheet observations found both the edge and iOS 26 content-pop recognizers enabled, with delegates permitting a start. These values were unchanged by temporarily showing the bar. Both shared swipe-extension files match current master
85e9d4c6; this is source comparison, not a base runtime test.The controls do not yet separate navigation-bar visibility, modal presentation and runtime behavior, so no product cause/fix or completed J1 native Back acceptance is claimed. All logs, nested diagnostics, failure stacks and screenshots are retained. Temporary source is restored exactly and the checkout remains clean at
20cfeffa; no source push, CI rerun or reviewer notification. Existing provider, funded, physical-device and full linked-request limits remain.Native Back visibility control — October 27, 23:28 UTC
The isolated UIKit modal control passed its one selected test in 8.209 seconds on the same owned iOS 26.5 / Xcode 27.1 setup after changing only the navigation bar from hidden to visible (plus its state assertion/log and test name). Native cancellation and completion callbacks were
[true, false], and the stack returned to its root. No SendSheet/payment/request/wallet objects participated. The prior hidden-bar modal failures remain retained.This isolates visibility-dependent behavior in that control; it does not establish the production cause/fix or complete SendSheet J1 native Back acceptance. Shared swipe code matches actual master
85e9d4c6, by source comparison only. A shared-navigation follow-up requires ownership reconciliation. Full build/test trees, nested diagnostics, raw logs and screenshots were inspected. Structured warning/error arrays are empty; SDK/accessibility notices and two UIKit transition-fallback notices remain. Temporary source is restored exactly, the checkout remains clean at20cfeffa, and scoped simulator services are stopped with data preserved. No production edit, source push, CI rerun or reviewer request. Existing provider, funded, physical-device and linked-request limits remain.