66 lines
3.6 KiB
Markdown
66 lines
3.6 KiB
Markdown
# Implementation summaries
|
||
|
||
## search (2026-07-20)
|
||
|
||
Built per `plan/search.md`: `%` inside `/tidal/search` opens a one-line input;
|
||
the term becomes a persistent (per-process) tree node holding Tidal search
|
||
results — 20 tracks queueable in place, plus artist/album results as canonical
|
||
`/tidal/artists/...` children. Creatable nodes carry an `is_creatable` flag
|
||
end-to-end (proto → provider → TUI marker `[%]` + pane hint). All 48 workspace
|
||
tests green; every gate in `quality/search.md` checked. Verified against the
|
||
live Tidal API: payload shapes match the existing models (probe kept as the
|
||
ignored `probe_search_shapes` test), and a full create→list→resolve-URL round
|
||
trip succeeded (`beatles` → 20 tracks / 40 children, idempotent, playable
|
||
stream URL from a search-track path).
|
||
|
||
The whole feature ran autonomously on user instruction; decisions were taken
|
||
without mid-stage confirmation and recorded in `architecture/search.md`
|
||
(options + decision per topic).
|
||
|
||
### Deviations from plan / architecture (search)
|
||
|
||
- **`Library::update` now concatenates tracks and children** (tracks first).
|
||
The old code showed tracks *instead of* children, which would have hidden
|
||
the artist/album results on term nodes — architecture assumed both would
|
||
render. Existing nodes are unaffected (they only ever carry one kind).
|
||
- **Search categories degrade independently**: a failing category logs and
|
||
contributes nothing; only all three failing is a `FetchError`. The plan
|
||
did not specify partial-failure behavior.
|
||
- **`get_lib_node` no longer requires a user id up front** — the gate moved
|
||
into the favorites arms (planned), which also means `create_lib_node`
|
||
validation works fully offline (used by the new unit tests).
|
||
- **End-to-end check ran at the provider layer** (temporary ignored test,
|
||
removed after passing) rather than driving the full TUI + server — no
|
||
interactive terminal/audio device in this environment. The gRPC handler and
|
||
TUI layers above it are covered by unit tests and review.
|
||
- **Environment note**: `target/` contains owner-built artifacts not writable
|
||
by this agent's user; builds/tests ran with a session-local
|
||
`CARGO_TARGET_DIR`. No repo change involved.
|
||
|
||
## help-modal (2026-07-20)
|
||
|
||
Built per `plan/help-modal.md`: `app/bindings.rs` (declarative
|
||
`BINDINGS` table + `lookup` + `key_label`), `app/help.rs` (overlay), the
|
||
`App::dispatch`/`DispatchResult` seam, and the rewired event loop in
|
||
`main.rs`. All 20 tests pass; every gate in `quality/help-modal.md` checked.
|
||
|
||
### Deviations from plan / architecture (help-modal)
|
||
|
||
- **Two-column modal layout.** The architecture assumed a single-column list;
|
||
the full table is ~50 rows and would not fit even a 100×40 frame. The modal
|
||
renders Global in the left column and Library + Queue stacked in the right
|
||
column, with the close keys as a footer line (`Close help: ?, Esc, q`)
|
||
derived from the `Scope::Help` bindings instead of a fourth listed group.
|
||
The open question "scroll vs truncate" stays resolved as truncate — but
|
||
after the column split the content fits ~34×94, so truncation only kicks in
|
||
on genuinely small terminals.
|
||
- **`Scope` derives `Hash`** (not in the stub) so the chord-uniqueness test
|
||
can use a `HashSet`.
|
||
- **`QueueInsertHere` description reworded** to "Insert library selection
|
||
after this track": `crabidy-server`'s `insert_tracks` splices at
|
||
`position + 1`. Same check confirmed the planned "Queue selection after
|
||
current track" wording for `LibraryQueueNext`.
|
||
- **`main.rs`** passes `tx` to `App::new` without the now-unneeded clone; the
|
||
`KeyCode`/`KeyModifiers`/`UiFocus`/`StatefulList` imports moved out with the
|
||
old match.
|