This file defines repository-specific rules for coding agents (including Codex) working on SimpleRunningTracker.
Keep this project a clean, scalable SwiftUI scaffold that junior and intermediate developers can adopt and extend.
Prioritize:
- clear architecture boundaries
- safe concurrency
- permission-first location handling
- testable dependencies
- maintainable feature growth
- Keep Swift version compatibility at Swift 6.
- Do not add business logic directly in Views.
- Keep navigation ownership in
Scenetypes. - Keep persistence/state mutation in the store/service layer.
- Use protocol-driven dependency injection at boundaries.
- Keep store/service streaming based on
AsyncStreamwhere async updates are exposed. - Do not start location tracking/map-driven run flows before authorization is granted.
Scenes/: top-level navigation owners (NavigationStack+ destinations)Views/: screen UI onlyComponents/: reusable UI units shared by viewsViewModels/: presentation/business logic, async workflows, derived UI stateServices/: concrete service implementations (location + actor-backed store) + service containerProtocols/: dependency contracts (*Protocol)Routes/: route enums used by scene-owned navigationModels/: domain models
Sceneowns.navigationDestination(for:)for its flow.- Child views/components emit route values, but do not own destination mapping.
- Do not scatter navigation destination wiring across feature views.
- Views render state and forward user actions.
- ViewModels perform async work and hold mutable presentation state.
- If logic grows beyond simple UI glue, move it from View to ViewModel.
- Keep view models
@MainActorwhen publishing UI-facing state. - View starts async work using
Taskand calls async ViewModel methods.
- Persisted run data is owned by actor-backed store implementation.
- Expose async change streams with
AsyncStream. - Keep file persistence concerns in store layer only.
- Respect actor isolation and avoid redundant synchronization primitives.
- Location authorization must be checked before tracking starts.
- Map and run capture UI should not attempt location-driven updates when permission is unavailable.
- Depend on protocols (
*Protocol) at boundaries. - Compose concrete implementations in app root/container.
- Prefer initializer injection.
- Avoid direct concrete construction deep inside Views/ViewModels.