Merge pull request #35 from SteelDynamite/claude/audit-consistency-A816f

Fix documentation and code inconsistencies found during audit
This commit is contained in:
SteelDynamite 2026-04-06 05:09:27 -07:00 committed by GitHub
commit 8772338e0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 12 additions and 9 deletions

View file

@ -49,7 +49,7 @@ Workspaces are plain folders. Each task list is a subfolder containing `.listdat
The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`). Key UI patterns: The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`). Key UI patterns:
- **Sliding drawer**: Left panel (lists) slides with main content as one piece via `translateX`. 80vw wide. List items show checkmark for active list and chevron on hover. - **Sliding drawer**: Left panel (lists) slides with main content as one piece via `translateX`. 80cqi wide (80% container query inline size). List items show checkmark for active list and chevron on hover.
- **Three-panel slide**: Main content area is 300% wide with three panels (task list, task detail, subtask detail) that slide via `translateX` using a `taskStack` array. Stack depth 0 = list, 1 = task detail, 2 = subtask detail. - **Three-panel slide**: Main content area is 300% wide with three panels (task list, task detail, subtask detail) that slide via `translateX` using a `taskStack` array. Stack depth 0 = list, 1 = task detail, 2 = subtask detail.
- **Settings modal**: Per-workspace settings opened from workspace kebab menu. Shows WebDAV config (for webdav workspaces), sync controls, and theme selector. - **Settings modal**: Per-workspace settings opened from workspace kebab menu. Shows WebDAV config (for webdav workspaces), sync controls, and theme selector.
- **Workspace switcher**: Custom drop-up menu in drawer footer (left), kebab menu per workspace (right) with Settings option. - **Workspace switcher**: Custom drop-up menu in drawer footer (left), kebab menu per workspace (right) with Settings option.
@ -68,7 +68,7 @@ Pre-alpha. No users, no released builds, no data to migrate. Breaking changes to
- **Phase 1** (Core + CLI): Complete - **Phase 1** (Core + CLI): Complete
- **Phase 2** (WebDAV sync): Complete — remote folder browsing, checksum-based conflict resolution, auto-sync lifecycle, per-workspace sync interval - **Phase 2** (WebDAV sync): Complete — remote folder browsing, checksum-based conflict resolution, auto-sync lifecycle, per-workspace sync interval
- **Phase 3** (GUI MVP): Complete - **Phase 3** (GUI MVP): Complete
- **Phase 4** (Mobile): Tauri Android cfg-gated with tauri-plugin-credentials and safe area insets; needs `tauri android init` + build - **Phase 4** (Mobile): In progress — Android preliminaries done (file-watcher gating, tauri-plugin-credentials, safe area insets, Android targets configured); needs build verification and iOS setup
### GUI features done ### GUI features done
@ -84,7 +84,7 @@ Pre-alpha. No users, no released builds, no data to migrate. Breaking changes to
- Due date picker/editor (DateTimePicker in new task + task detail); `has_time: bool` field tracks whether time is set - Due date picker/editor (DateTimePicker in new task + task detail); `has_time: bool` field tracks whether time is set
- Move task between lists (inline list in kebab menu, no submenu) - Move task between lists (inline list in kebab menu, no submenu)
- List rename (inline input in main panel header via kebab) - List rename (inline input in main panel header via kebab)
- Group-by-due-date toggle per list (main panel kebab) - Group-by-due-date toggle per list (main panel kebab; persists flag but display sorting not yet implemented)
- Delete completed tasks (main panel kebab + subtask kebab, with confirmation dialogs) - Delete completed tasks (main panel kebab + subtask kebab, with confirmation dialogs)
- Keyboard shortcuts (Escape priority chain: settings → detail → list menu → drawer → menus) - Keyboard shortcuts (Escape priority chain: settings → detail → list menu → drawer → menus)
- Setup screen with 2-step mode selection (Local Folder vs WebDAV Server), window dragging, "Open Existing Folder" option, remote folder browsing - Setup screen with 2-step mode selection (Local Folder vs WebDAV Server), window dragging, "Open Existing Folder" option, remote folder browsing

View file

@ -508,10 +508,10 @@ pub fn delete_credentials(domain: &str) -> Result<()>;
**Primary**: Platform Keychain via `keyring` crate **Primary**: Platform Keychain via `keyring` crate
- Store WebDAV username + password in system keychain - Store WebDAV username + password in system keychain
- Key format: `com.onyx.webdav.{server-domain}` - Key format: `com.onyx.webdav.{server-domain}::{username}` (the `::` separator prevents key collisions when usernames contain dots)
- Works on: Windows (Credential Manager), macOS (Keychain), Linux (Secret Service), iOS/Android (Keystore) - Works on: Windows (Credential Manager), macOS (Keychain), Linux (Secret Service), iOS/Android (Keystore)
**Fallback**: Encrypted local storage if keychain unavailable **Fallback**: Not yet implemented (planned: encrypted local storage if keychain unavailable)
### Dependencies ### Dependencies
@ -527,7 +527,7 @@ keyring = "3.0"
- [x] WebDAV client implementation in core library - [x] WebDAV client implementation in core library
- [x] Credential storage (platform keychain) - [x] Credential storage (platform keychain)
- [x] Bi-directional sync (push/pull) - [x] Bi-directional sync (push/pull)
- [x] Conflict resolution (last-write-wins) - [x] Conflict resolution (remote wins; local recovered as duplicate)
- [x] Offline queue for pending operations - [x] Offline queue for pending operations
- [x] CLI: `sync --setup` command - [x] CLI: `sync --setup` command
- [x] CLI: `sync --push` command - [x] CLI: `sync --push` command

View file

@ -118,7 +118,10 @@ impl AppConfig {
// Atomic write: write to temp file then rename to prevent corruption on crash // Atomic write: write to temp file then rename to prevent corruption on crash
let temp = path.with_extension("tmp"); let temp = path.with_extension("tmp");
std::fs::write(&temp, &content)?; std::fs::write(&temp, &content)?;
std::fs::rename(&temp, path)?; if let Err(e) = std::fs::rename(&temp, path) {
let _ = std::fs::remove_file(&temp);
return Err(e.into());
}
Ok(()) Ok(())
} }

View file

@ -135,10 +135,10 @@ pub struct RemoteFileSnapshot {
/// | unchanged | modified | download | /// | unchanged | modified | download |
/// | deleted | unchanged | delete remote | /// | deleted | unchanged | delete remote |
/// | unchanged | deleted | delete local | /// | unchanged | deleted | delete local |
/// | modified | modified | last-write-wins (compare timestamps) | /// | modified | modified | conflict (remote wins; local recovered) |
/// | deleted | modified | download (remote wins) | /// | deleted | modified | download (remote wins) |
/// | modified | deleted | upload (local wins) | /// | modified | deleted | upload (local wins) |
/// | added | added | last-write-wins | /// | added | added | conflict (remote wins; local recovered) |
pub fn compute_sync_actions( pub fn compute_sync_actions(
local_files: &[LocalFileInfo], local_files: &[LocalFileInfo],
remote_files: &[RemoteFileSnapshot], remote_files: &[RemoteFileSnapshot],