Skip to content

fix: spread pasted seed fragment - #1296

Open
jvsena42 wants to merge 14 commits into
masterfrom
fix/896-spread-pasted-seed-words
Open

jvsena42 wants to merge 14 commits into
masterfrom
fix/896-spread-pasted-seed-words

Conversation

@jvsena42

@jvsena42 jvsena42 commented Sep 17, 2026

Copy link
Copy Markdown
Member

Fixes #896
Related to #1275

This PR spreads a pasted partial recovery phrase across the Restore wallet word fields and keeps every field editable with Backspace.

Description

  • Spreads a pasted fragment of any length other than a full phrase across the fields from the one it was pasted into, so a partial paste no longer lands whole in one field.
  • Switches the form to 24 words when the pasted words run past field 12, and drops words beyond field 24.
  • Revalidates only the fields the paste wrote, then moves focus to the next empty field, or to the first field holding an invalid word when no field is empty, and hides the keyboard only when the phrase is complete and valid.
  • Re-requests focus when a paste switches the form between 12 and 24 words, so the field the view model points at is the one that holds the caret even when the focused index does not change.
  • Keeps the full replace for a 24-word paste into any field and a 12-word paste into field 1, and spreads 12 words pasted into a later field when other fields already hold words, so pasting the second half of a 24-word phrase keeps the first half.
  • Fixes Backspace being swallowed after a paste, because the field checked the saved word instead of its own text.
  • Drops a typed space instead of forwarding it as a paste, so editing a filled field to aban don no longer writes don over the next field; only an insertion longer than one character is spread.
  • Serializes word edits, so a word typed while a paste is still validating is no longer undone when the paste finishes.
  • Keeps the cursor at the end of a word copied into a field after a paste, so Backspace and typing edit the end of the word.

Out of Scope

  • iOS: the restore screen there has the same 12/24-only paste guard and needs a matching follow-up.
  • RestoreWalletViewModel: once a paste switches the form to 24 words, only a 12-word paste into field 1 switches it back.
  • journeys/restore-wallet: the new journey is committed but its onboarding route has not been run on a device without a wallet.
  • Restore wallet subtitle copy differs from Figma ("recovery phrase" vs "12 seed words"); this predates the change.

Design

There is no paste-specific design.

Preview

Screens use public BIP39 test words. The C3 and C9 buttons at the top right come from a temporary dev harness that copies test words to the clipboard and are not part of the app.

Figma Before After: fragment spread
figma-restore-wallet before-fragment-stuck after-fragment-spread
Figma: suggestions After: Backspace edits previous word After: phrase completed
figma-restore-wallet-suggestions after-backspace after-phrase-completed

QA Notes

Manual Tests

  • 1a. Onboarding → Restore wallet → paste abandon abandon abandon into Word 1: Words 1-3 show abandon and Word 4 is focused.
    • 1b. Backspace in empty Word 4: focus moves to Word 3.
    • 1c. Backspace again: Word 3 shows abando.
  • 2. Restore wallet with Words 1-3 filled → paste the remaining 9 words into Word 4: all 12 fields filled, keyboard hides, Restore enabled.
  • 3. Restore wallet → paste 9 words into Word 12: Words 12-20 filled, form switches to 24 words, Word 21 focused.
  • 4. regression: Restore wallet → paste a full 12-word phrase into Word 1: phrase restores as before.
  • 5. regression: Restore wallet → paste a full 24-word phrase into Word 1: form switches to 24 words and all fields fill.
  • 6. 24-word layout with Words 1-12 filled → paste the other 12 words into Word 13: Words 1-12 kept, Words 13-24 filled.
  • 7. Restore wallet with Words 1-2 filled → place the cursor inside Word 1 and type a space: Word 1 keeps its word and Word 2 is unchanged.
  • 8. Restore wallet with Words 1-9 filled with valid words → paste zzzz ability able into Word 10: Words 10-12 fill, Word 10 shows the error state and keeps focus with the keyboard up, and typing in it still shows suggestions that can be tapped.
  • 9. Restore wallet → paste a full 12-word phrase containing one invalid word into Word 1: the first invalid field takes focus and the keyboard stays up.
  • 10. Restore wallet (12-word layout) → tap Word 7 → paste a full 24-word phrase whose word 7 is invalid: the form switches to 24 words and Word 7 keeps focus with the keyboard up, the caret is not left on Word 13, and tapping a suggestion writes into Word 7 only.

