Three related CLI bugs found during smoke testing:
1. `get_repository` used `config.get_workspace(name)` which expects the
UUID string, so `onyx list create -w dev` or `onyx task add -w dev`
always failed with "Workspace 'dev' not found". Unified CLI resolution
into a single `resolve_workspace()` helper that accepts either the
display name or the UUID; removed sync.rs's duplicated local copy.
2. `workspace switch`/`remove`/`retarget`/`migrate` only accepted the
display name — the error message even suggested "Use the workspace ID
instead" on ambiguous names, but IDs were then rejected. Updated
`resolve_name` to try the map key first.
3. `onyx workspace add` never set `current_workspace`, so the very next
command failed with "No workspace set. Use 'onyx init'..." even
though a workspace was just created. Now sets the new workspace as
current whenever none was previously selected, and reports the fact.
Updated the error message to point at the correct `workspace add` /
`workspace switch` commands instead of `init`.
- Replace 2 production unwrap() calls in workspace.rs with proper error
handling to prevent panics on inconsistent state
- Add AppState::save_config() helper to eliminate 11 duplicated
save_to_file patterns in Tauri lib.rs
- Log file watcher errors instead of silently swallowing them
- Harden path traversal check in storage.rs: re-verify after
canonicalization to catch symlink escapes
- Add Windows reserved device name handling (CON, NUL, etc.) to
sanitize_filename
- Clean up stale .tmp files from interrupted atomic writes on startup
All 107 core tests pass.
https://claude.ai/code/session_01EnSrQsowc64rAwzD9BnJpc
Change workspace identifiers from display names to UUID strings so
multiple workspaces can share the same display name. WorkspaceConfig now
stores a name field; add_workspace returns a generated UUID. Update all
CLI, Tauri commands, frontend stores and screens, WebDAV managed
directories, and tests to use/resolve workspace IDs; add helpers
find_by_name/resolve_name to map display names to IDs when needed. This
removes duplicate-name checks, avoids filesystem conflicts, and
preserves display names while using stable unique IDs internally.
Add rollback to move_task: if delete-from-source fails after write-to-
destination, clean up the duplicate. Reject list names with path separators
or '..' to prevent traversal; canonicalize() failures now return errors
instead of silently falling back to unchecked paths. Add validation and
rollback to CLI workspace migration: check destination is empty, track
moved files, and reverse on failure.