mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-04 20:02:05 +00:00
tui v2: close 2fa url parity and advance strict mockup closeout
This commit is contained in:
1 parent
f0c120f84d
commit
a4de52ae4a
5 files changed
+1370
-1375
No files matched your search
@@ -22,7 +22,7 @@ Latest verification in this session:
|
||||
- coverage: `85.65%`
|
||||
- Focused TUI validation slices:
|
||||
- `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
- latest result: `31 passed`
|
||||
- latest result: `35 passed`
|
||||
- includes profile-tree keyboard navigation/select command coverage
|
||||
|
||||
## 2) Canonical Status Sources
|
||||
@@ -163,8 +163,31 @@ Progress update (2026-03-02):
|
||||
- one-time onboarding notice added for first online profile load with settings guidance
|
||||
|
||||
Current UI refresh remaining queue:
|
||||
1. Final visual polish pass against mockups (spacing, headers, action strip clarity).
|
||||
2. Tune semantic indicator wording/placement in top ribbon/action strip for readability under narrow terminals.
|
||||
1. Keep strict mockup parity `Open` count at zero:
|
||||
: preserve 2FA `copy URL` command/board affordance coverage.
|
||||
2. Finish remaining `Minor Gap` board polish:
|
||||
: `UI Board`, `Password`, `Stored Password`, `Note` geometry/rhythm and action-chip treatment.
|
||||
3. Final UI-board density/viewport balance polish:
|
||||
: keep both dense table rows and usable lower inspector in common terminal sizes.
|
||||
4. Continue semantic indicator wording/placement tuning (baseline compact ribbon pass is now landed) for readability under narrow terminals.
|
||||
5. Execute strict closeout pass from:
|
||||
: `docs/tui_v2_ui_refresh_plan.md` section "15) Mockup Board Parity Audit (2026-03-02)".
|
||||
4. Keep default list focus + hotkey reliability + compact responsive regression green:
|
||||
: `test_tui2_textual_default_focus_keeps_sensitive_hotkeys_active`.
|
||||
: `test_tui2_textual_compact_layout_hides_link_panel_and_can_restore`.
|
||||
5. Keep SSH/PGP/Nostr board-fidelity regression green:
|
||||
: `test_tui2_textual_ssh_pgp_nostr_boards_show_action_fidelity`.
|
||||
6. Keep Seed/Managed Seed board-fidelity regression green:
|
||||
: `test_tui2_textual_seed_and_managed_seed_boards_show_fidelity`.
|
||||
7. Preserve micro-alignment density (table/header/panel spacing) in ongoing UI slices.
|
||||
8. Keep Note/2FA metadata consistency regression green:
|
||||
: `test_tui2_textual_note_and_totp_boards_include_common_metadata`.
|
||||
9. Preserve table/header/action micro-copy consistency introduced in latest polish.
|
||||
10. Track strict closeout statuses (`Done` / `Minor Gap` / `Open`) per board and re-evaluate after each slice.
|
||||
11. Keep compact discoverability regression green (inline notes/tags fallback when side card is collapsed).
|
||||
12. Keep viewport-height balance regression green (activity fallback + layout rebalance on short screens).
|
||||
13. Preserve icon-enhanced board title hierarchy introduced in typography polish pass.
|
||||
14. Keep strict scorecard at `Open=0` and advance `Minor Gap -> Done` boards incrementally.
|
||||
|
||||
## 6) Working Rule
|
||||
|
||||
@@ -173,3 +196,16 @@ When priorities conflict:
|
||||
2. Close user-visible parity gaps.
|
||||
3. Raise security/testing gates.
|
||||
4. Then optimize docs and process.
|
||||
|
||||
## 7) Active UI Parity Focus (Mockup-Coupled)
|
||||
|
||||
Use this order for current TUI v2 design iterations:
|
||||
|
||||
1. Preserve upper table density while retaining usable lower inspector in the same viewport.
|
||||
2. Normalize shared inspector header metadata/actions across all kinds.
|
||||
3. Complete board-specific action affordance fidelity:
|
||||
: Password/Stored Password -> Note/2FA -> Seed -> SSH/PGP/Nostr.
|
||||
4. Keep each slice test-gated:
|
||||
: `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
5. Capture screenshot evidence after each slice in:
|
||||
: `artifacts/ui_eval/current_tui2_after*.png`.
|
||||
@@ -545,6 +545,416 @@ Completed:
|
||||
|
||||
Remaining (active queue):
|
||||
|
||||
1. Final alignment pass to mockup spacing/rhythm and action-strip clarity.
|
||||
1. Final alignment pass to mockup spacing/rhythm.
|
||||
2. Semantic-state indicator readability pass in ribbon/action strip for upcoming dense-status scenarios.
|
||||
3. Run focused TUI tests and coverage gate after each polish slice.
|
||||
3. Continue board-by-board card/action fidelity polish (Password/Stored Password -> Note/2FA -> SSH/PGP/Nostr).
|
||||
4. Run focused TUI tests and coverage gate after each polish slice.
|
||||
|
||||
## 16) Progress Update (2026-03-02, Slice: Action Rail + Hotkey Reliability)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Bottom action strip upgraded to a two-line persistent rail:
|
||||
- line 1: stable global controls
|
||||
- line 2: entry-kind contextual controls
|
||||
2. Status bar upgraded to a two-line presentation for better readability:
|
||||
- mode/pane + stable shortcut hint
|
||||
- latest status message
|
||||
3. Center-pane focus behavior changed to list-first:
|
||||
- `action_focus_center` now focuses `#entry-list` instead of `#search`
|
||||
- on launch, focus defaults to `#entry-list`
|
||||
4. This restores expected immediate hotkey behavior for `v`/`g` without requiring a manual focus fix.
|
||||
5. Top ribbon readability pass:
|
||||
- compacted status labels (`FP`, `M`, `E`, `K`, `SEM`, `Sync`)
|
||||
- semantic mode shortened (`kw|hyb|sem`)
|
||||
- fingerprint and sync strings truncated for narrow terminals
|
||||
6. Responsive narrow-screen fallback:
|
||||
- auto-compact mode when terminal width is narrow
|
||||
- link context side panel collapses in compact mode to preserve inspector readability
|
||||
- action strip now signals compact mode (`Compact: links hidden`)
|
||||
7. Board-fidelity refresh (current slice):
|
||||
- Password/Stored Password boards now use explicit board titles and refined action/field lines
|
||||
- Note/Document board now uses explicit board title with clearer preview labeling
|
||||
- 2FA board action labels clarified (`Copy Code`, `Reveal Secret`, `QR`)
|
||||
8. Added compact-layout regression test:
|
||||
- `test_tui2_textual_compact_layout_hides_link_panel_and_can_restore`
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `31 passed`.
|
||||
3. Added regression coverage:
|
||||
- `test_tui2_textual_default_focus_keeps_sensitive_hotkeys_active`
|
||||
|
||||
## 17) Progress Update (2026-03-02, Slice: SSH/PGP/Nostr Card Fidelity)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Inspector header readability tweak:
|
||||
- changed `Edit: [e]` to `Edit: e` (avoids markup-style ambiguity in Textual render output).
|
||||
2. SSH board polish:
|
||||
- explicit `SSH Board` title
|
||||
- metadata row moved directly under title
|
||||
- public-key preview line added (truncated for dense layout)
|
||||
- action rows grouped as public/private operations
|
||||
3. PGP board polish:
|
||||
- explicit `PGP Board` title
|
||||
- metadata-first structure + retained fingerprint prominence
|
||||
- action rows grouped as public/private operations
|
||||
4. Nostr board polish:
|
||||
- explicit `Nostr Board` title
|
||||
- metadata-first structure + npub/nsec lines
|
||||
- QR public/private actions shown together
|
||||
5. Added board-fidelity regression coverage:
|
||||
- `test_tui2_textual_ssh_pgp_nostr_boards_show_action_fidelity`
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `32 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after32_ssh.png`
|
||||
2. `artifacts/ui_eval/current_tui2_after32_pgp.png`
|
||||
3. `artifacts/ui_eval/current_tui2_after32_nostr.png`
|
||||
|
||||
## 18) Progress Update (2026-03-02, Slice: Seed Board Fidelity)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Seed-family board specialization:
|
||||
- `seed` now renders as `BIP-39 Seed Board`
|
||||
- `managed_account` now renders as `Managed Account Seed Board`
|
||||
2. Seed metadata fidelity:
|
||||
- word count now falls back to deriving from `seed_phrase` when `words` is absent
|
||||
- index metadata remains explicit in the board
|
||||
3. Seed action affordances aligned to sensitive workflow:
|
||||
- `Reveal Seed`, `QR Seed`, `Copy Seed(confirm)`, `Export Seed(confirm)`
|
||||
- clear command hints for confirm-gated copy/export/reveal flows
|
||||
4. Added board-fidelity regression coverage:
|
||||
- `test_tui2_textual_seed_and_managed_seed_boards_show_fidelity`
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `33 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after33_seed.png`
|
||||
2. `artifacts/ui_eval/current_tui2_after33_managed_seed.png`
|
||||
|
||||
## 19) Progress Update (2026-03-02, Slice: Spacing/Rhythm + Compact Action Strip)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Layout rhythm tuning:
|
||||
- top work area increased (`#top-work` from `5fr` to `6fr`)
|
||||
- inspector area increased (`#right` from `4fr` to `5fr`)
|
||||
- left rail slightly narrowed (`#left` from `34` to `32`)
|
||||
- inspector side rail slightly narrowed (`#inspector-side` from `30` to `28`)
|
||||
2. Compact-mode action-strip readability:
|
||||
- compact global row now uses shorter labels (`Ctrl+P`, `1/2/3`, `p/n`, `f/h`)
|
||||
- very narrow widths apply abbreviated context text (`Rev`, `Arch`, `cfm`)
|
||||
3. Responsive state tracking:
|
||||
- stores viewport width and adapts action-strip wording accordingly.
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `33 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after34_password.png`
|
||||
2. `artifacts/ui_eval/current_tui2_after34_note.png`
|
||||
3. `artifacts/ui_eval/current_tui2_after34_totp.png`
|
||||
4. `artifacts/ui_eval/current_tui2_after34_ssh.png`
|
||||
5. `artifacts/ui_eval/current_tui2_after34_pgp.png`
|
||||
6. `artifacts/ui_eval/current_tui2_after34_nostr.png`
|
||||
7. `artifacts/ui_eval/current_tui2_after34_seed.png`
|
||||
8. `artifacts/ui_eval/current_tui2_after34_managed_seed.png`
|
||||
|
||||
## 20) Progress Update (2026-03-02, Slice: Micro-Alignment Tightening)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Tightened top-frame rhythm to better mirror mockup structure:
|
||||
- reduced top-ribbon vertical gap
|
||||
- removed extra right-panel top gap
|
||||
2. Increased dense-table feel in center column:
|
||||
- reduced grid heading height and spacing
|
||||
- removed quick-jump extra bottom spacing
|
||||
3. Tightened panel rhythm in left column:
|
||||
- slightly narrower tree rail
|
||||
- reduced activity panel height and top gap
|
||||
4. Improved inspector rhythm:
|
||||
- removed extra spacing under inspector heading
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `33 passed`.
|
||||
|
||||
## 21) Progress Update (2026-03-02, Slice: Header/Action Consistency Sweep)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Note/Document board consistency upgrades:
|
||||
- now includes common metadata line: `Kind | Modified | Archived`
|
||||
- now includes common ID line: `Index Num* | Entry Num`
|
||||
2. 2FA board consistency upgrades:
|
||||
- now includes common metadata line: `Kind | Modified | Archived`
|
||||
- now includes common ID line: `Index Num* | Entry Num`
|
||||
3. Added regression coverage:
|
||||
- `test_tui2_textual_note_and_totp_boards_include_common_metadata`
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `34 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after35_password.svg`
|
||||
2. `artifacts/ui_eval/current_tui2_after35_note.svg`
|
||||
3. `artifacts/ui_eval/current_tui2_after35_totp.svg`
|
||||
4. `artifacts/ui_eval/current_tui2_after35_ssh.svg`
|
||||
5. `artifacts/ui_eval/current_tui2_after35_pgp.svg`
|
||||
6. `artifacts/ui_eval/current_tui2_after35_nostr.svg`
|
||||
7. `artifacts/ui_eval/current_tui2_after35_seed.svg`
|
||||
8. `artifacts/ui_eval/current_tui2_after35_managed_seed.svg`
|
||||
|
||||
## 22) Progress Update (2026-03-02, Slice: Final Table/Header Micro-Copy)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Grid heading copy cleanup:
|
||||
- removed ambiguous duplicate naming and standardized columns to:
|
||||
`Sel | Id | Entry# | Label | Kind | Meta | Arch`
|
||||
2. Board footer action wording normalized across kinds:
|
||||
- consistent verb-first labels with key hints, e.g.
|
||||
`Edit (e)`, `Archive (a)`, `Reveal (v)`, `QR (g)`, `Save (Ctrl+S)`, `Cancel (Esc)`.
|
||||
3. Seed/advanced command hints retained where explicit command forms are needed:
|
||||
- `copy seed confirm`
|
||||
- `export-field seed <path> confirm`
|
||||
- `qr private confirm`
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `34 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after36_password.svg`
|
||||
2. `artifacts/ui_eval/current_tui2_after36_note.svg`
|
||||
3. `artifacts/ui_eval/current_tui2_after36_totp.svg`
|
||||
4. `artifacts/ui_eval/current_tui2_after36_ssh.svg`
|
||||
5. `artifacts/ui_eval/current_tui2_after36_pgp.svg`
|
||||
6. `artifacts/ui_eval/current_tui2_after36_nostr.svg`
|
||||
7. `artifacts/ui_eval/current_tui2_after36_seed.svg`
|
||||
8. `artifacts/ui_eval/current_tui2_after36_managed_seed.svg`
|
||||
|
||||
## 23) Progress Update (2026-03-02, Slice: 2FA Copy URL Parity Closure)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Added first-class 2FA URL copy command:
|
||||
- `2fa-copy-url <entry_id>`
|
||||
2. Added TOTP URL support to generic copy flow:
|
||||
- `copy url confirm` (for selected TOTP entry) now resolves otpauth URI.
|
||||
3. Surfaced URL copy affordance in 2FA UI text:
|
||||
- 2FA inspector board action row now includes `Copy URL(confirm)`.
|
||||
- 2FA board command hint row now includes `2fa-copy-url <entry_id>`.
|
||||
4. Updated palette discoverability text:
|
||||
- command palette placeholder, help reference, and quick-help example include `2fa-copy-url`.
|
||||
5. Added/updated regression coverage:
|
||||
- extended 2FA board tests to assert:
|
||||
- successful URL copy
|
||||
- usage and input validation for `2fa-copy-url`
|
||||
- board command hint visibility
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `34 passed`.
|
||||
|
||||
Strict closeout impact:
|
||||
|
||||
1. 2FA board moved from `Open` to `Minor Gap` (functional parity closed; visual polish remains).
|
||||
|
||||
## 24) Progress Update (2026-03-02, Slice: Compact Discoverability + Board Polish)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Compact-mode notes/tags discoverability upgrade:
|
||||
- when compact mode collapses the right notes/tags panel, inspector boards now render notes/tags inline for discoverability.
|
||||
2. Applied inline notes/tags fallback across core boards:
|
||||
- password/stored_password, note/document, seed/managed_account, totp, ssh, pgp, nostr.
|
||||
3. Password + Note polish:
|
||||
- password board now has explicit `Credentials` section.
|
||||
- note board now uses clearer `Content Preview` heading and flow.
|
||||
4. Added compact discoverability regression assertions:
|
||||
- extended `test_tui2_textual_compact_layout_hides_link_panel_and_can_restore` to verify inline notes/tags content.
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `34 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after38_note_compact.svg`
|
||||
|
||||
## 25) Progress Update (2026-03-02, Slice: Viewport Balance Adaptation)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Added viewport-height adaptive layout balancing:
|
||||
- short viewports (`height < 32`): keeps inspector usable and hides activity panel to recover space.
|
||||
- standard viewports: balanced default (`top-work` / inspector sizing) with activity visible.
|
||||
- tall viewports (`height >= 52`): increases table density while preserving inspector legibility.
|
||||
2. Keeps compact-mode width behavior and height behavior coordinated via unified responsive update path.
|
||||
3. Added viewport-balance regression coverage:
|
||||
- `test_tui2_textual_viewport_balance_hides_activity_on_short_height`
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `35 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after39_note_compact_short.svg`
|
||||
2. `artifacts/ui_eval/current_tui2_after39_note_standard.svg`
|
||||
|
||||
## 26) Progress Update (2026-03-02, Slice: Typography/Icon Polish)
|
||||
|
||||
Implemented:
|
||||
|
||||
1. Added consistent kind icons in inspector board titles/headers for stronger visual scanning:
|
||||
- password, note/document, 2FA, seed/managed seed, SSH, PGP, Nostr now include their kind icon in board title lines.
|
||||
2. Applied icon-enhanced shared entry-header format for template-based boards.
|
||||
3. Preserved command and behavior parity while improving visual hierarchy.
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `35 passed`.
|
||||
|
||||
Artifacts:
|
||||
|
||||
1. `artifacts/ui_eval/current_tui2_after40_password.svg`
|
||||
2. `artifacts/ui_eval/current_tui2_after40_note.svg`
|
||||
3. `artifacts/ui_eval/current_tui2_after40_totp.svg`
|
||||
4. `artifacts/ui_eval/current_tui2_after40_ssh.svg`
|
||||
5. `artifacts/ui_eval/current_tui2_after40_pgp.svg`
|
||||
6. `artifacts/ui_eval/current_tui2_after40_nostr.svg`
|
||||
7. `artifacts/ui_eval/current_tui2_after40_seed.svg`
|
||||
8. `artifacts/ui_eval/current_tui2_after40_managed_seed.svg`
|
||||
|
||||
## 15) Mockup Board Parity Audit (2026-03-02)
|
||||
|
||||
Source set reviewed:
|
||||
|
||||
1. `UI_mockups/PNG/UI Board.png`
|
||||
2. `UI_mockups/PNG/Password Board.png`
|
||||
3. `UI_mockups/PNG/Stored Password Board.png`
|
||||
4. `UI_mockups/PNG/Note Board.png`
|
||||
5. `UI_mockups/PNG/2FA Board.png`
|
||||
6. `UI_mockups/PNG/BIP-39 Seed Board.png`
|
||||
7. `UI_mockups/PNG/SSH Board.png`
|
||||
8. `UI_mockups/PNG/PGP Board.png`
|
||||
9. `UI_mockups/PNG/Nostr Board.png`
|
||||
|
||||
### 15.1 Shared Layout Contract (from all mockups)
|
||||
|
||||
Expected:
|
||||
|
||||
1. Dense table-first upper region with always-visible rows and explicit separators.
|
||||
2. Persistent left hierarchy tree with compact, high-signal metadata.
|
||||
3. Lower inspector with:
|
||||
- shared header row (`label`, `kind`, `modified`, blacklist/archive, index/entry)
|
||||
- field cards
|
||||
- right-side secondary card (tags/notes/links/sensitive)
|
||||
4. Bottom action rail with stable global actions + contextual actions.
|
||||
|
||||
Current status:
|
||||
|
||||
1. Implemented in structure, but still needs spacing/density tuning to keep both:
|
||||
- sufficient table rows visible
|
||||
- full inspector card content visible in same viewport
|
||||
|
||||
### 15.2 Board-by-Board Functional + Layout Parity
|
||||
|
||||
| Mockup board | Required field/layout traits | Required actions | TUI v2 status |
|
||||
|---|---|---|---|
|
||||
| UI Board | Dense table, left tree, bottom rail | search/filter/paging/navigation | Minor Gap |
|
||||
| Password | password/username/url/tags + notes side panel | copy password, create new, edit, reveal/qr | Minor Gap |
|
||||
| Stored Password | password/username/url/tags + notes side panel | copy password, edit, reveal/qr | Minor Gap |
|
||||
| Note | large content area + tags side card | edit/save/cancel/export | Minor Gap |
|
||||
| 2FA | code field + URL field + notes/tags side card | copy code, copy URL, reveal/qr, 2FA board | Done |
|
||||
| BIP-39 Seed | seed field + notes + tags side card | reveal/confirm, qr, copy/export with confirm | Done |
|
||||
| SSH | public/private rows + notes/tags side card | copy public/private, export public/private, reveal private | Done |
|
||||
| PGP | public/private rows + notes/tags side card | copy/export public/private, reveal private | Done |
|
||||
| Nostr | npub/nsec rows + notes/tags side card | copy npub/nsec, qr public/private, reveal nsec | Done |
|
||||
|
||||
### 15.3 Closeout Status Definitions (Strict)
|
||||
|
||||
1. `Done`: matching layout and actions with no user-visible parity gap in normal viewport.
|
||||
2. `Minor Gap`: core behaviors present; remaining differences are visual rhythm/density or secondary affordance polish.
|
||||
3. `Open`: missing required interaction from mockup contract.
|
||||
|
||||
### 15.4 Strict Closeout Notes (2026-03-02)
|
||||
|
||||
1. `UI Board` -> Minor Gap:
|
||||
- structure is correct (left tree + table + inspector + action rail), but table density and lower board visibility balance still need final tuning.
|
||||
2. `Password/Stored Password` -> Minor Gap:
|
||||
- core actions and fields are present; remaining gap is closer card geometry fidelity to mockup.
|
||||
3. `Note` -> Minor Gap:
|
||||
- edit/save/export flow is complete; remaining gap is larger content-card visual weighting compared to mockup.
|
||||
4. `2FA` -> Done:
|
||||
- code/URL copy, reveal, QR, and board workflows are now first-class and discoverable.
|
||||
5. `BIP-39 Seed` -> Done:
|
||||
- reveal/QR/copy/export confirm workflows are present with board-level affordances.
|
||||
6. `SSH/PGP/Nostr` -> Done:
|
||||
- required copy/export/reveal/QR workflows are present with explicit board action affordances.
|
||||
|
||||
### 15.5 Current Priority Gap Order (derived from strict closeout)
|
||||
|
||||
1. Keep strict `Open` count at zero by preserving 2FA copy-URL parity.
|
||||
2. Final visual card/rhythm pass for remaining `Minor Gap` boards (`UI Board`, `Password`, `Stored Password`, `Note`).
|
||||
3. Final action-rail wording polish to match mockup verbs.
|
||||
|
||||
### 15.6 Immediate Next Slice (strict closeout coupled)
|
||||
|
||||
1. Final card geometry pass for Password/Stored Password/Note.
|
||||
2. Final UI-board density pass (table rows + lower inspector balance).
|
||||
3. Final action-strip verb/microcopy polish.
|
||||
4. Re-run focused suite and capture `after41` artifacts.
|
||||
|
||||
## 27) Progress Update (2026-03-02, Slice: Strict Closeout Scoring Pass)
|
||||
|
||||
Scoring method:
|
||||
|
||||
1. `Done`: no user-visible functional parity gap and mockup-consistent action discoverability in normal viewport.
|
||||
2. `Minor Gap`: functional parity met, but visual/rhythm mismatch remains.
|
||||
3. `Open`: required interaction missing.
|
||||
|
||||
Current strict closeout scoreboard:
|
||||
|
||||
1. `Done` (5/9): `2FA`, `BIP-39 Seed`, `SSH`, `PGP`, `Nostr`.
|
||||
2. `Minor Gap` (4/9): `UI Board`, `Password`, `Stored Password`, `Note`.
|
||||
3. `Open` (0/9).
|
||||
|
||||
Evidence basis:
|
||||
|
||||
1. Focused validation gate: `35 passed` in current run set.
|
||||
2. Artifact set: `artifacts/ui_eval/current_tui2_after40_*.svg`.
|
||||
3. Dedicated parity regressions in `src/tests/test_tui_v2_textual_interactions.py` for:
|
||||
- default hotkey focus
|
||||
- compact discoverability
|
||||
- board fidelity (`SSH/PGP/Nostr`, `Seed/Managed Seed`, `Note/2FA metadata`)
|
||||
- viewport balance behavior
|
||||
+57
-1133
File diff suppressed because it is too large.
Load diff
+616
-237
File diff suppressed because it is too large.
Load diff
@@ -980,6 +980,236 @@ async def test_tui2_textual_managed_account_keyboard_reveal_and_qr() -> None:
|
||||
assert "Payload:" in qr_text
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_default_focus_keeps_sensitive_hotkeys_active() -> None:
|
||||
service = FakeEntryService(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"kind": "managed_account",
|
||||
"label": "Acct 1",
|
||||
"seed_phrase": (
|
||||
"legal winner thank year wave sausage worth useful "
|
||||
"legal winner thank yellow"
|
||||
),
|
||||
}
|
||||
]
|
||||
)
|
||||
app = _build_app(service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
assert getattr(app.focused, "id", None) == "entry-list"
|
||||
|
||||
await pilot.press("v")
|
||||
await pilot.pause()
|
||||
assert "requires confirmation" in _status_text(app)
|
||||
assert "Run: reveal confirm" in _widget_text(app, "#secret-detail")
|
||||
|
||||
await pilot.press("g")
|
||||
await pilot.pause()
|
||||
qr_text = _widget_text(app, "#secret-detail")
|
||||
assert "Managed Account Seed #1 QR" in qr_text
|
||||
assert "Payload:" in qr_text
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_compact_layout_hides_link_panel_and_can_restore() -> None:
|
||||
service = FakeEntryService(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"kind": "document",
|
||||
"label": "Doc 1",
|
||||
"notes": "compact note",
|
||||
"tags": ["alpha", "beta"],
|
||||
}
|
||||
]
|
||||
)
|
||||
app = _build_app(service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
link_detail = app.query_one("#link-detail", Static)
|
||||
assert link_detail.has_class("hidden")
|
||||
assert "Compact" in _widget_text(app, "#action-strip")
|
||||
detail = _widget_text(app, "#entry-detail")
|
||||
assert "Compact: Notes/Tags shown inline." in detail
|
||||
assert "Tags: alpha, beta" in detail
|
||||
assert "Notes: compact note" in detail
|
||||
|
||||
app._update_responsive_layout(width=220)
|
||||
await pilot.pause()
|
||||
assert not link_detail.has_class("hidden")
|
||||
|
||||
app._update_responsive_layout(width=120)
|
||||
await pilot.pause()
|
||||
assert link_detail.has_class("hidden")
|
||||
assert "Compact" in _widget_text(app, "#action-strip")
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_viewport_balance_hides_activity_on_short_height() -> None:
|
||||
service = FakeEntryService([{"id": 1, "kind": "document", "label": "Doc 1"}])
|
||||
app = _build_app(service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
activity = app.query_one("#activity", Static)
|
||||
assert activity.has_class("hidden")
|
||||
|
||||
app._update_responsive_layout(width=120, height=28)
|
||||
await pilot.pause()
|
||||
assert activity.has_class("hidden")
|
||||
|
||||
app._update_responsive_layout(width=170, height=46)
|
||||
await pilot.pause()
|
||||
assert not activity.has_class("hidden")
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_ssh_pgp_nostr_boards_show_action_fidelity() -> None:
|
||||
service = FakeEntryService(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"kind": "ssh",
|
||||
"label": "SSH 1",
|
||||
"private_key": "SSH_PRIVATE_1",
|
||||
"public_key": "ssh-ed25519 AAAA-1",
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"kind": "pgp",
|
||||
"label": "PGP 2",
|
||||
"private_key": "-----BEGIN PGP PRIVATE KEY BLOCK-----",
|
||||
"fingerprint": "FPR-2",
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"kind": "nostr",
|
||||
"label": "Nostr 3",
|
||||
"npub": "npub1abc",
|
||||
"nsec": "nsec1abc",
|
||||
},
|
||||
]
|
||||
)
|
||||
app = _build_app(service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
|
||||
app._run_palette_command("open 1")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "SSH Board" in board
|
||||
assert "▣ Copy Public" in board
|
||||
assert "▣ Reveal Private" in board
|
||||
|
||||
app._run_palette_command("open 2")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "PGP Board" in board
|
||||
assert "Fingerprint: FPR-2" in board
|
||||
assert "▣ Export Private" in board
|
||||
|
||||
app._run_palette_command("open 3")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "Nostr Board" in board
|
||||
assert "▣ QR Public" in board
|
||||
assert "▣ QR Private" in board
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_seed_and_managed_seed_boards_show_fidelity() -> None:
|
||||
service = FakeEntryService(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"kind": "seed",
|
||||
"label": "Seed 1",
|
||||
"seed_phrase": (
|
||||
"abandon abandon abandon abandon abandon abandon "
|
||||
"abandon abandon abandon abandon abandon about"
|
||||
),
|
||||
"index": 1,
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"kind": "managed_account",
|
||||
"label": "Managed 2",
|
||||
"seed_phrase": (
|
||||
"legal winner thank year wave sausage worth useful "
|
||||
"legal winner thank yellow"
|
||||
),
|
||||
"index": 2,
|
||||
},
|
||||
]
|
||||
)
|
||||
app = _build_app(service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
|
||||
app._run_palette_command("open 1")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "BIP-39 Seed Board" in board
|
||||
assert "Word Count: 12" in board
|
||||
assert "copy seed confirm" in board
|
||||
|
||||
app._run_palette_command("open 2")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "Managed Account Seed Board" in board
|
||||
assert "Word Count: 12" in board
|
||||
assert "export-field seed <path> confirm" in board
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_note_and_totp_boards_include_common_metadata() -> None:
|
||||
service = FakeEntryService(
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"kind": "document",
|
||||
"label": "Note 1",
|
||||
"content": "hello",
|
||||
"file_type": "md",
|
||||
"index": 1,
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"kind": "totp",
|
||||
"label": "Auth 2",
|
||||
"secret": "JBSWY3DPEHPK3PXP",
|
||||
"period": 30,
|
||||
"digits": 6,
|
||||
"index": 2,
|
||||
},
|
||||
]
|
||||
)
|
||||
app = _build_app(service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
|
||||
app._run_palette_command("open 1")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "Note Board" in board
|
||||
assert "Kind: document | Modified:" in board
|
||||
assert "Index Num*:" in board
|
||||
|
||||
app._run_palette_command("open 2")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "2FA Board" in board
|
||||
assert "Kind: totp | Modified:" in board
|
||||
assert "Index Num*:" in board
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_filters_panel_tracks_selected_entry() -> None:
|
||||
service = FakeEntryService(
|
||||
@@ -1552,6 +1782,13 @@ async def test_tui2_textual_2fa_board_view_timer_and_copy() -> None:
|
||||
assert service.clipboard_values[-1] == "123456"
|
||||
assert "Copied TOTP code for entry 1" in _status_text(app)
|
||||
|
||||
app._run_palette_command("2fa-copy-url 1")
|
||||
await pilot.pause()
|
||||
copied_uri = service.clipboard_values[-1]
|
||||
assert copied_uri.startswith("otpauth://totp/")
|
||||
assert "secret=" in copied_uri
|
||||
assert "Copied TOTP URL for entry 1" in _status_text(app)
|
||||
|
||||
app._run_palette_command("2fa-refresh")
|
||||
await pilot.pause()
|
||||
assert "2FA board refreshed" in _status_text(app)
|
||||
@@ -1589,11 +1826,20 @@ async def test_tui2_textual_2fa_board_secret_mode_and_validation() -> None:
|
||||
await pilot.pause()
|
||||
assert "2fa-copy entry_id must be an integer" in _status_text(app)
|
||||
|
||||
app._run_palette_command("2fa-copy-url")
|
||||
await pilot.pause()
|
||||
assert "Usage: 2fa-copy-url <entry_id>" in _status_text(app)
|
||||
|
||||
app._run_palette_command("2fa-copy-url nope")
|
||||
await pilot.pause()
|
||||
assert "2fa-copy-url entry_id must be an integer" in _status_text(app)
|
||||
|
||||
app._run_palette_command("2fa-board")
|
||||
await pilot.pause()
|
||||
board_text = _widget_text(app, "#totp-board")
|
||||
assert "******" in board_text
|
||||
assert "123456" not in board_text
|
||||
assert "2fa-copy-url <entry_id>" in board_text
|
||||
|
||||
app._run_palette_command("2fa-hide")
|
||||
await pilot.pause()
|
||||
|
||||
Reference in new issue
Block a user