# Quality gates — queue selection, visual mode, and the register Criteria an implementation of `architecture/queue-register.md` must satisfy. Automated coverage lives in `cbd-tui/src/app/list.rs` (`carry_marks_tests`), `cbd-tui/src/app/register.rs`, `cbd-tui/src/app/mod.rs` (dispatch), and the mirrors of those in `cbd-web/src/state.rs`. ## Data safety (highest priority) - [ ] **G1 — A delete never removes an unmarked track.** The positions sent to `Remove` are computed from the newest queue snapshot, never from an index remembered across an update. *(tests: the `carry_marks` suite plus `deleting_marked_rows_sends_their_current_positions`.)* - [ ] **G2 — Marks follow their track across a snapshot.** Append, removal before a mark, removal of the marked track, streaming resolve, duplicate paths, wholesale replacement, empty queue, and a first snapshot all behave as the `carry_marks` tests state. Divergence clears rather than guesses. - [ ] **G3 — No panic on any mark bookkeeping.** Mismatched lengths, an empty queue, a cursor past the end, and marks on a filtered-out row are all handled without indexing panics. *(test: `a_short_mark_vector_is_tolerated`, plus the empty-queue dispatch tests.)* - [ ] **G4 — `c`/`C` write the register before clearing.** Clearing 200 tracks is recoverable with one `p`. *(tests: `clear_fills_the_register_with_what_it_dropped`.)* ## Register semantics - [ ] **G5 — Only `y`, `d`, `c`, `C` write the register.** Marking (`s`), visual mode, cursor movement, `a`/`L`/`Enter`, `w`/`W`, and every playback action leave it untouched. *(test: `marking_and_queueing_do_not_touch_the_register`.)* - [ ] **G6 — A write overwrites.** One slot, no history, no numbered registers. An empty write clears it. - [ ] **G7 — Paste leaves the register intact**, so the same yank can be pasted repeatedly. *(test: `pasting_twice_inserts_twice`.)* - [ ] **G8 — `p` inserts after the cursor, `P` before it**, and `d` followed by `P` restores the deleted rows to their original positions. *(tests: `paste_after_and_before_use_the_right_position`, `delete_then_paste_before_restores_the_positions`.)* - [ ] **G9 — Paste on an empty register is a no-op**, not an empty `Insert` round trip. *(test: `pasting_an_empty_register_sends_nothing`.)* - [ ] **G10 — The register holds paths, and only labels for display.** No label ever reaches the server; `Insert` carries paths in yank order. ## Selection and visual mode - [ ] **G11 — The queue's `s`, `v`, `V` behave exactly as the library's**: `v` and `V` are the same action, entering anchors at the cursor and marks it, movement paints the anchored range so moving back reverses, `Esc` and any non-movement action leave visual mode while keeping the marks. *(tests: the queue mirrors of the library's visual-mode suite.)* - [ ] **G12 — Every queue row is markable**; the library's `is_queable` gate does not leak into the queue (queue rows carry `is_queable: false`). Conversely the library still refuses to mark an unqueueable row. - [ ] **G13 — Marks live on the full list.** A marked row hidden by the `/` filter still counts for `y` and `d`. *(test: `a_filtered_out_marked_row_is_still_deleted`.)* - [ ] **G14 — `y` and `d` consume the marks they acted on** (the pane comes back unmarked), as queueing already does. - [ ] **G15 — With nothing marked, `y`/`d` act on the cursor row only** — today's `d` behaviour is preserved. - [ ] **G16 — Mark and visual logic exists once per client.** `Library` and `Queue` both go through `MarkedPane`; no second copy of the paint rule. ## Both clients - [ ] **G17 — `cbd-web` reaches parity in the same change**: library visual mode (which it lacks today), queue marks, queue visual mode, `y`, `p`, `P`, and `c`/`C` filling the register. - [ ] **G18 — The web client's queue marks reconcile by the same rule.** It owns no queue list, so its marks sit beside the server signal; the reconciliation cases from G2 are tested there too. - [ ] **G19 — Both key tables and both help overlays list the new keys**, and `cbd-web`'s keymap tests keep their lockstep with its `HELP` table. - [ ] **G20 — The TUI's binding table stays the single source of truth** for its help modal (no hand-maintained duplicate list). ## Documentation - [ ] **G21 — `p`'s changed meaning is documented as a change**, in the book's TUI page, the web page, and the README walkthrough: it pastes the register, and the browse→insert-here flow is now `y` then `p`. - [ ] **G22 — The register's limits are stated**: per client, in memory, one slot, and paste re-resolves so a stale path may not come back. - [ ] **G23 — Key tables match the code.** Every new binding appears in `docs/src/clients/tui.md`, `docs/src/clients/web.md` where it lists keys, and the README's usage section. ## Hard rules - [ ] **G24 — No panics** on user input or empty state anywhere in the new paths; `todo!()`/`unimplemented!()` from the stub stage are all gone. - [ ] **G25 — No new server surface.** No `.proto` change, no new RPC, no change to `crabidy-server`. The feature is two clients and the two existing calls (`Insert`, `Remove`). - [ ] **G26 — Clippy clean under `-D warnings`** for `cbd-tui` and for `cbd-web` on **both** the native and `wasm32-unknown-unknown` targets (`mod app` only compiles for wasm), and the trunk bundle still builds.