crabidy/plan/node-editing.md

84 lines
4.4 KiB
Markdown

# Plan — editable and deletable nodes
Ordered tasks for the `implement` stage. Inputs: `architecture/node-editing.md`,
stubs across the workspace, gates in `quality/node-editing.md`. Tests:
`devenv shell -- cargo test --workspace` (10 failing at plan time = the
target: 5 in tidaldy, 5 in cbd-tui). Use the session-local `CARGO_TARGET_DIR`
if `target/` contains artifacts owned by the repo owner.
## 1. Term-list mutations (tidaldy)
- [x] Implement `rename_search_term(old, new)`: under one write lock, if
`new` already exists remove the `old` slot (merge); else if `old`
exists replace it in place; else push `new` (stale-client
forgiveness). Implement `remove_search_term(term)`: `retain`
everything but `term`. Both poison-tolerant like
`register_search_term`, no await under the lock. **Verify**:
`rename_replaces_in_place_and_merges_duplicates` passes; gate "lock
discipline".
## 2. Provider rename/delete (tidaldy)
- [x] `rename_lib_node`: trim new title → `InvalidInput` if empty;
`parse_path(path)?` must be `TidalPath::SearchTerm(old)` else
`NotSupported`; decode old term, `rename_search_term`, return
`get_lib_node(join_path(parent, encode_segment(new)))`. **Verify**:
`rename_rejects_empty_titles_and_foreign_paths` passes (validation
before any network call).
- [x] `delete_lib_node`: `parse_path(path)?` must be `SearchTerm` else
`NotSupported`; decode + `remove_search_term` (idempotent); return
`get_lib_node(/tidal/search)`. **Verify**: `delete_rejects_foreign_paths`
and `delete_removes_terms_idempotently_and_returns_the_parent` pass.
- [x] Flag term children in the `Search` arm of `get_lib_node`:
`is_editable: true, is_deletable: true` via struct update. **Verify**:
`search_node_lists_created_terms` passes (extended assertion).
## 3. Server handlers (crabidy-server)
- [x] Replace the `todo!()` bodies of `rpc.rs
rename_library_node`/`delete_library_node`: record span fields,
bounded(1) rendezvous with the matching `ProviderCommand`, map errors
exactly like `create_library_node` (`NotSupported` →
`failed_precondition` with an operation-specific message,
`InvalidInput``invalid_argument`, rest → `internal`). **Verify**:
gates "error mapping" + "bounded rendezvous"; `cargo check`.
(Orchestrator routing and the command-loop arms were finalized at
stub time — re-read them against the gate rather than re-doing them.)
## 4. TUI library accessors + marker (cbd-tui)
- [x] Implement `Library::selected_editable` / `selected_deletable` from
`list_state.selected()` + the `UiItem` flags. **Verify**:
`edit_opens_the_overlay_prefilled_only_on_editable_selections`,
`delete_sends_only_for_deletable_selections`,
`rename_submit_sends_the_trimmed_new_title`,
`rename_cancels_and_emptied_buffers_send_nothing` pass (dispatch and
overlay logic already landed with the stubs).
- [x] Render the `[e]`/`[d]`/`[ed]` suffix for modifiable items in
`Library::render`, `COLOR_SECONDARY` like `[%]`. **Verify**:
`modifiable_items_are_marked_and_the_rename_overlay_is_labelled`
passes; gate "marked in UI".
## 5. TUI ↔ server wiring (cbd-tui)
- [x] `RpcClient::rename_library_node`: send the rpc, evict the old path and
the parent (`crabidy_core::parent_path`), insert + return the renamed
node. `delete_library_node`: send the rpc, evict the deleted path and
the parent, insert + return the returned parent node. **Verify**: gate
"cache eviction" (read; the cache is private, as with create).
- [x] `main.rs poll`: replace the `todo!()` arms — `RenameNode` calls
`rename_library_node`, `DeleteNode` calls `delete_library_node`; on
success `ReplaceLibraryNode(node)`, on failure `error!` and leave the
UI unchanged. **Verify**: gate "failures never panic".
## 6. End-to-end + gates sweep
- [x] Exercise the full path against the live API if the local tidal config
is available (create a term, rename it, delete it, confirm the parent
listing and that a queued search track still resolves a URL); note the
outcome in the summary. If unavailable, rely on the offline tests and
say so.
- [x] Sweep: no `todo!()` left (workspace grep), fmt + clippy + tests green,
every `quality/node-editing.md` box checked, docs updated where
behavior shifted. Append the outcome + deviations to `plan/summary.md`.