Repository navigation
fix: stabilize contact selection and amount layouts - #1003
ben-kaufman wants to merge 14 commits into
Conversation
[Medium impact] The changes affect payment entry and contact selection in a few bounded app workflows. The PR appears safe to merge, with a non-blocking setup correction needed in the new amount journey. Findings
SummaryThis PR disables contact rows while payment details resolve and updates the shared request/subscription amount screen.
No runtime tests or visual captures were performed. The review environment is Linux and cannot render the iOS views. Reviews (1) · Last reviewed commit: "fix: stabilize contact selection and amo..." · Reviewed by Greptile |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. Disables every contact row while a saved-contact payment resolves, and moves the request/subscription amount screen into a scroll view with leading-aligned amount, wrapping BTC/USD controls and a divider above the keypad. Reviewed 6ba39e0, full tier.
What I checked, and 4 candidates I ruled out
Read in full: SendContactSelectView.swift, CreatePaymentRequestView.swift (PaymentRequestAmountView), PubkyContactRow.swift, NumberPad.swift, NumberPadTextField.swift
Call sites traced: PaymentRequestAmountView from ReceiveSheet.swift:150 and SubscriptionAmountView (CreateSubscriptionView.swift:251); both keep their container identifiers, and the PaymentRequest* field, asset, unit and continue identifiers are unchanged.
CI: validate and Greptile green; Run Tests, Run Integration Tests and build-local still pending at review time.
Not built here: iOS does not build on Linux, so this review is reasoned from the code and CI, not from a simulator run.
Ruled out
- Rows stay disabled after a failed resolve:
payclearsselectedContactKeyin adefer, so every exit path (toast, thrown error, cancellation, navigation) re-enables the list. - Spacers collapse inside the new
ScrollView: the content carries.frame(minHeight: geometry.size.height, alignment: .top), so the two flexible spacers still share the leftover height and Continue sits at the bottom when everything fits. - Asset/unit actions lost in the stacked fallback:
amountActionsemits the assetHStackplus the optional unit button, and bothViewThatFitsbranches render the same builder, so the BTC-only unit toggle and conversion handlers are identical in either layout. - Keypad taps eaten by the scroll view: plausible bounce on a fixed-size pad, but not demonstrable without a device run; not posted.
Merge confidence: 4/5, no findings, but the build and test jobs had not finished and the layout was not run on a simulator.
There was a problem hiding this comment.
Verdict: ✅ Approve: one LOW layout shift, and all six cases passed at 71342ec.
Findings:
-
LOW
Bitkit/Views/PaymentRequests/CreatePaymentRequestView.swift:344: switching between BTC and USD now moves the controls. The BTC amount (NumberPadTextField, with its fiat line) is about 24 pt taller than the USD amount (NumberPadAmountText). The flexibleSpacerthat used to absorb the difference is now a fixed 16 pt gap.- Tapping USD moves the BTC/USD chips and the divider up 24 pt and the keypad up 12 pt, on both iPhone 17 Pro and iPhone SE.
- At the largest text size the shift is 52 pt for the chips and 89 pt for the keypad, because the stacked unit button disappears too.
- On base 7b3f093 the chips and keypad stay where they are. Giving the amount slot the BTC branch's height in both modes would keep them fixed.
Head, BTC then USD Base, BTC then USD 

