Automerge Storage Architecture

Overview

Minuta uses Automerge CRDT format for data storage, enabling conflict-free multi-device sync via folder sync services (Dropbox, iCloud Drive, Google Drive).

Document Model

  • Tags: Single tags.automerge document containing all tags
  • Records: Individual YYYY-MM-DD_HHmmss.automerge files per time record
  • Images: Separate files (unchanged from JSON era)

Storage Services

HybridStorageService (orchestrates migration)
    |
    +-- AutomergeStorageService (primary, write path)
    |       - Binary .automerge format
    |       - LRU cache for documents
    |
    +-- LocalFileStorageService (legacy, read fallback)
    |       - JSON format
    |       - Read-only during migration
    |
    +-- MigrationService (one-time migration)
            - Converts JSON to Automerge on first launch

Conflict Resolution

  • Last-writer-wins per field: Concurrent edits merge via Automerge
  • ConflictResolutionService: Handles .automerge file merges when sync services detect conflicts

For the full concurrency story (flock, mtime-based cache invalidation, external-change polling, storage-path discovery across app and CLI), see Cross-Process Safety.

Migration

Migration is automatic on first launch:

  1. Check if tags.json exists and not already migrated
  2. Convert all tags to Automerge format
  3. Convert all records to Automerge format
  4. Mark migration complete in UserDefaults

Legacy JSON files are preserved (read-only fallback until user confirms data integrity).

File Locations

~/Documents/Minuta/
    tags.automerge              # All tags
    records/
        YYYY/
            MM/
                YYYY-MM-DD_HHmmss.automerge

Related Documentation