This is a small SwiftUI + SwiftData app that tracks time for projects.
Core features implemented:
- Projects list with color and optional category
- Add and edit projects (name, color, category)
- Category manager (add/delete categories)
- Project detail view with start/pause/stop timer and a list of work sessions
- Sessions are stored in SwiftData models (
Project,WorkSession,Category) - Optional notes on past, completed, paused, and currently running sessions
- One app-wide timer with hourly local reminders and a Live Activity
- Weekly project/category reporting, including sessions that cross day or week boundaries
The app preserves data at two layers:
- Before SwiftData opens the database on launch, it makes and verifies a quiescent
copy of the SQLite store and its real
-wal,-shm, and-journalsidecars. The newest 5 distinct raw-store snapshots are retained. - Every persisted user change requires a verified, checksummed JSON snapshot first. The newest 20 distinct data states are retained. Unchanged background snapshots are deduplicated, so this does not create endless periodic backups.
- If the store cannot be opened and no verified JSON snapshot can be restored, the original files remain preserved and editing is locked instead of exposing a writable empty database.
If SwiftData cannot open the store after an app or OS update, the failed store is quarantined (up to 5 copies) and the newest valid JSON snapshot is restored into a fresh store. The restored records and relationships are compared with the snapshot before recovery is accepted.
DataSnapshotPayload.currentSchemaVersion is the recoverable-data schema baseline.
Snapshot V2 (before notes) remains readable and restores into V3 with empty notes.
Any future model change must update that snapshot schema and include migration tests
against a copy of the current store.
Build the app and unit tests with the Time scheme. Production-source data-safety
checks and the migration fixture are also directly executable on macOS:
scripts/test-data-safety.sh
scripts/test-schema-migration.shThe first command executes the production snapshot, raw archive, record-loss, duration-input, and note-normalization code. The migration test writes a V2 SwiftData database, opens it using the V3 notes model, verifies all records and relationships, then writes and re-reads a note.
Open the Time.xcodeproj in Xcode (or workspace) and run on a simulator or device.
- Sync (iCloud/CloudKit) can be added by moving to CloudKit-backed storage or using NSPersistentCloudKitContainer patterns.
- Exact historical allocation of old paused sessions is not possible because legacy data stores only total active time, not each active segment. Reports distribute that active time proportionally across the session's wall-clock span. New segment storage can be introduced as a future, snapshot-protected schema change.