This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
SundialKitStream is a modern Swift 6.1+ async/await observation plugin for SundialKit, providing actor-based observers with AsyncStream APIs for network monitoring and WatchConnectivity communication. The package prioritizes strict concurrency safety, avoiding @unchecked Sendable conformances in favor of proper actor isolation.
# Build the package
swift build
# Build including tests
swift build --build-tests
# Run tests
swift testThe project uses a comprehensive linting setup with SwiftLint, swift-format, and periphery (dead code detection):
# Run all linting and formatting
./Scripts/lint.sh
# Format only (skip linting checks)
FORMAT_ONLY=1 ./Scripts/lint.sh
# Strict mode (used in CI)
LINT_MODE=STRICT ./Scripts/lint.shImportant: Linting requires mise to be installed. The lint script uses mise to manage tool versions via .mise.toml.
# Run all tests
swift test
# Run a specific test target
swift test --filter SundialKitStreamTests
# Run a specific test class
swift test --filter NetworkObserverTests
# Run a specific test method
swift test --filter NetworkObserverTests.testStreamUpdatesSundialKitStream follows a three-layer architecture:
-
Core Protocols (Dependencies from SundialKit package):
SundialKitCore- Base protocols and types (ActivationState,ConnectivityError, etc.)SundialKitNetwork- Network monitoring protocols (PathMonitor,NetworkPing,PathStatus)SundialKitConnectivity- WatchConnectivity protocols (ConnectivitySession,Messagable)
-
Observer Layer (This package - SundialKitStream):
- Actor-based observers:
NetworkObserver,ConnectivityObserver - AsyncStream-based state delivery
- Manages continuations and distributes updates to multiple subscribers
- Actor-based observers:
Actor-based network connectivity monitoring with AsyncStream APIs:
- Generic over:
PathMonitor(typicallyNWPathMonitorAdapter) andNetworkPing - Streams:
pathStatusStream,isExpensiveStream,isConstrainedStream - Thread Safety: Actor isolation ensures safe concurrent access
- Location: Sources/SundialKitStream/NetworkObserver.swift
Actor-based WatchConnectivity communication with AsyncStream APIs:
- Protocols: Conforms to
ConnectivitySessionDelegate,StateHandling,MessageHandling - Key Components:
ConnectivityStateManager- Manages activation, reachability, and pairing stateStreamContinuationManager- Centralized continuation management for all stream typesMessageDistributor- Handles incoming message distribution to subscribersMessageRouter- Routes outgoing messages through appropriate transports
- Streams:
activationStates(),activationCompletionStream(),reachabilityStream(),messageStream(),typedMessageStream() - Location: Sources/SundialKitStream/ConnectivityObserver.swift
The codebase uses a centralized continuation management pattern via StreamContinuationManager:
- Each stream type has its own continuation dictionary keyed by UUID
- Registration asserts prevent duplicate continuations
- Removal asserts catch programming errors
- Yielding iterates all registered continuations for fan-out distribution
- Location: Sources/SundialKitStream/StreamContinuationManager.swift
ConnectivityStateManager coordinates state updates with stream notifications:
- Maintains
ConnectivityStatewith activation, reachability, and pairing information - Synchronizes state updates with continuation notifications
- Provides read-only snapshot accessors for current state
- Location: Sources/SundialKitStream/ConnectivityStateManager.swift
Message flow uses a routing and distribution pattern:
MessageRouter- Selects appropriate transport (interactive message, application context, etc.)MessageDispatcher- Transforms protocol-level callbacks into async operationsMessageDistributor- Distributes received messages to all active stream subscribers- Supports both untyped (
[String: any Sendable]) and typed (Messagable) messages
This package requires Swift 6.1+ and enables extensive experimental features:
- Swift 6.2 Upcoming Features: ExistentialAny, InternalImportsByDefault, MemberImportVisibility, FullTypedThrows
- Experimental Features: BitwiseCopyable, BorrowingSwitch, NoncopyableGenerics, TransferringArgsAndResults, VariadicGenerics, and many more (see Package.swift:8-34)
- Strict Concurrency: The project operates in Swift 6 strict concurrency mode
When writing new code, ensure:
- All public types properly declare their concurrency characteristics (
actor,@MainActor,Sendable) - No
@unchecked Sendableconformances are added - AsyncStream continuations are managed through
StreamContinuationManager
Source files use functional organization with extensions:
- Main type definition:
TypeName.swift - Extensions by functionality:
TypeName+Functionality.swift - Example:
ConnectivityObserver.swift,ConnectivityObserver+Lifecycle.swift,ConnectivityObserver+Messaging.swift,ConnectivityObserver+Streams.swift
Tests follow a similar pattern with hierarchical organization:
- Test suites:
TypeName.swift,TypeName+Category.swift - Individual test files:
TypeName.Category.SpecificTests.swift - Example:
ConnectivityStateManager.swift,ConnectivityStateManager.State.swift,ConnectivityStateManager.State.UpdateTests.swift
The project enforces strict code quality standards:
- File Length: Warning at 225 lines, error at 300 lines
- Function Body Length: Warning at 50 lines, error at 76 lines
- Line Length: Warning at 108 characters, error at 200 characters
- Cyclomatic Complexity: Warning at 6, error at 12
- Indentation: 2 spaces (configured in .swiftlint.yml:120)
- Access Control: Explicit access levels required (
explicit_acl,explicit_top_level_acl) - File Headers: All source files require proper copyright headers (enforced by Scripts/header.sh)
Disabled rules:
nesting,implicit_getter,switch_case_alignment,closure_parameter_position,trailing_comma,opening_brace,pattern_matching_keywords,todo
This package depends on SundialKit v2.0.0+ which provides three products:
SundialKitCore- Core protocols and typesSundialKitNetwork- Network monitoring abstractions over Apple's Network frameworkSundialKitConnectivity- WatchConnectivity abstractions
- iOS 16+
- watchOS 9+
- tvOS 16+
- macOS 13+
Tests use mock implementations for protocol-based abstractions:
MockPathMonitor- Simulates network path changesMockNetworkPing- Simulates ping operationsMockConnectivitySession- Simulates WatchConnectivity behaviorTestValueCapture- Captures async stream values for testing
When writing tests:
- Use actor-isolated test methods when testing actors
- Capture stream values with async task groups or
TestValueCapture - Test both success and error paths for
Result-based streams (e.g.,activationCompletionStream()) - In order to run the builds and tests for iOS or watchOS, use xcodebuild.
- Don't use swift package generate-xcodeproj