New SourceOs variants: Android, IpadOs — routed to android-to-* and
ipad-to-* pattern files respectively. Pattern bodies assume zero terminal
experience; every command explained from first principles with App Store /
iOS analogies.
Dual-boot supplement system: PatternFile::extend() + load_supplement()
in patterns.rs; lib.rs loads dualboot-{windows,macos}.toml on top of the
primary pattern file when migration.dual_boot_with is set. Supplement
covers NTFS dirty flag from Fast Startup, clock skew (RTC local vs UTC),
GRUB overwrite by Windows Update, BitLocker, APFS/HFS+ access, T2 Secure
Boot.
complete_onboarding() now accepts dual_boot_with: Option<String> and
normalises it to "windows"/"macos". Onboarding.vue becomes a 3-step flow:
source OS -> (Linux distro if linux) -> (dual-boot if windows/macos).
Mobile users skip the dual-boot step entirely.
10 new pattern files (8 mobile + 2 supplements), config.rs tests updated.
Pattern files: 12 cross-family migration pairs covering debian, fedora, arch,
opensuse — each tuned to the user's prior tooling (apt, dnf, pacman, zypper).
Includes the custom linux-to-arch file for experienced distro-hoppers and
the macos-to-arch / windows-to-debian expansions from the prior session.
Code changes:
- patterns::load() accepts source_distro_family: Option<&str> — tries
specific debian-to-arch.toml before falling back to linux-to-arch.toml
- MigrationConfig adds source_distro_family: Option<String> with serde default
- complete_onboarding() accepts optional source_distro arg and derives family
via distro_family() for Linux-to-Linux migrations
- llm.rs: Ollama streaming client with Vec<u8> buffer for UTF-8 safety,
emit errors logged not silenced
- commands::chat: spawns stream task, returns immediately so frontend
isn't blocked waiting for full LLM response
- lib.rs: registers mod llm and commands::chat in invoke_handler
- lib.rs: replaces stub setup with full wiring: loads PatternFile from
config, extracts log_paths, spawns watcher, runs classifier loop in
async task, dispatches MatchedEvents via notify::dispatch
- lib.rs: config Mutex lock uses unwrap_or_else(|e| e.into_inner()) to
recover from poison instead of panicking
- patterns.rs: load() now tries three path candidates in order
(dev-relative, src-tauri-relative, system) before returning bail!
Validation loop (match_text, sources) retained inside candidate loop
- read_to_end + from_utf8_lossy replaces read_to_string so Wine/game logs
with Latin-1 bytes are handled via U+FFFD replacement instead of silently
dropping all events from that file
- bytes_read from I/O call used for new_pos (not content.len()) for correct
byte position accounting
- spawn_blocking handle is now awaited so panics inside the blocking task
surface to the caller instead of being silently swallowed
Replace flat watcher.rs with watcher/ module containing mod.rs plus stub
sub-modules for journald, kmsg, and inotify. Upgrades spawn() to accept
log_paths and return mpsc::Receiver<SystemEvent>. Updates lib.rs call site.
- load() now rejects patterns with empty match_text or empty sources list
- EventSource derives Serialize/Deserialize with serde tag for emit() readiness
- AppLog variant changed to struct form (AppLog { app }) for tagged enum compat
- classify() takes &SystemEvent directly (top-level use import, not per-fn)
- #[must_use] on classify()
- 5 new tests: any-source wildcard (journald+kmsg), applog mismatch, empty-field validation
Add EventSource enum and update SystemEvent in watcher.rs (M0 stub
updated to support Task 5 clean deletion). Create patterns.rs with
PatternFile/Pattern/MatchedEvent types, TOML loader, and classify()
matching against source + text. Five unit tests covering journald,
applog, no-match, and source discrimination cases.
- parse_id now strips both double and single quotes per os-release spec
- distro_family debian arm includes "mint" (legacy Linux Mint ID)
- Add tests: single-quoted ID round-trip, mint family classification