- Add truncate_title() function for bead titles (max 60 chars with ellipsis)
- Add escape_project() to replace / with :: in mapping keys for filesystem safety
- Add InvalidInput error code for validation errors
- Add comprehensive tests for truncation, escaping, and Unicode handling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements core startup infrastructure:
- AppConfig for data directory paths
- ensure_data_dir() to create ~/.local/share/mc/
- verify_cli_dependencies() async CLI availability check
- load_with_migration() for state file loading with migration support
- init() main entry point coordinating lock acquisition and setup
- StartupWarning enum for non-fatal issues (missing CLIs, state reset)
- InitError enum with conversion to McError
Also exposes Bridge::with_data_dir() publicly (was test-only).
Includes 11 tests covering directory creation, lock acquisition,
lock contention, corrupt file handling, and config paths.
bd-3jh
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Log swallowed errors in file watcher and window operations (lib.rs, watcher.rs)
- Propagate recovery errors from bridge::recover_pending to SyncResult.errors
so the frontend can display them instead of silently dropping failures
- Fix useTauriEvent/useTauriEvents race condition where cleanup fires before
async listen() resolves, leaking the listener (cancelled flag pattern)
- Guard computeStaleness against invalid date strings (NaN -> 'normal'
instead of incorrectly returning 'urgent')
- Strengthen isMcError type guard to check field types, not just presence
- Log warning when data directory resolution falls back to '.' (state.rs, bridge.rs)
- Add test for computeStaleness with invalid date inputs
- Create ReasonPrompt dialog for capturing optional reasons
- Add quick tag buttons (Blocking, Urgent, Context switch, etc.)
- Support keyboard navigation (Escape to cancel)
- Handle text input with trimming and null for empty
- Different titles for different actions (set_focus, defer, skip)
- All 10 tests pass
Closes bd-2p0
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Completes persistence story and crash recovery hardening.
Nav store persistence:
- Wraps nav store with zustand persist middleware
- Persists activeView to localStorage under "mc-nav-store"
- Remembers which view you were on across sessions
Bridge tmp file cleanup (src-tauri/src/data/bridge.rs):
- New cleanup_tmp_files() method removes orphaned .json.tmp files
- Called on startup to clean up from crashes during save_map()
- Logs cleaned files for debugging
- Returns count of files removed
The atomic write pattern (write to .tmp, then rename) can leave
orphan files if the app crashes between write and rename. This
cleanup ensures we don't accumulate stale tmp files over time.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds the core sync engine that maps GitLab events (from lore CLI) to beads
tasks. This is the foundational data layer for Mission Control's unified
task view.
Bridge architecture:
- GitLabBeadMap: JSON file storing event -> bead_id mappings
- MappingKey: Type-safe keys for MR reviews, issues, and authored MRs
- Cursor: Tracks last sync and reconciliation timestamps
Crash-safety features:
- Write-ahead pattern: pending=true written before bead creation
- Atomic file writes via temp file + rename
- Recovery on startup: retries pending entries with bead_id=None
- flock(2) based single-instance locking (prevents concurrent MC)
Two-strike orphan detection:
- First miss sets suspect_orphan=true (items may temporarily vanish)
- Second miss closes the bead (confirmed deleted/merged)
- Reappearance clears the flag (healed)
Sync operations:
- incremental_sync(): Process since_last_check events
- full_reconciliation(): Cross-check all open items
- recover_pending(): Handle interrupted syncs
Dependencies added:
- libc: For flock(2) system call
- thiserror: For ergonomic error types
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>