52 lines
2.9 KiB
Markdown
52 lines
2.9 KiB
Markdown
# Plan: bookmarks
|
|
|
|
Ordered tasks; each names its verification (tests in `fsdy/src/lib.rs` /
|
|
`crabidy-server/src/bookmark_store.rs` and/or gates in
|
|
`quality/bookmarks.md`). Stubs, the proto rpc, and orchestrator wiring
|
|
exist; the new fsdy/bookmark-store tests fail on `todo!()` at plan time.
|
|
|
|
- [x] **T1 — fsdy shared naming.** `dir_name` (prefix + shared sanitizer,
|
|
no suffix; refactor `track_file_name` onto one helper) and
|
|
`validate_folder_name` (trim, reject separators/NUL/hidden/reserved).
|
|
Verifies: `dir_names_share_the_track_file_sanitizer`,
|
|
`folder_name_validation_trims_and_rejects`; gate "no second naming
|
|
scheme".
|
|
- [x] **T2 — fsdy mutable top level.** Flags on the editable-instance root
|
|
listing (skip reserved); `rename_lib_node`/`delete_lib_node`
|
|
implementations gated on option + direct child + not reserved
|
|
(`NotSupported` otherwise); rename validates via
|
|
`validate_folder_name`, refuses collisions (`InvalidInput`), returns
|
|
the renamed node; delete is idempotent and returns the root listing.
|
|
Verifies: `editable_instances_flag_only_unreserved_top_level_folders`,
|
|
`rename_moves_a_top_level_folder`,
|
|
`rename_rejects_reserved_invalid_and_colliding_targets`,
|
|
`delete_removes_top_level_folders_idempotently`; gates "Mutable top
|
|
level".
|
|
- [x] **T3 — queue_store reuse.** `QueueStore::validate_name` delegates to
|
|
`fsdy::validate_folder_name` with `current` reserved (behavior
|
|
unchanged — existing tests must stay green).
|
|
- [x] **T4 — BookmarkStore capture.** `open`, `capture_with_caps`
|
|
(iterative pre-order walk over `get_lib_node` /
|
|
`get_metadata_for_track`, mirrored dirs + link files, caps, temp
|
|
cleanup on every failure, tmp-and-swap). Verifies: all
|
|
`bookmark_store::tests`; gates "Capture".
|
|
- [x] **T5 — TUI capture flow.** `Action::LibraryCaptureNode` (`w`,
|
|
`Scope::Library`), `Library::selected_queueable()` (bare selection,
|
|
queueable, path + title), `InputPurpose::Capture { path }` prefilled
|
|
with the title, `MessageFromUi::CaptureNode { path, name }`,
|
|
orchestrator arm → new `rpc::capture_library_node` (log failures, keep
|
|
polling). TUI tests: binding lookup, overlay gating + prefill, submit
|
|
message. Verifies: new `cbd-tui` tests; gates "TUI".
|
|
- [x] **T6 — full verification.** Whole workspace suite green;
|
|
clippy/fmt/taplo/markdownlint clean; walk every gate in
|
|
`quality/bookmarks.md` and tick it; no `todo!()` left.
|
|
- [x] **T7 — live smoke test.** Capture a real Tidal artist subtree into a
|
|
temp store through the provider layer, browse it through a
|
|
`/bookmarks` instance, rename it, resolve an album, and fetch a stream
|
|
URL for one captured link — remove any temporary probe afterwards.
|
|
Verifies: end-to-end D1/D2/D4 behavior outside unit scope.
|
|
- [x] **T8 — docs.** `plan/summary.md` section incl. deviations; reconcile
|
|
`architecture/queue-persistence.md` D8 (saved queues now
|
|
renamable/deletable) and `architecture/bookmarks.md` if the
|
|
implementation diverged.
|