File-to-Database Mapping
MonoTerm follows a clear write/read separation pattern.Copy
╔══════════════════════════════════════════════════════════════════════╗
║ WRITE/READ ARCHITECTURE ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ WRITE LAYER (Rust) READ LAYER (TypeScript) ║
║ ================== ====================== ║
║ ║
║ Rust PTY Log ────writes───▶ Frontend Polling ║
║ │ (control-tabs-worked) ║
║ ▼ ║
║ atomic-term.db ║
║ ║
║ Rust Session ────writes───▶ Frontend Recovery ║
║ │ (main app startup) ║
║ ▼ ║
║ session.db ║
║ ║
║ Rust OnIt ────writes───▶ Frontend Display ║
║ │ (project init, sidebar) ║
║ ▼ ║
║ onit.db ║
║ ║
║ Watcher Daemon ────writes───▶ Frontend Polling ║
║ │ (direct) (watcher tab) ║
║ ▼ ║
║ niia-watcher.db ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
Rust Modules (Writers)
The backend modules that write to databases.Copy
╔══════════════════════════════════════════════════════════════════════╗
║ RUST WRITE MODULES ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ MODULE DATABASE WHAT IT WRITES ║
║ ══════ ════════ ══════════════ ║
║ ║
║ PTY Log atomic-term.db Parsed terminal activity ║
║ (VTE Parser) File operations detected ║
║ from command output ║
║ ║
║ Session DB session.db Terminal heartbeats ║
║ Session state ║
║ Tab information ║
║ ║
║ OnIt onit.db Project information ║
║ Activity logs ║
║ Folder associations ║
║ ║
║ Auto-fix atomic-term.db Path corrections ║
║ (Cross-DB) (updates) Resolves truncated paths ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
TypeScript Modules (Readers)
The frontend modules that read from databases.Copy
╔══════════════════════════════════════════════════════════════════════╗
║ TYPESCRIPT READ MODULES ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ MODULE DATABASE WHAT IT READS ║
║ ══════ ════════ ═════════════ ║
║ ║
║ Worked Files atomic-term.db Recently worked files ║
║ Polling for sidebar display ║
║ ║
║ Project Init onit.db Project list ║
║ Folder mappings ║
║ ║
║ Watcher Tab niia-watcher.db File change events ║
║ Watch path status ║
║ ║
║ Terminals Tab session.db Active sessions ║
║ Recovery candidates ║
║ ║
║ Diff Viewer work-wiki-diff.db Git diff history ║
║ File versions ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
Terminal Activity Flow
From PTY output to worked files display.Copy
╔══════════════════════════════════════════════════════════════════════╗
║ TERMINAL ACTIVITY FLOW ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ STEP 1: PTY OUTPUT ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ PTY Daemon ──▶ Rust Backend ──▶ VTE Parser (Alacritty) │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
║ STEP 2: SAVE + EMIT ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ VTE Parser detects file operation │ ║
║ │ │ │ ║
║ │ │ INSERT INTO parsed_activities │ ║
║ │ ▼ │ ║
║ │ Auto-fix resolves truncated paths │ ║
║ │ │ │ ║
║ │ │ UPDATE path column │ ║
║ │ ▼ │ ║
║ │ Emit event to frontend │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
║ STEP 3: FRONTEND READ ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ Tauri invoke("get_worked_files") │ ║
║ │ │ │ ║
║ │ │ SELECT FROM parsed_activities │ ║
║ │ ▼ │ ║
║ │ Display in "Worked Files" sidebar │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
Session Recovery Flow
How sessions are recovered after app restart.Copy
╔══════════════════════════════════════════════════════════════════════╗
║ SESSION RECOVERY FLOW ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ STEP 1: SESSION CREATE ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ New terminal tab opened │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ INSERT INTO terminal_heartbeats │ ║
║ │ (terminal_id, instance_id, is_alive=1) │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
║ STEP 2: HEARTBEAT (every 10 seconds) ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ Frontend sends heartbeat │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ UPDATE terminal_heartbeats │ ║
║ │ SET last_heartbeat = NOW() │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
║ STEP 3: APP RESTART ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ Cleanup stale terminals (no heartbeat for 30s) │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ Find recoverable sessions (PTY socket still exists) │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ Reconnect to PTY daemon │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ Restore terminal display │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
File Watcher Flow
From file system event to UI display.Copy
╔══════════════════════════════════════════════════════════════════════╗
║ FILE WATCHER FLOW ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ STEP 1: DAEMON WRITE (Direct - No IPC) ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ OS detects file change │ ║
║ │ │ │ ║
║ │ │ Rust notify crate │ ║
║ │ ▼ │ ║
║ │ File Watcher Daemon │ ║
║ │ │ │ ║
║ │ │ Direct rusqlite (no IPC overhead) │ ║
║ │ ▼ │ ║
║ │ INSERT INTO file_events │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
║ STEP 2: UI POLLING (every 3 seconds) ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ Frontend polls for changes │ ║
║ │ │ │ ║
║ │ │ Tauri invoke("query_file_events") │ ║
║ │ ▼ │ ║
║ │ SELECT FROM file_events │ ║
║ │ WHERE timestamp > last_check │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ Update watcher tab UI │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
Design Principles Applied
Copy
╔══════════════════════════════════════════════════════════════════════╗
║ DESIGN PRINCIPLES ║
╠══════════════════════════════════════════════════════════════════════╣
║ ║
║ SIMPLICITY (SMPC) ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ [x] Direct rusqlite writes (no ORM overhead) │ ║
║ │ [x] Each Rust module handles ONE database │ ║
║ │ [x] Frontend uses simple invoke() for reads │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
║ ORDER FROM CHAOS (OFAC) ║
║ ┌───────────────────────────────────────────────────────────────┐ ║
║ │ [x] Heartbeat + cleanup pattern for recovery │ ║
║ │ [x] Emit for immediate updates, polling for history │ ║
║ │ [x] Daemon survives crash, writes continue │ ║
║ └───────────────────────────────────────────────────────────────┘ ║
║ ║
╚══════════════════════════════════════════════════════════════════════╝
Module Reference Table
| Layer | Module | Database | Direction |
|---|---|---|---|
| Rust | PTY Log | atomic-term.db | Write |
| Rust | Session DB | session.db | Write/Read |
| Rust | OnIt | onit.db | Write/Read |
| Rust | Auto-fix | atomic-term + niia-watcher | Cross-DB |
| Daemon | File Watcher | niia-watcher.db | Write |
| TypeScript | Worked Polling | atomic-term.db | Read |
| TypeScript | Watcher Tab | niia-watcher.db | Read |
| TypeScript | Terminals Tab | session.db | Read |