Steps 1-3 were run on an emulator through a temporary dev harness that opens the Restore wallet screen without wiping the wallet. The journey is committed at journeys/restore-wallet/paste-seed-fragment.xml and follows the same steps from onboarding. It now fills the clipboard from the host (pbcopy/xclip, picked up over emulator clipboard sharing) instead of leaving "copy from another app" undefined, since cmd clipboard is unimplemented on the emulator image and input text drops characters; each paste is followed by a check that reports a short paste as a clipboard setup failure. Its onboarding route has not been run on a device without a wallet.

journeys/restore-wallet/paste-seed-fragment.xml
diff --git a/journeys/restore-wallet/paste-seed-fragment.xml b/journeys/restore-wallet/paste-seed-fragment.xml
new file mode 100644
index 000000000..bb12ec8e8
--- /dev/null
+++ b/journeys/restore-wallet/paste-seed-fragment.xml
@@ -0,0 +1,23 @@
+<journey name="paste seed fragment">
+  <description>Proves #896: pasting part of a recovery phrase on Restore wallet spreads the words across the word fields, and every field stays editable with Backspace. Precondition: a throwaway emulator with no wallet (Restore is reachable only from onboarding; never run this on a device holding a wallet you need). Both pasted strings are BIP39 test vectors — "abandon abandon abandon" and "abandon abandon abandon abandon abandon abandon abandon abandon about". Use only these public test words, never a real wallet's phrase. Neither string can be put on the clipboard from the device: `adb shell cmd clipboard` is not implemented on the emulator image and `adb shell input text` drops characters from long strings (journeys/README.md:78-79), and a dropped character would fail the word assertions as if the app were at fault. So the clipboard is filled on the host and the emulator picks it up over clipboard sharing (Extended controls > Settings > General > "Enable clipboard sharing", on by default). Each copy action below gives the host command and is followed by a check that the words arrived whole; a short or empty paste there is a clipboard setup failure, not an app failure — re-copy and repeat the paste before reading it as a journey failure. Paste is sent as KEYCODE_PASTE (279) to the focused field.</description>
+  <actions>
+    <action>On the host, run `printf 'abandon abandon abandon' | pbcopy` (macOS) or `printf 'abandon abandon abandon' | xclip -selection clipboard` (Linux), then give the emulator window focus by clicking its title bar — not the device screen — so the shared clipboard reaches the guest</action>
+    <action>Launch to.bitkit.dev on a device with no wallet</action>
+    <action>Verify that the terms screen shows "Check1" and "Check2", then tap "Continue" — the two blocks are text, not toggles, and "Continue" is always enabled</action>
+    <action>Tap "SkipIntro"</action>
+    <action>Tap "RestoreWallet"</action>
+    <action>Tap "MultipleDevices-button"</action>
+    <action>Verify that the Restore wallet screen shows word fields "Word-0" to "Word-11", all empty</action>
+    <action>Tap "Word-0" and run `adb shell input keyevent 279`</action>
+    <action>Verify that "Word-0", "Word-1" and "Word-2" each show "abandon", "Word-3" is empty and focused, and "Word-0" does not show the whole pasted text — if the three fields are empty, or any of them shows a truncated word such as "abandn", the clipboard did not cross from the host whole: re-copy on the host, tap "Word-0" and paste again, and report a clipboard setup failure rather than an app failure if it repeats</action>
+    <action>Run `adb shell input keyevent 67`</action>
+    <action>Verify that "Word-2" is focused and still shows "abandon"</action>
+    <action>Run `adb shell input keyevent 67`</action>
+    <action>Verify that "Word-2" shows "abando", so Backspace deletes from the end of the pasted word</action>
+    <action>Run `adb shell input text n`</action>
+    <action>On the host, run `printf 'abandon abandon abandon abandon abandon abandon abandon abandon about' | pbcopy` (or the `xclip -selection clipboard` equivalent) and give the emulator window focus by clicking its title bar, then tap "Word-3" and run `adb shell input keyevent 279` — the app stays on the Restore wallet screen throughout, so nothing has to be typed on the device</action>
+    <action>Verify that "Word-0" to "Word-10" show "abandon", "Word-11" shows "about", no word field is focused and the keyboard is hidden — a truncated word or a short field count here means the nine-word copy did not cross whole, which is a clipboard setup failure: re-copy on the host and repeat the paste before reading it as an app failure</action>
+    <action>Verify that "RestoreButton" is enabled, and do not tap it</action>
+    <action>Press the device back button</action>
+  </actions>
+</journey>