QA for 71342ec:
Tested on iPhone 17 Pro and iPhone SE (3rd generation) simulators, iOS 26.5. Debug build on staging regtest, with the bitkit-docker USDT fixture and Trezor emulator. Two wallets were linked as contacts.
Test 1: contact rows lock while payment details resolve ✅ Only the tapped row spins, every row is disabled, and a failed resolve shows the error and re-enables them.
- Failed resolve: I tapped a contact that cannot resolve. Its row alone showed the spinner, both rows dimmed, and the accessibility tree reported both rows as not enabled. A tap on Bob in the meantime opened nothing. After about 14 s the "Unable To Pay Contact / Please try again." toast appeared and both rows became tappable again.
- Retry: Tapping Bob showed his spinner with both rows dimmed. A tap on the other row was ignored, and one amount screen opened for Bob after about 12 s.
- Both waits come from contact resolution on staging, with the spinner shown the whole time.
test1-contact-rows.2x.mp4 |
Test 2: request amount layout in USD ✅ The amount sits leading under the header, the BTC/USD controls trail directly below it, a divider sits above the keypad, and details keep $1,50.
This was a request for Bob, with the simulator on a comma-decimal locale. BTC showed the same structure with the unit button beside BTC/USD, and Continue stayed at the bottom. I closed the request without sending.
test2-request-amount.2x.mp4 |
Test 3: subscription amount in BTC and USD ✅ Same layout in both, nothing overlaps the keypad or Continue, and accepted methods are Savings only for BTC and USDT only for USD.
- Amounts: 1000 sats, then $1,50.
- Exclusive methods: Tapping USDT while in BTC switched the amount to USD and turned Savings off.
- Recipient: Bob was selectable as the recipient. I closed the sheet without proposing.
test3-subscription-amount.2x.mp4 |
Test 4: compact width and largest text ✅ On the iPhone SE everything fits at default text, and at the largest size one scroll brings Continue fully into view.
- Largest text, BTC: the unit button stacks under BTC/USD, and Continue starts below the fold.
- Scrolling: a scroll that started on the keypad entered no digit. $1,50 carried through to the details.
- Subscription amount: behaved the same at that size.
- Width: 375 pt is the narrowest width these simulator runtimes offer, so 320 pt was not driven.
- Against base 7b3f093 at the largest size: base cuts the unit button to "BIT…" and leaves Continue half off-screen with no way to scroll. The
000key reads "0…" on both builds;NumberPadis unchanged.
test4-compact-large-text.2x.mp4 |
Test 5: USDT wallet and Receive layout ✅ Savings and USDT open with the same opaque slide, Show Details keeps its position across Receive tabs, and USDT keeps Network: Arbitrum One after the network list.
- Show Details: on Savings and USDT it stayed at the same position on every switch, above the home indicator. Spending shows Receive Lightning Funds in that slot.
- Network: after going back from the network list, Show Details opened the Arbitrum One address.
- SE, default and largest text: the network row and Show Details stayed visible. The network name truncates at the largest size.
test5-wallets-receive.2x.mp4 | test5-receive-compact.2x.mp4 |
Test 6: hardware tab label ✅ With a paired Trezor emulator, the hardware tab reads Trezor on every switch and never changes to Hardware.
I switched nine times between Trezor, USDT and Savings. At the largest text size the tab truncates to "Tre…", and its accessibility label stays Trezor.
test6-hardware-label.2x.mp4 |
Not from this PR: on the iPhone SE the USDT Receive tab's Network button sits over the Edit/Copy/Share row, so tapping Copy opens the network list and leaves the clipboard unchanged. Base 7b3f093 does the same, and this PR does not touch Receive.
existing-usdt-copy-head-vs-base.2x.mp4 |
Covered: the full diff, 7b3f093..71342ec. Every changed path had a device case. Pulling the amount sheet down from mid-screen while at rest still dismisses it, the same as on base.
Twin: synonymdev/bitkit-android#1564 matches on the contact picker. On both, the spinner stays on the selected row and every row is disabled. Android also announces the loading row to accessibility services; iOS rows only report disabled. The amount-entry layout from #974 is not part of it.
|
Also addressed the compact Receive problem noted in the review, in f55dc6f. The USDT QR now fits above Edit/Copy/Share, as it does in the Bitcoin receive layout, so Network does not cover the actions. The shared QR logo scales down only when space is limited; the existing maximum size is retained. Address details still scroll, and copy/share/URI contents are unchanged. Checked production-view renders at 320/375 pt and normal/largest text. All four compact QR renders decode to the original payment URI; a new regression decodes the actual USDT and Bitcoin QR components at compact/normal heights. All three receive tests pass, with no new format or translation findings. Android already bounds the QR; its five receive-copy/navigation tests pass, and #1565 has the matching QA journey. The enlarged-text truncation in the unchanged shared buttons is separate from this overlap fix. The journey still calls for reviewer checks of the physical tap targets. |
jvsena42
left a comment
There was a problem hiding this comment.
Code scan: no findings.
Checked and clean:
- USD input uses
Locale.current.decimalSeparatorand BTC uses..handleInputandparsePaykitAmountInputare unchanged. - The hidden
amountControlscopy and the always-present BTC field are out of the accessibility tree and can't be tapped. QR.swift: the QR content, the share image andcopyValueare unchanged. Only the logo's sizing source moved, and bothQrAreacallers now have a bounded height.SendContactSelectView.disabled:pay()clearsselectedContactKeyin adefer, so every exit re-enables the rows.
Scope differs from synonymdev/bitkit-android#1565 (QR logo and the contact .disabled change are iOS-only; Android already has the latter on master). The two new journey files are byte-identical.
Device gate (partial): not run yet. Pending: the three journeys on the simulator, including whether the Bitcoin QR sits lower on tall layouts now that the logo GeometryReader makes the ZStack flexible. Perf: not relevant. The device result follows in a second review.
There was a problem hiding this comment.
Verdict:
Findings: No new code findings. The previous BTC/USD layout-shift finding is fixed.
QA for b087c50:
Built and tested on iPhone 17 Pro and iPhone SE (3rd generation) simulators, iOS 26.5, using regtest and test USDT. Nothing was paid or published.
Test 1: request and subscription amounts, normal text ✅ BTC/USD keeps the divider and keypad stationary, and 1.50 USD reaches details.
Accessibility bounds confirm the positions in both callers. A 1000-sat subscription selects Savings; selecting USDT switches the denomination to USD and deselects Savings. Both forms were closed without sending.
amount-normal-2x.2x.mp4
Test 2: compact amount entry and largest text ✅ Wrapped controls stay in place across BTC/USD, and scrolling reaches the keypad and Continue.
On the iPhone SE, the divider and keypad bounds match in both denominations for requests and subscriptions. All BTC keypad controls were tapped; after clearing input, 1000 sats and 1.50 USD reached details. Default-text compact layout was also checked. The unchanged 000 label still truncates at the largest size, as recorded in the earlier review.
amount-accessibility-2x.2x.mp4
Test 3: compact Receive Copy and QR ✅ Copy reaches the plain address without opening Network, and the displayed QR decodes at normal and largest text.
Copy occupies y483–523; Network starts at y539. Clipboard reads match the QR’s receiving address. Core Image decoding of the captured display returns the correct Arbitrum payment URI at both text sizes; Bitcoin codes also decode. The network round-trip retains Arbitrum and address details scroll. Existing button and network-label truncation remains at the largest text size.
receive-compact-2x.2x.mp4
Test 4: tall Bitcoin and USDT Receive ✅ Both displayed codes decode, their logos remain centered, and the actions stay reachable.
Core Image decoded the captured Bitcoin and USDT displays to their original payment URIs. Copy, the network round-trip and Show Details retain the USDT address and Arbitrum network. Savings, Spending and USDT switching keeps the footer reachable; Spending shows its Lightning onboarding action because this wallet has no channel.
receive-tall-2x.2x.mp4
Test 5: contact-detail Request or Pay ❌ The funded warm Pay handoff takes about 6.5 seconds against the journey’s three-second target.
Pay shows progress with Request disabled during lookup and eventually opens one send amount screen. Closing permits retry, and Request opens the request amount screen. A timed accessibility probe still sees Request Or Pay after 3.2 seconds and first sees SendAmount after 6.5 seconds. The timing assertion did not pass. This caller and its navigation helper are unchanged in the reviewed delta, so this is an unmet journey expectation rather than a new code finding on this PR.
contact-request-or-pay-2x.2x.mp4
The earlier passing report at 71342ec supplies unchanged contact-row locking/failure-retry, opaque wallet-transition and paired hardware vendor-label evidence. QR rendering was rechecked here. No planned case remains unrun. The narrowest device width driven was 375 pt; no 320 pt device or fresh Figma comparison is claimed. The conditional saved-activity/deposit-details step had no saved records to open and its routes are unchanged.
Reviewed the complete delta 71342ec..b087c50 and the prior open finding. Every changed runtime component had a device case; the test, journey and changelog edits were source-reviewed.
Pair PR: synonymdev/bitkit-android#1565 fix: stabilize usdt wallet and payment layouts matches the amount-stability intent and shared journey text. Android already bounds its Receive QR; the shared QR logo adjustment here is iOS-specific. Android was not rebuilt in this run.
|
Thanks for confirming the layout fixes and measuring the contact handoff. The 6.5-second result remains an unmet latency target; I am not counting that journey assertion as passed. This caller is unchanged by the layout PR, so I’m keeping the latency investigation under #868 rather than adding speculative timing changes here. The separate fixed-request work in #1014 adds duration-only resolution/setup diagnostics for incoming requests; it does not claim to explain this contact-detail delay. |
|
Resolved the master conflict while retaining the compact amount layout and master’s The app builds and all 44 focused amount, conversion, keypad, USDT display and component-sizing tests pass on the simulator. SwiftFormat is clean; translation validation reports no errors and the same 14 warnings as current master |
jvsena42
left a comment
There was a problem hiding this comment.
The delta since my review, 2297f2c, is a merge of master. The one conflict, in PaymentRequestAmountView.body, keeps this PR's GeometryReader/ScrollView layout and master's inputValue edits (lines 405, 430). usdtInputAmount display and the locale separator are intact, and QR.swift, UsdtReceiveView.swift and SendContactSelectView.swift are untouched. No code findings. One LOW on the journey is inline.
Device gate (partial): not run yet. Pending: paykit-amount-layout.xml, usdt-wallet-receive-layout.xml and contact-request-or-pay.xml step 19 on the simulator.
There was a problem hiding this comment.
Verdict:
Findings: No new code findings in this delta. The earlier amount-layout fix remains intact. The conditional failure/retry journey setup remains deferred to synonymdev/bitkit-ios#1031, as agreed in the review thread.
QA for 2297f2c:
Built and tested on iPhone 17 Pro and iPhone SE (3rd generation), iOS 26.5 simulators, with linked contacts and fixture USDT. No payment, request or subscription was submitted. Videos are at 2× speed.
Test 1: request and subscription amounts, normal text ✅ BTC/USD keeps the divider and keypad stationary, and 1.50 USD survives editing and reopening Amount.
Accessibility bounds confirm stable positions in both callers. The comma-decimal display retains 1,50 after conversion and draft restoration; request digit editing also returns 1,50. A 1000-sat subscription selects Savings; selecting USDT converts to USD and deselects Savings.
amount-normal-2x.2x.mp4
Test 2: compact amount entry at largest text ✅ Wrapped controls remain stationary across BTC/USD, and scrolling reaches the keypad and Continue.
Both request and subscription details retain 1.50 USD. Accessibility bounds confirm the divider and keypad positions; all BTC keypad controls were tapped after scrolling. Default-text compact request geometry was also checked. The 000 label still truncates, as in the earlier report.
amount-compact-2x.2x.mp4
Test 3: compact Receive and wallet navigation ✅ Copy reaches the plain address without opening Network, and the displayed USDT QR decodes at normal and largest text.
Clipboard reads and Core Image decoding match the receiving address and Arbitrum payment URI. Network remains Arbitrum after returning; address details and bottom actions remain reachable. Savings, USDT and saved-activity transitions stay opaque. At largest text, Network and Show Details wrap; the short Edit/Copy/Share labels still clip.
receive-2x.2x.mp4
Test 4: funded contact-detail Request or Pay ❌ The warm Pay handoff takes about 6.4 seconds against the three-second target.
Timed accessibility polling still sees Request Or Pay with Request disabled at 3.4 seconds and first sees SendAmount at 6.4 seconds. Progress is shown, one amount screen opens, closing permits retry, and Request opens PaymentRequestAmount. This caller is unchanged; the author’s response keeps the existing latency investigation under synonymdev/bitkit-ios#868. I have not counted the timing assertion as passed.
contact-handoff-2x.2x.mp4
The passing report at 71342ec supplies unchanged selected-row locking, failure/retry and paired hardware-label evidence. The report at b087c50 supplies unchanged tall Bitcoin QR evidence; compact USDT decoding was repeated here. No planned case remains unrun. The narrowest device was 375 pt; no fresh Figma comparison or 320 pt device run is claimed.
Reviewed the complete delta b087c50..2297f2c and prior open feedback. The integrated request/subscription amount paths were driven; the rest of the master integration was source-reviewed outside these layout journeys.
Pair PR: synonymdev/bitkit-android#1565 fix: stabilize usdt wallet and payment layouts matches amount stability and compact QR intent. Its contact failure setup differs as tracked in synonymdev/bitkit-ios#1031. Android was not rebuilt in this run.
Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest
|
Device gate (partial):
|
|
Thanks for the completed compact-device checks. I have kept the three-second handoff assertion explicitly unpassed and linked the 6.4-second measurement under #868 in Out of Scope. I passed the measurement to the separate performance investigation; this layout PR will not change contact preparation speculatively. The shared controls’ largest-text clipping was also recorded in the earlier base comparison and remains outside this layout delta. The deterministic failure setup remains tracked in #1031. |
|
Fixed the matching fresh-amount bug found on Android #1565 in e539585. Selecting USDT before opening a new subscription amount now allows digit entry immediately; existing cents and conversion behavior stay intact. Verified the actual iOS editor with zero → 150.50 and existing 150.50 → 150.55, including the Continue result. All 44 focused regression tests passed, changed-file formatting is clean, and all PR commits are locally signed and GitHub-verified. The amount journey now covers fresh USDT selection and reopening the entered amount. |
|
Integrated current master after #1002 merged. The only conflict was in The Swift diff is unchanged from the previously tested head. SwiftFormat, journey XML parsing and whitespace checks pass. Translation validation has zero errors and the same 14 warnings as current master. Independent review confirmed both branches’ changes are preserved, and all eight PR commits verify locally and on GitHub. CI is running again; no local build or device tests were rerun for this documentation-only resolution, preserving the ongoing latency measurements. |
|
Integrated current master ( |
|
Applied the shared formatting-only repair for the inherited ActivityRow lint failure. The Swift code is identical apart from whitespace. Full-repository SwiftFormat 0.64.0 passes; translation validation has zero errors and the same 14 warnings as master. App/test-target compilation passed before this formatting-only edit; no new runtime test result is claimed. Re-requesting review. |
There was a problem hiding this comment.
Verdict:
The PR moved to 1780ff2 after this run; these results are for fff038e.
Findings: No new code findings in this delta. The failures below were already reported before this head.
QA for fff038e:
Built and tested on iPhone 17 Pro and iPhone SE (3rd generation), iOS 26.5 simulators, with linked test contacts and fixture USDT. No payment, request or subscription was submitted. Videos are at 2× speed.
Test 1: fresh USD request and USDT subscription entry ✅ Both accept 1.50 from zero without Delete, and reopening preserves the cents.
The request retains 1,50 through BTC/USD switches and reopening; editing its last digit produces 1,55 in details. Selecting USDT before opening a new subscription amount accepts 1,50 immediately.
Accessibility bounds confirm stable divider and keypad positions. A 1000-sat subscription selects Savings; selecting USDT converts to USD and deselects Savings.
amount-normal-2x.2x.mp4
Test 2: compact editor and keypad legibility at largest text ❌ The unchanged 000 key still displays as “0…”, so the journey’s legibility assertion is not passed.
Fresh USD requests and USDT-first subscriptions accept 1,50 and preserve it on reopening. BTC/USD keeps the divider and keypad stationary, including the wrapped unit control. Scrolling reaches every key and Continue; all BTC keys were tapped, and cleared input reaches 1000-sat subscription details.
The earlier review already records the same 000 truncation on base. This is an unmet assertion, not a new finding on the changed lines.
amount-compact-2x.2x.mp4
Test 3: funded contact-detail Request or Pay ❌ A repeated warm Pay handoff exceeds the three-second target.
Pay shows progress with Request disabled and eventually opens one SendAmount. Closing enables another attempt, and Request opens PaymentRequestAmount.
On the repeat, timed accessibility polling first observes progress at 1.05 seconds after the tap command, still sees Request or Pay at 4.59 seconds, and first sees SendAmount at 6.00 seconds. The author’s response keeps this existing latency under synonymdev/bitkit-ios#868 contact payment latency on staging.
contact-handoff-2x.2x.mp4
Test 4: prepared endpointless contact failure and retry ✅ Selected-row progress, all-row disabling, error recovery and retry hold.
Only the selected row spins, and accessibility reports both rows disabled. Tapping the other row during lookup opens no second flow. A linked fixture contact with its published methods withdrawn shows “Unable To Pay Contact” and “The contact you're trying to send to hasn't enabled payments.” Both rows then become enabled; retrying the payable contact opens one amount screen. Both flows were cancelled without paying.
contact-retry-2x.2x.mp4
Test 5: compact Receive after master integration ⏭️ Not driven before the PR advanced to 1780ff2.
I added this check for the integrated ReceiveQr ViewBuilder simplification. Testing stopped after the active contact case when the head moved, so this run establishes no new Receive integration result.
The report at 2297f2c supplies earlier compact Receive evidence. The report at 71342ec supplies the unchanged paired hardware vendor-label check. The narrowest driven width was 375 pt; no 320 pt device run or fresh Figma comparison is claimed.
Reviewed the complete delta 2297f2c..fff038e and prior open feedback. Amount entry and contact selection were driven; the rest of the master integration was source-reviewed outside those journeys.
Pair PR: synonymdev/bitkit-android#1565 fix: stabilize usdt wallet and payment layouts matches fresh USD initialization and the shared journey expectations. Android was not rebuilt in this run.
These results cover fff038e. The newer head 1780ff2 was not reviewed or tested here.
Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest
|
Thanks for the rerun. Out of scope: the shared The roughly six-second contact handoff remains under #868 and the separate latency investigation. The Receive integration case still needs a fresh device run; I am not counting it as passed. The change from the reviewed |
jvsena42
left a comment
There was a problem hiding this comment.
Code scan at 1780ff2: no issues found. I reviewed e539585 and 1780ff2, plus both merges with --remerge-diff.
c81f534keeps both the duplicate-flow check and #1002's endpointless-contact failure and retry.fff038ekeeps this PR'sGeometryReader/ScrollViewbody; master's side of that conflict was formatting only.
Checked and clean:
- The zero-draft guard in
.taskcopies the existingconverted.atomic == 0 ? ""path. Continue still submitsamountwith the draft's endpoints, note and expiry. - The
ActivityRowchange is whitespace only. QR.swift, the.disabledchange inSendContactSelectViewand theUsdtReceiveViewlogic are unchanged from my last review.contact-request-or-pay.xmlstep 19 now walks the endpointless contact, the error and the retry, and the precondition is listed. I resolved that thread earlier.- Parity with synonymdev/bitkit-android#1565: same zero-draft fix, same 0.2 / 68 logo ratio, and byte-identical new journeys.
Perf: not relevant. l10n: no new keys. The Edit/Copy/Share clipping at the largest text size is on master and tracked in #1036.
Device gate (partial): 1780ff2 — not run yet. Pending: paykit-amount-layout.xml, usdt-wallet-receive-layout.xml and payment-requests/contact-request-or-pay.xml on the simulator. Device results will follow in a separate review.
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Scope: Reviewed the full PR diff against its merge base, at 1780ff2.
No new actionable code findings.
Saved-contact rows stay disabled until resolution finishes: pay clears selectedContactKey in a defer on success, failure, and navigation. A zero USD draft loads as an empty string, so a new request or USDT subscription accepts digits immediately; a non-zero amount reloads inputValue and keeps the cents. The amount row reserves the taller Bitcoin field and unit-control height, so switching BTC/USD leaves the divider and keypad in place. The shared QR logo uses the same 20% / 68 pt cap as Android, and the USDT receive code sits above Edit/Copy/Share with Network kept separate.
Compared those flows with bitkit-android#1565 at a4ce71cd: row disabling, zero-amount initialization, and the logo ratio match. Android locks the QR to a square; this was source comparison only.
Run Tests on this revision passed, including testCompactQrWithLogoRemainsScannable. SwiftFormat passed. This review did not execute those jobs or a simulator. Device testing: not performed. Prior device runs on fff038e and earlier commits still leave the contact handoff over the journey's three-second mark (#868) and the unchanged keypad 000 truncation at the largest text size (#1036).
There was a problem hiding this comment.
Verdict: ⛔️ Request changes — two journey assertions remain unpassed at 1780ff2.
Findings: I found no new defects in the delta. The failures below reproduce the existing, explicitly deferred keypad and contact-latency issues.
QA for 1780ff2: I built and installed this head on iOS 26.5 simulators. Recordings play at 2×; timing below uses the original run.
Test 1: Compact amount entry at largest text ❌ Fresh amounts, reopening, stable controls and scrolling work; the shared 000 label still truncates.
On a 375-point iPhone SE, I entered USD 1.50 directly from zero without Delete in a request and a USDT-first subscription. Continue and reopening retained the cents. Accessibility bounds matched for the BTC/USD controls, divider and keypad across currency switches in both editors. Scrolling exposed every key and Continue; tapping 1 then 000 produced 1,000 sats, but the visible 000 label reads 0… in both editors.
The subscription selected Savings for sats; choosing USDT converted the amount to USD and deselected Savings. I selected a recipient and cancelled without proposing. The failed legibility assertion remains tracked in bitkit-ios#1036 Keep the 000 keypad label readable at largest text.
amount-compact-2x.2x.mp4
Test 2: Funded contact-detail Request or Pay ❌ Progress, Request disabling, closing and retry work; a warm repeat exceeds three seconds.
With linked staging contacts and a funded test USDT wallet, both Pay attempts opened one SendAmount screen. The progress state disabled Request. Closing restored the contact action; Request subsequently opened PaymentRequestAmount. I cancelled without sending a payment or request.
A host-local monotonic accessibility probe on the repeat recorded the physical tap completing at 0.738 s. The sheet was still loading during the 3.841–4.309 s observation, over 3.10 s after tap completion. SendAmount was first observed by 6.539 s from tap-command start. This fails the journey's three-second target; the existing latency follow-up is bitkit-ios#868 Contact payment latency on staging.
contact-handoff-2x.2x.mp4
Test 3: Compact Receive after master integration ✅ QR decoding, Copy, network round-trip, scrolling details and footer reachability pass.
At normal and largest text on the iPhone SE, I decoded the displayed Bitcoin and USDT QR captures with Core Image. USDT Copy produced the plain displayed address, checked from the clipboard, without opening Network. The network-selection round-trip retained Arbitrum, details scrolled, and the Savings, Spending and USDT footer actions remained reachable. The existing largest-text Edit/Copy/Share label clipping is tracked in the shared accessibility follow-up above.
receive-integration-2x.2x.mp4
I retained these passing reports for unchanged behavior:
- Previous review at fff038e: deterministic endpointless-contact failure/retry and all-row locking.
- Wallet and activity review: wallet transitions and saved USDT activity. Receive was rerun above.
- Paired hardware-wallet review: unchanged hardware vendor label.
Scope: I reviewed the contiguous fff038e…1780ff2 delta and outstanding QA; its only change is whitespace in ActivityRow.swift, checked in source without a separate device case. No cases remain unrun in this plan. This run adds no 320-point, Figma or physical-hardware coverage.
Twin: bitkit-android#1565 fix: stabilize usdt wallet and payment layouts at a4ce71c matches the two new journey files byte-for-byte; Android was not rebuilt in this run.
Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest
jvsena42
left a comment
There was a problem hiding this comment.
Device gate (partial): 1780ff2 on iPhone 17 (simulator, 402 pt, iOS 26.5). One LOW from the device is inline: the Bitcoin QR and its buttons sit lower than on master.
paykit-amount-layout.xml: steps 1-6 passed.- BTC/USD switching keeps the controls, divider, keypad and Continue at the same y in every state, including AX-XL and AX5.
- At AX5, Continue is reachable by scrolling.
- A subscription amount from 0 accepts the first digit.
- A USD amount accepts USDT only, and a BTC amount accepts Savings only.
usdt-wallet-receive-layout.xml: steps 1-4 and 7 passed.- Opaque push transitions, and Show Details clear of the home indicator on every tab.
- "Network: Arbitrum One" is shown, and Copy copies the plain address.
- At AX5 the USDT QR now fits above Edit/Copy/Share, where on master it overflows under them.
⚠️ Not run:- step 7 of
paykit-amount-layout.xmland step 6 ofusdt-wallet-receive-layout.xml(compact width): no compact simulator on this Mac, and I'm reusing the existing ones; - step 5 of
usdt-wallet-receive-layout.xml(hardware tab label): needs the Trezor emulator paired; payment-requests/contact-request-or-pay.xml: two-party, pending a cross-device run with Android.
- step 7 of
Seen on master too, not from this PR:
- At AX5 the Edit/Copy/Share labels break mid-word.
- A USD subscription amount re-converted through BTC drifts 1,50 → 1,51.
- With region en-BR, the USD asset uses "," while BTC-in-USD uses ".".
The remaining items, and the code/review follow-up, will come in a separate review.
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Scope: Follow-up review of b17f49c since 1780ff2, using the baseline QA review. Inherited coverage: saved-contact row disable and cleanup, request and subscription amount layout, compact QR decode plus the paykit-amount-layout, usdt-wallet-receive-layout, and contact-request-or-pay journeys, and Android parity at a4ce71cd for contact disable and zero-USD initialization. This pass rechecked the shared QR logo layout and its receive callers, the new tall-container sizing test, and Android QR logo geometry at a4ce71cd12ed.
No new actionable code findings.
The logo GeometryReader is an overlay on the QR container, so Savings, Spending, hardware, and USDT codes keep the square image height. That removes the extra vertical space measured on Savings at 1780ff2 in the device comment. The logo stays centered at min(68, 20% of the shorter side), with the inner image at 50/68, matching Android QrCodeImage's square container and the same ratio. Profile and address-viewer codes pass no logo.
The author reports that all four QR/sharing tests passed on this commit, including the new square-layout case. This review did not run them. Run Tests was still in progress; Run Integration Tests had passed. Device testing was not performed in this review; the position measurements are from 1780ff2. Keypad legibility (#1036) and contact preparation latency (#868) remain the previously deferred journey gaps.
Device testing: not performed in this review.
Suggested additional test cases
- iOS, iPhone 17 simulator, iOS 26.5, same wallet as the 1780ff2 Savings measurement: open Receive on Savings and confirm
QRCodey is 258 andReceiveCopyQRy is 644, matching mastercf2b97e. Switch between Savings and USDT and confirm the vertical jump is about 6 pt. Scan the displayed Bitcoin and USDT codes.
piotr-iohk
left a comment
There was a problem hiding this comment.
Approve at b17f49c. Current-head review and targeted device checks confirm the QR correction; amount entry, scrolling and contact-row disabling are covered.
The remaining largest-text caption/keypad issues also reproduce on master and remain separate follow-ups, including #1036. Contact-preparation latency remains tracked in #868. These are not blockers for this PR.
|
CI follow-up: the new merge-checkout formatting job fails on Electrum/RGS Settings from master |
|
@ben-kaufman the red SwiftFormat check here comes from master's own files, which #1040 fixed (merged). Syncing this branch with master turns it green; if it still fails after that, run SwiftFormat 0.64.0 on this PR's changed files. |
There was a problem hiding this comment.
Verdict: ⛔️ Request changes — two existing journey assertions remain unpassed at 17e6533.
Findings: I found no new defects in the 1780ff2..17e6533 delta. The QR square-layout correction and USDT footer fix hold on the simulators. The failures below are the previously deferred keypad and contact-latency issues.
QA for 17e6533: I built this head and tested iPhone SE (375 pt) and iPhone 17 (402 pt) simulators on iOS 26.5, using disposable wallets and fixture USDT. No payment, request or subscription was submitted. Videos play at 2×; timings use the original run.
Test 1: Compact amount entry at largest text ❌ Fresh entry, preserved cents, stable controls and scrolling work; the shared 000 label still reads 0….
A fresh USD request and a subscription with USDT selected before opening Amount both accept 1.50 without Delete. Continue and reopening retain the cents. Accessibility bounds match for the divider and keypad across BTC/USD in both editors; scrolling fully exposes Continue. The Bitcoin keypad keys were tapped, and clearing the request then entering 1 and 000 produces 1,000 sats. The visible 000 label remains truncated, as tracked in bitkit-ios#1036 Keep the 000 keypad label readable at largest text. The subscription's USD details retain USDT selected and Savings unselected.
amount-largest-2x.2x.mp4
amount-fresh-2x.2x.mp4
amount-request-2x.2x.mp4
Test 2: Funded contact-detail Request or Pay ❌ One warm handoff exceeds three seconds; the repeat is faster.
Both attempts show progress with Request disabled, then open one SendAmount screen. Closing permits another attempt, and Request opens PaymentRequestAmount.
After more than a minute in the foreground, the first monotonic probe records the physical tap completing at 0.620 s. The sheet is still loading during the 3.968–4.365 s observation, more than 3.34 s after tap completion; SendAmount is first observed by 6.164 s from command start. On the repeat, the tap completes at 0.631 s and SendAmount is observed by 3.122 s. The first run leaves the timing assertion failed; the variable latency remains tracked in bitkit-ios#868 Contact payment latency on staging with the shared Paykit runtime: pin paykit-rs#171 and re-measure.
contact-latency-2x.2x.mp4
Test 3: Standard-size Receive footer and Bitcoin QR ✅ The Bitcoin QR returns to its earlier position, and Savings/USDT keep the footer anchored.
At normal text on iPhone 17, Savings QR y=258 and Copy y=644 match the earlier master comparison. Show Details is y=784 on both Savings and USDT. At the largest text size, their button heights differ but the bottom edges remain at y=840. Spending retains its Lightning onboarding footer because this wallet has no channel.
Core Image decodes the captured Bitcoin and USDT displays at both text sizes to their expected payment URIs. USDT Copy matches the plain address from the clipboard. The Network round-trip retains Arbitrum One and Show Details opens the address.
receive-tall-2x.2x.mp4
Test 4: Compact Receive Copy and QR ✅ The QR fits above the actions, Copy reaches the address, and the footer remains reachable.
On iPhone SE, Show Details is y=595 on both Savings and USDT at normal text. At the largest size, both bottom edges remain at y=651. USDT Copy remains separate from Network and copies the plain receiving address without opening network selection. Core Image decodes displayed Bitcoin and USDT codes at both sizes. The Arbitrum network round-trip and scrolling address details work. Existing largest-text Edit/Copy/Share caption clipping remains visible.
receive-compact-2x.2x.mp4
I retained these reports for passing assertions whose implementation the later pushes leave untouched:
- Earlier contact failure/retry and all-row locking report.
- Wallet transitions and saved USDT activity report.
- Paired hardware vendor-label report.
Scope: I reviewed the contiguous 1780ff2…17e6533 delta and outstanding feedback. Both changed runtime components were driven; the two added hosted regressions were source-reviewed. No planned case remains unrun. Device widths were 375 and 402 points; a fresh Figma comparison was unavailable.
Twin:
- bitkit-android#1565 fix: stabilize usdt wallet and payment layouts at
aba8c0fmatches the new journey files and the square QR container with its 20% / 68-point logo sizing. This was a source comparison.
Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest
|
Synced with master in 7d68cf1, including the merged #1040 correction. Full SwiftFormat 0.64.0 now passes (0/831 files), translation validation has zero errors and the same 14 base warnings, and independent review confirms the Receive spacer/QR fixes and master's swipe behavior are preserved. The previous CI run completed its tests successfully before cancellation in post-cache cleanup. The integration is formatter-equivalent to that tested runtime tree; current-head SwiftFormat and translation validation are now green. Unit/integration tests and the E2E build remain in progress. All 13 PR commits are verified locally and on GitHub. The PR description now includes the latest successful Receive device checks while keeping #1036 and #868 explicit. |
piotr-iohk
left a comment
There was a problem hiding this comment.
QA review
Scope: Full reassessment of the entire PR diff against merge base 039c7b51, at 7d68cf1. No verified coverage baseline was supplied, and the comparison base changed since the saved assessment, so no earlier coverage was inherited.
1 actionable finding — resolve or provide an evidence-backed rebuttal.
The BTC unit control does not join the denomination buttons in the horizontal row ViewThatFits measures. Contact-row disabling, empty zero-USD entry, the QR logo overlay, and the USDT footer spacer are otherwise consistent with the behavior measured on earlier commits in this PR. The merge after those measurements adds the master swipe-between-tabs gesture on the USDT receive container and does not rewrite those views.
Run Tests, SwiftFormat, and translation validation passed on this head. Run Integration Tests was cancelled at the one-hour limit after Blocktank/regtest timeouts in channel-purchase and address-type cases. This review did not build the app or run a simulator. Device testing: not performed here. Simulator measurements on 17e6533 still show Show Details aligned across Savings and USDT, including iPhone SE, and the amount divider staying put; those views were not rewritten afterward. The contact handoff remains over the journey's three-second target (#868), and the shared keypad 000 label still truncates at the largest text size (#1036). Compared contact disabling and the amount screen with bitkit-android#1564 at afcf6ff4: Android disables every row while a contact resolves, and it keeps the unit control on its own trailing row.
Suggested additional test cases
- iOS simulator, iPhone 17 width, normal text, USDT enabled, onboarded wallet with a rate. Open a payment-request amount, select BTC, and leave the text size at the default. Expected: BTC, USD, and the Bitcoin unit control sit on one trailing row, with no blank row between that row and the divider. Switch to USD and back. Expected: the divider and keypad do not move. Repeat at the largest accessibility text. Expected: only the unit control wraps to a second trailing-aligned row.
Findings
- [LOW] Unit control always stacks under the denomination buttons — inline at
Bitkit/Views/PaymentRequests/CreatePaymentRequestView.swift:420.
There was a problem hiding this comment.
Verdict: ⛔️ Request changes — the existing keypad-legibility and contact-timing journey assertions remain unpassed at 7d68cf1.
Findings: I found no new code defects in the delta. The unit-control report does not reproduce in either actual editor: the controls share one row when they fit and wrap at enlarged text, confirming the author’s rebuttal. The failures below remain the explicitly deferred shared-control and latency issues.
QA for 7d68cf1: I built this head and tested iPhone SE (375 pt) and iPhone 17 (402 pt) simulators on iOS 26.5, with mutually saved and linked disposable identities and a payer funded with fixture USDT. No payment, request or subscription was submitted. Videos play at 2×; timings use the original run.
Test 1: Request and subscription unit-control rows ✅ The unit control shares the normal-size row and wraps below it at the largest text size.
On iPhone 17, both actual editors show BTC, USD and Bitcoin in one trailing row at default text. At the largest accessibility size, only the unit button wraps into the second trailing row. BTC → USD → BTC preserves the divider and keypad positions. Accessibility measurements put the divider / first keypad row at y=343.33 / 408.33 at default text and y=539.67 / 556.67 at the largest size, in both denominations and both editors.
unit-controls-2x.2x.mp4
Subscription amount controls, default and largest text.
unit-request-2x.2x.mp4
Payment-request amount controls, default and largest text.
Test 2: Compact amount entry at largest text ❌ Fresh entry, preserved cents and scrolling work; the shared 000 label still reads 0….
On iPhone SE, a fresh USD request and a subscription with USDT selected before opening Amount both accept 1.50 without Delete. Continue and reopening retain the cents, displayed as 1,50 in this locale. Accessibility bounds confirm stable divider and keypad positions across BTC/USD. Scrolling exposes all keys and Continue; every Bitcoin keypad key was tapped in both editors. The visible 000 label still truncates, so its legibility assertion remains failed under synonymdev/bitkit-ios#1036 Keep the 000 keypad label readable at largest text.
amount-largest-2x.2x.mp4
Fresh USDT-first subscription entry, reopening and compact keypad.
amount-request-2x.2x.mp4
Fresh USD request entry, reopening and compact keypad.
Test 3: Funded warm contact Request or Pay ❌ The repeat exceeds three seconds; loading disables Request and each attempt opens one amount screen.
Both Pay attempts show progress with Request disabled and open one SendAmount screen. Closing permits retry, and Request opens PaymentRequestAmount. The send screen shows the payer’s 25 fixture USDT available balance.
The first monotonic probe records physical tap completion at 0.621 s and first observes SendAmount by 3.405 s from command start. On the repeat, the tap completes at 0.682 s; the 3.812–4.312 s observation still shows loading with Request disabled, more than 3.13 s after tap completion. SendAmount is first observed by 5.933 s. This leaves the three-second assertion failed; the existing investigation remains synonymdev/bitkit-ios#868 Contact payment latency on staging.
contact-latency-2x.2x.mp4
Warm first attempt, closing and retry, then Request opening the amount editor.
Test 4: Integrated USDT Receive swipe and Copy ✅ Swipes change tabs without a copied tooltip, and a tap still copies the address.
On iPhone SE, a right swipe over the USDT QR selects Spending and shows its Lightning onboarding content. A 600 ms left swipe returns to USDT. A left swipe over the last USDT tab leaves it selected. Immediate full-resolution captures show no copied tooltip after either USDT swipe. Tapping the QR shows the tooltip and copies the plain receiving address, independently checked from the clipboard. Network: Arbitrum One and Show Details remain visible; their compact positions remain y=539 and y=595 after the round-trip.
receive-swipes-2x.2x.mp4
Compact Receive tab swipes and QR tap-to-copy.
I retained these passing reports where the later merge leaves the tested implementation untouched:
- Previous QR decoding, standard/compact Receive footer and Copy report.
- Prepared endpointless-contact failure/retry and all-row locking report.
- Opaque wallet transitions and saved USDT activity report.
- Paired hardware vendor-label report.
Scope: I reviewed the contiguous 17e6533…7d68cf1 delta and outstanding feedback. The overlapping USDT swipe integration was driven; imported master settings/reset, identifier, dependency and documentation changes were source-reviewed outside these layout journeys. No planned case remains unrun. This run adds no 320-point device or fresh Figma comparison. I did not rerun the separate native integration suite; its current-head CI run remains unsuccessful.
Twin:
- synonymdev/bitkit-android#1565 fix: stabilize usdt wallet and payment layouts at
aba8c0fmatches both new journey files byte-for-byte and the square QR container’s 20% / 68-point logo sizing. This was a source comparison; Android was not rebuilt here.
Reviewed by gpt-6.1-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest
|
Resolved the new master conflict in ac54f6e. The compact Receive QR and anchored footer remain, and master’s USDT copy confirmation is preserved on both QR and address-details paths, along with tab wrap behavior. Validation on the final tree: 33 focused tests; 2,833 canonical unit executions plus 39 UI executions passed, with four fixture skips explicit. Full SwiftFormat is clean; all 15 translation warnings match actual master. Complete diagnostics/xcresult and a fresh independent integration review are recorded in the updated QA notes. All 14 actual-base PR commits are locally verified and GitHub-verified ( J1–J3 remain unchecked for their previously documented device/fixture gaps; no new funded/provider journey is implied. Re-requesting ovitrif and jvsena42 for the integration. |
Refs #974. Matches the contact-picker behavior in synonymdev/bitkit-android#1564.
Description
Out of Scope
Shared keypad accessibility: Keep the 000 keypad label readable at largest text #1036 tracks the existing
000label truncation at the largest text size (device review). The keypad is unchanged from master; its legibility assertion remains unpassed.Contact preparation latency remains tracked in Contact payment latency on staging with the shared Paykit runtime: pin paykit-rs#171 and re-measure #868. The latest device review still measured variable delays beyond the three-second journey target; that assertion remains unpassed.
Deterministic contact-failure journey setup across the sibling PRs: Align contact-resolution failure setup across QA journeys #1031 (review thread).
This PR does not redesign the BTC/USD selector or master’s receive-network warning.
Payment conversion, subscription method exclusivity and copied address/share payloads remain unchanged; master’s USDT-specific copy confirmation is retained.
Design
Request amount — Handoff v62 and amount layout — Refactor v63. Reuses existing typography, buttons, colors and divider; the undecided selector variant is retained.
Preview
Before/after captures were taken at 320/375-point widths with normal and accessibility text, including the scrolled keypad/Continue view. Live Receive captures confirm the network remains visible. Screenshots are available in the author’s local review gallery.
QA Notes
Setup
Use PR commit
ac54f6e8d4d3e3c68aee3a6e17661f259990c026, preserving the pinnedPackage.resolved(Core0.8.0-rc9atfab768db, Paykit0.1.0atdd8e75e5, LDK0.7.0-rc.77). Follow the repository’s simulator setup and payment-request fixture recipe resolved at mastera61e0c44. Configure an E2E/regtest test wallet with Paykit and USDT enabled; use test identities, never a personal seed. J1 needs a saved linked test contact and a current BTC/USD rate; cancel before publishing a request. J2 needs an onboarded wallet and a paired hardware test wallet for its vendor-label step; copy/scan without creating a deposit. J3 needs two linked test installs, payable endpoints and the separate no-endpoint failure fixture described by the journey; its full recipe requires regtest funds, which were not used in this maintenance run. Preserve existing wallets and do not reset them. Review J1/J2 on compact and standard screens at normal and largest text. The deterministic J3 failure fixture remains tracked in #1031; an unavailable fixture is a gap, not a pass.The hosted validation below uses Xcode 27.0 (
27A266a), iOS 26.1,xcodebuildmcp2.7.0, one worker and the dedicated unfunded unit-test simulator; CI uses Xcode 16.4. It does not substitute for J1–J3. IDs are newly added to the existing three cases for stable references, without changing their expectations or claiming new execution.Journeys
paykit-amount-layout.xml— request/subscription alignment, fresh USDT amount entry, preserved cents, legible keypad keys, scrolling to Continue and enlarged-text reachability.usdt-wallet-receive-layout.xml— cross-platform wallet transition, Receive footer and network/vendor-label parity, compact Copy hit target and displayed QR scan.contact-request-or-pay.xml— selected-row progress, all-row disabling and duplicate-payment protection.Manual Tests
N/A
Automated Checks
150.50directly from zero and edited an existing150.50to150.55; Continue preserved the exact amount, note and expiry. The fixture was removed after validation.Earlier validation passed three receive-sharing tests, including decoding the actual USDT and Bitcoin QR components with logos at compact and normal heights. Isolated Receive renders at 320/375 pt with normal/largest text keep actions separate from Network; all four rendered USDT codes decode correctly. Simulator Receive tab checks passed. A paired hardware-wallet journey and an end-to-end contact payment were not rerun in this follow-up; the duplicate guard and awaited navigation were source-reviewed. SwiftFormat reports no changed-file findings. At that earlier revision, translation validation reported no errors and 14 warnings verified unchanged from its base. Compiler warnings were also checked against unchanged base lines.
testQrLogoPreservesSquareLayoutInTallContainerinUsdtReceiveSharingTests.swift— QR with Bitcoin/USDT logos and without a logo stays square when its parent offers extra height, at compact and normal widths. Existing rendered QR decoding coverage remains.The focused layout validation compiled the app and all test targets with Swift warnings treated as errors. All five Receive layout/QR-sharing tests passed, including square QR layout, Bitcoin/USDT QR decoding, share contents and full-height USDT content at compact/normal widths with normal/largest text. The new full-height regression failed against the previous code and passes with the flexible spacer that anchors Network and Show Details.
The latest device review confirms stable Receive footer positions, displayed QR decoding, plain-address copying and network switching on iPhone 17 and SE at normal/largest text sizes. The shared keypad legibility issue (#1036) and variable contact latency (#868) remain explicit exceptions; the whole journeys above are therefore not marked passed.
Synced with master
039c7b51, including the merged #1040 formatter correction. Full-repository SwiftFormat 0.64.0 passes (0/831 files need changes); translation validation has zero errors and 14 warnings checked against the base. Independent integration review confirms the Receive fixes and master's swipe behavior are preserved.CI run 39448955514 completed 2,712 tests with zero failures, plus 43 integration tests with four skips and zero failures, before cancellation during post-test cache cleanup. Its tested merge tree and this final integration differ only in Transifex docs/config/scripts and two Settings files whose changes exactly match SwiftFormat 0.64.0 output. No new local native run was performed for that formatter-equivalent integration. The CI log contains dependency linker warnings; this is not a claim of warning-free CI. Prior-head SwiftFormat CI and translation validation are green. At the prior head
7d68cf13, unit tests, the E2E build and the configured E2E CI job have passed. This does not close the outstanding manual journey assertions listed above. The separate integration run 39465856741 was cancelled at its 60-minute limit after real regtest failures: Blocktank mining/transport errors, balance waits and channel-purchase readiness assertions. It is not a passing run or a post-cache cancellation. The then-current master integration run 39459205073 independently failed the same channel-purchase flow and encountered Blocktank transport/HTTP 500 errors before timing out. That investigation found those integration tests, workflow and payment services unchanged by the PR against its then-current base. No integration assertions were weakened or unchanged jobs repeatedly rerun; this validation remains blocked.Targeted follow-up render on
7d68cf13confirms one trailing control row at 402 pt/default text and wrapping at 320 pt/accessibility5, with stable BTC/USD divider positions. A temporary helper-layout probe passed (158 × 28 pt); the fixture was removed and production code remains unchanged. This is targeted layout evidence, not a complete accessibility or payment-journey pass.Current master integration —
ac54f6e8Merged actual master
a61e0c44with a normal signed merge. The sole manual conflict retains the compact QR/scrolling-details/full-height footer layout and passes master’s USDT-specific copy confirmation through bothQrAreaandCopyAddressCard; tab wrap behavior remains intact. Other PR changes are preserved, and everything outside the PR diff matches that master. Independent frozen-tree review found no introduced correctness or repository-pattern issue.a61e0c44verify locally and match the exact GitHub PR commit set, eachverified=true/reason=valid. New-head CI is running and is not yet claimed green.Evidence is retained in the author checkpoint
usdt-monitor-20261022-2149(test arguments, full logs, xcresult reports, base-warning comparison and independent review). J1–J3 were not rerun as complete device journeys in this integration. Existing keypad/latency/failure-fixture gaps above remain open, as do paired-hardware and funded/provider validation; prior device and CI evidence remains tied to its original revisions. No payment, wallet reset or deployment was performed.Models used
gpt-6-astra(reasoning:xhigh)gpt-6-astra(reasoning:xhigh)gpt-6-astra(reasoning:xhigh)Model metadata for this integration and its independent frozen-tree gate was checked against the actual parent/reviewer session and turn records. Earlier review evidence remains attributed to its linked reviews.