Spotty Domain Policy
Relevant source files
The following files were used as context for generating this wiki page:
Spotty Domain Policy defines the portable, deterministic logic layer for the Spotty music client. It governs state transitions, queue management, device policies, and playback semantics without relying on external dependencies such as UI, networking, or audio hardware. This layer ensures that the application's core behavior remains consistent and verifiable across different execution environments.
The domain policy resides in the SpottyDomain target. It maintains strict isolation by prohibiting imports of AppKit, SwiftUI, AVFoundation, or SpottyPlaybackCore. By isolating pure policy from implementation details, the system achieves deterministic behavior for state updates and projections.
Architecture and Dependencies
Spotty follows a unidirectional dependency flow where the application depends on the core, which in turn depends on the domain. The domain remains the most portable part of the system, acting as a leaf node in the Swift dependency graph.
The diagram shows the hierarchical dependency structure of the Spotty project, highlighting the isolation of the domain layer.
Sources: AGENTS.md:38-40, Sources/SpottyDomain/AGENTS.md:7-10
Key Domain Components
| Component | Description |
|---|---|
| PlaybackState | An atomic presentation snapshot representing the current playback status. |
| PlaybackReducer | The sole entry point for mutating PlaybackState, ensuring deterministic transitions. |
| ResumeLoadPlan | Manages rehydration of user sessions and reconnection sequences using sticky URIs. |
| Projections | Logic that extracts specific views of the state, such as device connections or queue visibility. |
Sources: Sources/SpottyDomain/AGENTS.md:12-22, Sources/Spotty/Spotify/AGENTS.md:39-42
State Management and Transitions
The system treats PlaybackState as an immutable snapshot. All modifications occur through the PlaybackReducer, which applies incoming events to the current state to produce a new state. This design prevents partial in-place writes and ensures that every change is explicit and traceable.
The sequence diagram illustrates the deterministic state mutation flow through the Reducer.
Sources: Sources/SpottyDomain/AGENTS.md:12-14, Sources/Spotty/Spotify/AGENTS.md:11-13
Invariants for State Updates
- Atomicity: Transitions update the entire state object at once.
- Determinism: Given the same initial state and event, the reducer must produce the same output.
- Rejection Policy: The reducer rejects stale or superseded events based on epoch and revision semantics.
- Isolation: The reducer does not access globals, closures with side effects, or external storage.
Sources: Sources/SpottyDomain/AGENTS.md:11-17, Sources/Spotty/Spotify/AGENTS.md:15-18
Playback and Queue Policy
Domain policy manages the logic of how tracks are ordered and presented. It distinguishes between the protocol state (data from Spotify) and metadata labels (data for the UI).
Projection Logic
Projections are pure functions that transform raw protocol data into usable structures for the application:
- ConnectionSnapshotProjection: Handles session phases and empty device ID semantics.
- PlaybackSnapshotProjection: Manages transport states, URI handling, and timestamps.
- QueueService: Determines track precedence and maintains context identity. Upcoming rows are projected from unfiltered Connect tracks to ensure metadata does not erase authoritative state.
Sources: Sources/SpottyDomain/AGENTS.md:17-21, Sources/Spotty/Spotify/AGENTS.md:30-33
Resume and Rehydration
Rehydration does not rely on presentation snapshots. Instead, ResumeLoadPlan captures sticky resume-load URIs. This ensures that when a user reconnects, the rehydration sequence follows a consistent plan per engine session generation.
Sources: Sources/SpottyDomain/AGENTS.md:21-23, Sources/Spotty/Spotify/AGENTS.md:37-39
Verification and Testing
Domain policies are verified through SpottyDomainTests. These tests are designed to be fast, deterministic, and free of Rust dependencies or FFI calls.
This diagram contrasts the requirements for domain-level testing versus boundary-level testing.
Sources: Tests/AGENTS.md:3-6
- Coverage: Tests focus on pure policy, state transitions, sorting, and lifetime semantics.
- Wait Strategy: Domain tests use cooperative waits rather than fixed sleeps or blocking threads.
- Privacy: Tests utilize reduced, synthetic fixtures to avoid including real account data in the repository.
Sources: Tests/AGENTS.md:8-15, PRIVACY.md:41-43
Summary
The Spotty Domain Policy centralizes the application's critical decision-making logic into a portable, deterministic layer. By strictly isolating these policies from UI and IO concerns, Spotty ensures that playback behavior, session rehydration, and state transitions are predictable and easily testable. This architecture supports the project's goal of native macOS behavior while maintaining a thin adapter to the Rust-based playback engine.
Sources: AGENTS.md:38-42, README.md:19-21