Automated Checks

  • Unit tests added: RestoreWalletViewModelTest.kt covers fragment spread from the first and middle fields, switching to 24 words, dropping words past field 24, invalid word flags, trailing-space words, whitespace-only input, focus and keyboard handling, when a 12-word paste replaces or spreads, that a word typed during a pending paste validation survives, and that a paste leaving an invalid word focuses that field so its suggestions and suggestion taps keep working. MnemonicInputPasteTest.kt covers telling a paste from a typed space.
  • Not unit tested: re-requesting focus on a 12/24 switch lives in a LaunchedEffect in RestoreWalletScreen, and compose.ui.test.junit4 is androidTestImplementation only, so nothing in app/src/test can observe it. Manual test 10 covers it.
  • UI tests added: MnemonicInputFieldTest.kt covers whitespace text not kept in the field, a typed space not reaching the view model, showing only the saved word after a paste, Backspace deleting from the end, and Backspace in a field with text not jumping to the previous field. It compiles but has not been run, since connected tests were not run for this PR.
  • Local: just compile, just test and just lint pass.

jvsena42 and others added 3 commits September 16, 2026 20:51
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42 jvsena42 self-assigned this Sep 17, 2026
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

This PR is not yet safe to merge because routine whitespace input and overlapping edits can replace recovery words the user already entered.

Findings

  1. P1 Spaces overwrite recovery words
  2. P1 Older edits can overwrite newer

Summary

This PR expands restore-wallet paste handling so partial recovery phrases are distributed from the selected field, updates focus and validation afterward, and makes the text field’s local cursor and Backspace behavior follow the displayed text.

  • Adds fragment spreading with 12/24-word layout transitions and truncation at 24 fields.
  • Preserves full replacement for complete phrases under the documented conditions.
  • Adds view-model and Compose UI regression coverage.
  • Introduces ordinary-whitespace and asynchronous event-ordering paths that can overwrite recovery-word edits.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Recovery field value changes] --> B{Contains whitespace?}
  B -- No --> C[Update one word and suggestions]
  B -- Yes --> D[Split into words]
  D --> E{24 words or eligible 12-word phrase?}
  E -- Yes --> F[Replace all fields]
  E -- No --> G[Spread from selected field]
  F --> H[Recompute phrase validation]
  G --> I[Select next empty field]
  I --> H
Loading

Reviews (1) · Last reviewed commit: "fix: keep cursor at end of synced seed w..."

Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt
Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt
@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Regtest APK

