- Standardize on bun: remove package-lock.json, add packageManager field,
gitignore non-bun lockfiles, fix stray npm install in android:build:clean
- Remove stale build logs and empty dirs (src-tauri/plugins, docs/tickets)
- Move android-dev.sh into scripts/
- Consolidate root docs into docs/ (docker/builder under docs/build/);
move the architecture overview to docs/architecture/README.md
- Extract Requirements Specification from README into docs/requirements.md
and slim README down to a project intro + docs index
- Fix internal references to the moved files
- Add #[specta::specta] to all 201 #[tauri::command] functions.
- Derive specta::Type on all IPC DTOs (repository/types, settings, player/storage/
download command DTOs, player enums, jellyfin SessionInfo/NowPlayingItem/PlayState,
ThumbnailCacheStats, DownloadInfo, CacheConfig, etc.).
- Replace tauri::generate_handler! with a tauri_specta::Builder + collect_commands!
in lib.rs (exports bindings.ts in debug builds).
Two contract changes required by specta constraints (frontend migration follows):
- specta caps command arity at 10 args: download_item_and_start / download_item /
download_video now take a single request struct (params bundled, body unchanged
via destructuring).
- specta can't parse split serde rename_all: SessionInfo/NowPlayingItem/PlayState
switched to rename_all = "PascalCase" (Jellyfin deserialization preserved; these
now serialize PascalCase to the frontend).
cargo check --lib is clean (0 errors). Frontend migration to bindings.ts is the next step.