92 lines
4.8 KiB
Markdown
92 lines
4.8 KiB
Markdown
# Quality gates — editable and deletable nodes
|
|
|
|
Checklist for the `implement` stage. Automatic tests live in
|
|
`crabidy-core/src/lib.rs`, `tidaldy/src/lib.rs`, and
|
|
`cbd-tui/src/app/{bindings,mod}.rs` test modules; run with
|
|
`devenv shell -- cargo test --workspace` (network-dependent tidaldy tests
|
|
stay `#[ignore]`). 10 tests fail at gate-writing time — they define the
|
|
target.
|
|
|
|
## Contract & wire
|
|
|
|
- [x] Proto changes are additive only: existing field numbers untouched;
|
|
`LibraryNodeChild.is_editable = 5`, `is_deletable = 6`;
|
|
`RenameLibraryNode` and `DeleteLibraryNode` rpcs present. Old clients
|
|
keep working against the new server.
|
|
- [x] `rpc.rs` (server) maps errors per the documented contract for **both**
|
|
new rpcs: `NotSupported` → `failed_precondition`, `InvalidInput` →
|
|
`invalid_argument`, everything else → `internal`. No `color-eyre`
|
|
report or debug formatting of internals leaks into `Status` messages.
|
|
- [x] `ProviderOrchestrator::{rename,delete}_lib_node` route `/tidal`-prefixed
|
|
paths to the Tidal client and answer anything else (including the
|
|
synthetic root `/`) with `NotSupported` — same prefix discipline as
|
|
`create_lib_node`.
|
|
- [x] Both new commands follow the existing bounded(1)-reply rendezvous
|
|
pattern; no new unbounded channels anywhere in the feature.
|
|
|
|
## Provider semantics (tidaldy)
|
|
|
|
- [x] `rename_lib_node` trims the new title; empty/whitespace →
|
|
`InvalidInput`; any path that is not a `SearchTerm` (including
|
|
`/tidal/search` itself) → `NotSupported`; validation happens before any
|
|
network call.
|
|
- [x] Rename replaces the term **in place** (keeps its list position);
|
|
renaming onto an existing term merges (the old slot is removed, no
|
|
duplicates ever); renaming an unknown term registers the new one
|
|
(stale-client forgiveness). Returns `get_lib_node(new_path)` — the
|
|
node at its new percent-encoded path.
|
|
- [x] `delete_lib_node` accepts only `SearchTerm` paths (`NotSupported`
|
|
otherwise), removes the term idempotently (unknown term → success),
|
|
and returns the refreshed `/tidal/search` parent node.
|
|
- [x] `rename_search_term` / `remove_search_term` follow the established
|
|
lock discipline: poison-tolerant, the `search_terms` lock is never
|
|
held across an `await`.
|
|
- [x] Term children returned by the `Search` arm set
|
|
`is_editable: true, is_deletable: true`; nothing else in the provider
|
|
sets either flag.
|
|
- [x] Queued search tracks keep playing after a rename/delete of their term:
|
|
`get_urls_for_track` / `get_metadata_for_track` resolve from the track
|
|
id embedded in the path, independent of term registration.
|
|
|
|
## No panics on user input (hard rule)
|
|
|
|
- [x] All `todo!()` stubs from api-design are gone (grep the workspace).
|
|
- [x] Rename/delete failures (network, auth, malformed paths from stale
|
|
clients) surface as `ProviderError`/`Status`, never a panic; the TUI's
|
|
rename and delete paths handle an error reply without crashing the
|
|
orchestrate task (log + stay put).
|
|
|
|
## TUI behavior
|
|
|
|
- [x] `e` opens the overlay only when the **selected** item `is_editable`,
|
|
prefilled with the current title; `d` sends `DeleteNode` only when the
|
|
selected item `is_deletable`; both are silent no-ops otherwise
|
|
(including when nothing is selected or the list is empty).
|
|
- [x] The overlay carries its purpose: submit sends `CreateNode` for
|
|
`InputPurpose::Create` and `RenameNode` for `InputPurpose::Rename`;
|
|
the rendered label distinguishes them (`new node:` vs `rename:`).
|
|
While the overlay is open the bindings table stays unreachable
|
|
(existing input-mode bypass, unchanged).
|
|
- [x] Delete is deliberately unconfirmed (architecture/node-editing.md D4);
|
|
the open question about confirmation for higher-value nodes is
|
|
preserved in the architecture doc, not silently dropped.
|
|
- [x] Modifiable children are visibly marked in the library list (`[e]`,
|
|
`[d]` or `[ed]` suffix, `COLOR_SECONDARY`), coexisting with the `[%]`
|
|
marker for creatable ones.
|
|
- [x] `RpcClient::rename_library_node` evicts the old path **and** the
|
|
parent entry, then caches the node under its new path;
|
|
`delete_library_node` evicts the deleted path and the parent, then
|
|
caches the returned parent. No stale `/tidal/search` listing can
|
|
resurrect an old term.
|
|
- [x] On successful rename the library navigates into the renamed node; on
|
|
successful delete it shows the refreshed parent; on failure the
|
|
library stays where it was.
|
|
|
|
## Code quality
|
|
|
|
- [x] Public items added in all five crates have doc comments matching final
|
|
behavior; the `e`/`d` bindings appear in the help modal automatically.
|
|
- [x] No new dependencies.
|
|
- [x] `devenv shell -- cargo fmt --check`, `cargo clippy --workspace`
|
|
(no new warnings), `cargo test --workspace` all pass.
|