Built from 829f17c (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt Fixed
Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt Fixed
Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt Fixed
Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt Fixed
Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt Fixed
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no HIGH/MEDIUM findings at head 097ab79a9. (Posted as a comment because GitHub does not allow approving your own PR.)

Inline: LOW — spread that completes the phrase with an invalid word leaves the pasted field focused but focusedIndex null

Checked: Traced MnemonicInputField.onValueChange at the PR head: non-whitespace input updates the local TextFieldValue and the view model together; whitespace input is forwarded only when isPastedInput sees an insertion longer than one character after subtracting a replaced selection, so a typed space is dropped and the controlled field reverts. In the view model, handlePastedWords, replaceAllWords, spreadWords and updateWordValidity all run under wordEditMutex and build the new word list inside _uiState.update, so an older edit cannot resurrect pre-paste words (the two greptile P1 threads are fixed in 4af0ab9 and the four detekt line-length threads are cleared by 097ab79; no line in the changed files exceeds 120 chars). spreadWords writes pastedWords.take(24 - startIndex) at startIndex..lastWrittenIndex, switches to 24 words only when lastWrittenIndex >= 12, and the 12-word layout never holds words at 12..23 because the only 24->12 transition (replaceAllWords with 12 words) clears them, so bip39Mnemonic (subList(0, wordCount)) and hasNoWordsExcept stay consistent. The 12->24 switch re-creates focusRequesters keyed on wordCount in the same state emission as focusedIndex, nextEmptyIndex is always < the new wordCount, and column-two nodes that change index positionally are re-synced by LaunchedEffect(value) because their value key changes. The 12-word full-replace rules (field 1 always; a later field only on an otherwise-empty 12-word form) and the no-way-back from 24 words are explicitly documented in the PR body and not re-raised. Passphrase handling is untouched; RestoreWalletViewModel has no Logger calls and the restore path (WalletViewModel.restoreWallet -> WalletRepo.restoreWallet) logs only a generic error without the mnemonic. No iOS twin PR exists; the PR body lists iOS as a follow-up.

Comment thread app/src/main/java/to/bitkit/viewmodels/RestoreWalletViewModel.kt Outdated
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no HIGH/MEDIUM findings at head 9c9d483de. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Follow-up on 9c9d483: the reported focus case is fixed. One LOW the new commit introduced (12->24 switching paste from a column-two field) is posted as a reply on the earlier thread; restore stays gated by checksum, so it is not blocking. Follow-up on 9c9d483 (delta over 097ab79). The original LOW is fixed on the path it described: spreadWords (RestoreWalletViewModel.kt:175) falls back to the first invalid index within wordCount only when no empty field remains, so zzzz ability able into field 10 with fields 1-9 filled now yields focusedIndex=9, scrollToFieldIndex=9 and shouldDismissKeyboard=false; the field stays OS-focused, isError stays hidden on it, updateSuggestions(value, 9) resolves and onSelectSuggestion writes to index 9. shouldDismissKeyboard (line 181) is still true exactly when no empty field and no invalid index remain, so the valid-paste path is unchanged: focusedIndex=null, focus cleared, keyboard hidden, Restore reachable. replaceAllWords (line 151) now focuses invalidIndices.minOrNull(), which is < pastedWords.size <= the new wordCount, so focusRequesters[index] is in range after the 12/24 switch; a paste with all valid words still gives null/dismiss. Typed-space splitting (isPastedInput, RestoreWalletScreen.kt:438) and the wordEditMutex ordering are untouched by the delta. The three new tests fail on the previous code (they assert 9/4 where the old code produced null, and non-empty suggestions where focusedIndex=null cleared them). No Logger calls added; no seed material logged. One narrow over-correction remains and is replied on the original thread.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no HIGH/MEDIUM findings at head 66f701936. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Follow-up on 66f7019: keying the focus effect on wordCount fixes the 12->24 switching-paste LOW from the previous thread. Both state writers set is24Words and focusedIndex in one _uiState.update (replaceAllWords at RestoreWalletViewModel.kt:146-152, spreadWords at 177-185), and focusedIndex is always below the new wordCount, so the re-run cannot index past the focusRequesters list rebuilt at RestoreWalletScreen.kt:131. The effect runs after the recomposition that attaches the new requesters, the same ordering the focusedIndex key already relied on. The rest of the PR is unchanged since the approval at 9c9d483.

@jvsena42
jvsena42 requested a review from ovitrif September 18, 2026 13:26
jvsena42 and others added 2 commits September 18, 2026 10:40
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ed-seed-words

# Conflicts:
#	journeys/README.md

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no blocking HIGH/MEDIUM findings at head 5bea120c7. (Posted as a comment because GitHub does not allow approving your own PR.)

Inline: LOW — Clipboard setup gives no route, so runners fall back to input text or stop

Checked: Follow-up on 89920b3 (new journey): Round 4 delta is 89920b3 only: the new journey journeys/restore-wallet/paste-seed-fragment.xml plus two README rows. Every tag it names exists at head and the route matches OnboardingNav: Terms (Check1/Check2 are TermsText blocks, Continue is an always-enabled PrimaryButton) -> Intro SkipIntro -> last slide CreateWalletScreen RestoreWallet -> WarningMultipleDevices MultipleDevices-button -> Restore with Word-0..Word-11 and RestoreButton. Traced each step through RestoreWalletViewModel at head: 3 words into index 0 spread to 0..2 and focus 3; DEL in the empty Word-3 is consumed by onPreviewKeyEvent and moves focus to 2; the second DEL edits from the cursor end set by LaunchedEffect(value), giving abando; 9 words into index 3 end at 11 with no empty or invalid field, so focus clears, the keyboard hides and abandon x11 about passes the checksum, enabling Restore. With the fix reverted, step 8 fails (master's handlePastedWords ignores a 3-word paste, so Word-0 keeps the whole text and Word-1 stays empty), so the journey cannot pass on a regression. The phrase is the public BIP39 abandon x11 about vector, labelled public test words, and the journey never taps Restore, so nothing gets funded. No iOS twin exists, and the cross-platform row records it as not ported because the behaviour does not exist on iOS yet, which matches the SKIP rule.

Comment thread journeys/restore-wallet/paste-seed-fragment.xml Outdated
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — no blocking HIGH/MEDIUM findings at head 4403315af. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Follow-up: the earlier journey finding is fixed. Follow-up on 4403315: the earlier clipboard-route LOW is fixed. Checked the host route on the running emulator (Pixel_9, API 36 image, emulator 36.6.11, embedded in Android Studio): after printf '<nine-word vector>' | pbcopy the guest clipboard did not change while another app was frontmost, and brought to the front the emulator's host window, dumpsys clipboard showed a new 69-character text/plain primary clip within a second, matching the string length. So the step's instruction to focus the emulator window after copying is necessary and enough; the host clipboard was restored afterwards and the app was not touched. Neither long string goes through input text; the only typed input is the single character n. The added verify steps name the truncation and empty-paste symptoms and send them to a clipboard setup failure, so a failed copy cannot read as an app failure, and the copy-before-launch ordering matches the flow. The app-side tags and paste handling are unchanged by this commit.

ovi-reviewer[bot]

This comment was marked as resolved.

@ovitrif

ovitrif commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

@jvsena42 e2e red and conflicts

ovitrif

This comment was marked as resolved.

@ovitrif
ovitrif enabled auto-merge September 18, 2026 16:12
@jvsena42

Copy link
Copy Markdown
Member Author

Same as the others: covered centrally in #1275 (comment). The conflict is the shared journeys/README.md row, a merge of current master is running on this branch now, and the red e2e shards failed in setup rather than in an assertion.

I will confirm here once the merge lands and CI re-runs on the new head.

…ed-seed-words

# Conflicts:
#	journeys/README.md
ovi-reviewer[bot]

This comment was marked as resolved.

ovi-reviewer[bot]

This comment was marked as resolved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42

Copy link
Copy Markdown
Member Author

Test 6 is a real bug and it is fixed in d3ade08.

What happened. The paste did not land in an empty Word 13 — it landed in Word 12, which already
held about. MnemonicInputField forwarded newValue.text, i.e. the whole field after the paste,
so the view model received "aboutabout abandon×11 art": 13 tokens, spread from index 11. That is
exactly your screenshot — Word 12 aboutabout, Words 13–23 abandon, Word 24 art. The layout flip
to 24 words follows from the same spread (lastWrittenIndex >= WORDS_MIN).

Fix. The field now forwards only the text the paste actually inserted, not the word it was dropped
next to:

internal fun insertedText(previous: TextFieldValue, new: TextFieldValue): String {
    val prefixLength = previous.selection.min
    val suffixLength = previous.text.length - previous.selection.max
    ...
}

So pasting 12 words onto a filled Word 12 now writes about into Word 12 and the rest into 13–23 —
the target word is replaced rather than merged with the first pasted word. Pasting into an empty
field is unchanged, and a single-word paste never reaches this path (no whitespace).

Proof. Four cases added to MnemonicInputPasteTest.kt (after / before / over a filled word, and
the empty-field regression). Negative control — with insertedText stubbed back to new.text, the
new test fails with your exact string:

expected:<about[] abandon art> but was:<about[about] abandon art>

just test and just lint are green; the only detekt finding is the pre-existing LargeClass on
RestoreWalletViewModelTest.

ovi-reviewer[bot]

This comment was marked as resolved.

@ovitrif
ovitrif dismissed ovi-reviewer[bot]’s stale review September 18, 2026 18:28

addressed - reaudit confirmed

ovi-reviewer[bot]

This comment was marked as resolved.

@jvsena42
jvsena42 requested a review from ovitrif September 18, 2026 20:19

@ovi-reviewer ovi-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: ✅ Approve


Reaudit: diff 1 file.
Retest suggested: item 6 (The base sync does not touch restore behavior; item 6 remains the only unproven QA path from the prior fix).

Findings:
N/A

Audit:
Already done in comment.

QA: emu-1 redroid emulator on Android 15, dev build 188

  1. ⏭️ skipped: tested on b1dee6f, recording

  2. ⏭️ skipped: tested on b1dee6f, recording

  3. ⏭️ skipped: tested on b1dee6f, recording

  4. ⏭️ skipped: tested on b1dee6f, recording

  5. ⏭️ skipped: tested on b1dee6f, recording

  6. passed: Pasting the final 12 words into Word 13 kept Words 1-12 unchanged and filled Words 13-24 without duplicating Word 13.

    Test 6:
    24-word layout with Words 1-12 filled → paste the other 12 words into Word 13: Words 1-12 kept, Words 13-24…
    6.mp4
  7. ⏭️ skipped: tested on b1dee6f, recording

  8. ⏭️ skipped: tested on b1dee6f, recording

  9. ⏭️ skipped: tested on b1dee6f, recording

  10. ⏭️ skipped: tested on b1dee6f, recording

Tip

Test 6 worth a journey:

  • Accept the terms and skip the intro
  • Open Restore wallet and acknowledge the multiple-device warning
  • Fill the first twelve words on a fresh twenty-four-word form
  • Preload the final twelve public test words
  • Return to Bitkit and tap Word 13
  • Paste the final twelve words
  • Verify Words 1-12 remain unchanged and Words 13-24 fill

Coverage:
QA: 12 of 12 manual tests passed


Reviewed by gpt-5.6-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest · audit (author or owner)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Pasting partial mnemonic during wallet restore fills first word field and blocks editing

3 participants