Skip to content

Commit ac10ec6

Browse files
leogdionclaude
andauthored
Final Fixes Before Merge (#5)
* fix: resolve watchOS test timing issues and update dependency versions - Fix race condition in stream tests by moving assertions outside confirmation blocks - Update Package.swift to use SundialKit 2.0.0-alpha.1 semantic version - Update documentation to reference alpha versions (SundialKit 2.0.0-alpha.1, SundialKitStream 1.0.0-alpha.1) - Add todo rule to disabled SwiftLint rules The stream tests (pathStatusStream, isExpensiveStream, isConstrainedStream) were failing on watchOS with Xcode 16.4 due to timing issues. Tests now wait for confirmation to complete before verifying captured values, eliminating the race condition that caused "Index out of range" fatal errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: add CLAUDE.md with project development guidelines Add comprehensive development documentation for Claude Code including: - Project overview and architecture details - Build, test, and linting commands - Code organization and style guidelines - Testing patterns and requirements - Swift 6.1 concurrency safety guidelines 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * reverting fix --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent cf1193b commit ac10ec6

6 files changed

Lines changed: 208 additions & 9 deletions

File tree

.swiftlint.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,5 @@ disabled_rules:
129129
- closure_parameter_position
130130
- trailing_comma
131131
- opening_brace
132-
- pattern_matching_keywords
132+
- pattern_matching_keywords
133+
- todo

CLAUDE.md

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
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.
8+
9+
## Development Commands
10+
11+
### Building
12+
13+
```bash
14+
# Build the package
15+
swift build
16+
17+
# Build including tests
18+
swift build --build-tests
19+
20+
# Run tests
21+
swift test
22+
```
23+
24+
### Linting
25+
26+
The project uses a comprehensive linting setup with SwiftLint, swift-format, and periphery (dead code detection):
27+
28+
```bash
29+
# Run all linting and formatting
30+
./Scripts/lint.sh
31+
32+
# Format only (skip linting checks)
33+
FORMAT_ONLY=1 ./Scripts/lint.sh
34+
35+
# Strict mode (used in CI)
36+
LINT_MODE=STRICT ./Scripts/lint.sh
37+
```
38+
39+
**Important**: Linting requires `mise` to be installed. The lint script uses mise to manage tool versions via `.mise.toml`.
40+
41+
### Testing
42+
43+
```bash
44+
# Run all tests
45+
swift test
46+
47+
# Run a specific test target
48+
swift test --filter SundialKitStreamTests
49+
50+
# Run a specific test class
51+
swift test --filter NetworkObserverTests
52+
53+
# Run a specific test method
54+
swift test --filter NetworkObserverTests.testStreamUpdates
55+
```
56+
57+
## Code Architecture
58+
59+
### Layer Architecture
60+
61+
SundialKitStream follows a three-layer architecture:
62+
63+
1. **Core Protocols** (Dependencies from SundialKit package):
64+
- `SundialKitCore` - Base protocols and types (`ActivationState`, `ConnectivityError`, etc.)
65+
- `SundialKitNetwork` - Network monitoring protocols (`PathMonitor`, `NetworkPing`, `PathStatus`)
66+
- `SundialKitConnectivity` - WatchConnectivity protocols (`ConnectivitySession`, `Messagable`)
67+
68+
2. **Observer Layer** (This package - SundialKitStream):
69+
- Actor-based observers: `NetworkObserver`, `ConnectivityObserver`
70+
- AsyncStream-based state delivery
71+
- Manages continuations and distributes updates to multiple subscribers
72+
73+
### Core Observers
74+
75+
#### NetworkObserver
76+
77+
Actor-based network connectivity monitoring with AsyncStream APIs:
78+
79+
- **Generic over**: `PathMonitor` (typically `NWPathMonitorAdapter`) and `NetworkPing`
80+
- **Streams**: `pathStatusStream`, `isExpensiveStream`, `isConstrainedStream`
81+
- **Thread Safety**: Actor isolation ensures safe concurrent access
82+
- **Location**: Sources/SundialKitStream/NetworkObserver.swift
83+
84+
#### ConnectivityObserver
85+
86+
Actor-based WatchConnectivity communication with AsyncStream APIs:
87+
88+
- **Protocols**: Conforms to `ConnectivitySessionDelegate`, `StateHandling`, `MessageHandling`
89+
- **Key Components**:
90+
- `ConnectivityStateManager` - Manages activation, reachability, and pairing state
91+
- `StreamContinuationManager` - Centralized continuation management for all stream types
92+
- `MessageDistributor` - Handles incoming message distribution to subscribers
93+
- `MessageRouter` - Routes outgoing messages through appropriate transports
94+
- **Streams**: `activationStates()`, `activationCompletionStream()`, `reachabilityStream()`, `messageStream()`, `typedMessageStream()`
95+
- **Location**: Sources/SundialKitStream/ConnectivityObserver.swift
96+
97+
### Key Architectural Patterns
98+
99+
#### AsyncStream Continuation Management
100+
101+
The codebase uses a centralized continuation management pattern via `StreamContinuationManager`:
102+
103+
- Each stream type has its own continuation dictionary keyed by UUID
104+
- Registration asserts prevent duplicate continuations
105+
- Removal asserts catch programming errors
106+
- Yielding iterates all registered continuations for fan-out distribution
107+
- **Location**: Sources/SundialKitStream/StreamContinuationManager.swift
108+
109+
#### State Management
110+
111+
`ConnectivityStateManager` coordinates state updates with stream notifications:
112+
113+
- Maintains `ConnectivityState` with activation, reachability, and pairing information
114+
- Synchronizes state updates with continuation notifications
115+
- Provides read-only snapshot accessors for current state
116+
- **Location**: Sources/SundialKitStream/ConnectivityStateManager.swift
117+
118+
#### Message Handling
119+
120+
Message flow uses a routing and distribution pattern:
121+
122+
- `MessageRouter` - Selects appropriate transport (interactive message, application context, etc.)
123+
- `MessageDispatcher` - Transforms protocol-level callbacks into async operations
124+
- `MessageDistributor` - Distributes received messages to all active stream subscribers
125+
- Supports both untyped (`[String: any Sendable]`) and typed (`Messagable`) messages
126+
127+
## Swift Version and Compiler Settings
128+
129+
This package requires **Swift 6.1+** and enables extensive experimental features:
130+
131+
- **Swift 6.2 Upcoming Features**: ExistentialAny, InternalImportsByDefault, MemberImportVisibility, FullTypedThrows
132+
- **Experimental Features**: BitwiseCopyable, BorrowingSwitch, NoncopyableGenerics, TransferringArgsAndResults, VariadicGenerics, and many more (see Package.swift:8-34)
133+
- **Strict Concurrency**: The project operates in Swift 6 strict concurrency mode
134+
135+
When writing new code, ensure:
136+
- All public types properly declare their concurrency characteristics (`actor`, `@MainActor`, `Sendable`)
137+
- No `@unchecked Sendable` conformances are added
138+
- AsyncStream continuations are managed through `StreamContinuationManager`
139+
140+
## File Organization
141+
142+
Source files use functional organization with extensions:
143+
144+
- Main type definition: `TypeName.swift`
145+
- Extensions by functionality: `TypeName+Functionality.swift`
146+
- Example: `ConnectivityObserver.swift`, `ConnectivityObserver+Lifecycle.swift`, `ConnectivityObserver+Messaging.swift`, `ConnectivityObserver+Streams.swift`
147+
148+
Tests follow a similar pattern with hierarchical organization:
149+
150+
- Test suites: `TypeName.swift`, `TypeName+Category.swift`
151+
- Individual test files: `TypeName.Category.SpecificTests.swift`
152+
- Example: `ConnectivityStateManager.swift`, `ConnectivityStateManager.State.swift`, `ConnectivityStateManager.State.UpdateTests.swift`
153+
154+
## Code Style and Linting
155+
156+
The project enforces strict code quality standards:
157+
158+
- **File Length**: Warning at 225 lines, error at 300 lines
159+
- **Function Body Length**: Warning at 50 lines, error at 76 lines
160+
- **Line Length**: Warning at 108 characters, error at 200 characters
161+
- **Cyclomatic Complexity**: Warning at 6, error at 12
162+
- **Indentation**: 2 spaces (configured in .swiftlint.yml:120)
163+
- **Access Control**: Explicit access levels required (`explicit_acl`, `explicit_top_level_acl`)
164+
- **File Headers**: All source files require proper copyright headers (enforced by Scripts/header.sh)
165+
166+
Disabled rules:
167+
- `nesting`, `implicit_getter`, `switch_case_alignment`, `closure_parameter_position`, `trailing_comma`, `opening_brace`, `pattern_matching_keywords`, `todo`
168+
169+
## Dependencies
170+
171+
This package depends on SundialKit v2.0.0+ which provides three products:
172+
173+
- `SundialKitCore` - Core protocols and types
174+
- `SundialKitNetwork` - Network monitoring abstractions over Apple's Network framework
175+
- `SundialKitConnectivity` - WatchConnectivity abstractions
176+
177+
## Platform Support
178+
179+
- iOS 16+
180+
- watchOS 9+
181+
- tvOS 16+
182+
- macOS 13+
183+
184+
## Testing Patterns
185+
186+
Tests use mock implementations for protocol-based abstractions:
187+
188+
- `MockPathMonitor` - Simulates network path changes
189+
- `MockNetworkPing` - Simulates ping operations
190+
- `MockConnectivitySession` - Simulates WatchConnectivity behavior
191+
- `TestValueCapture` - Captures async stream values for testing
192+
193+
When writing tests:
194+
- Use actor-isolated test methods when testing actors
195+
- Capture stream values with async task groups or `TestValueCapture`
196+
- Test both success and error paths for `Result`-based streams (e.g., `activationCompletionStream()`)
197+
- In order to run the builds and tests for iOS or watchOS, use xcodebuild.
198+
- Don't use swift package generate-xcodeproj

Package.resolved

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ let package = Package(
5959
)
6060
],
6161
dependencies: [
62-
.package(url: "https://github.com/brightdigit/SundialKit.git", branch: "v2.0.0")
62+
.package(url: "https://github.com/brightdigit/SundialKit.git", from: "2.0.0-alpha.1")
6363
],
6464
targets: [
6565
.target(

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ let package = Package(
7171
name: "YourPackage",
7272
platforms: [.iOS(.v16), .watchOS(.v9), .tvOS(.v16), .macOS(.v13)],
7373
dependencies: [
74-
.package(url: "https://github.com/brightdigit/SundialKit.git", from: "2.0.0"),
75-
.package(url: "https://github.com/brightdigit/SundialKitStream.git", from: "1.0.0")
74+
.package(url: "https://github.com/brightdigit/SundialKit.git", from: "2.0.0-alpha.1"),
75+
.package(url: "https://github.com/brightdigit/SundialKitStream.git", from: "1.0.0-alpha.1")
7676
],
7777
targets: [
7878
.target(

Sources/SundialKitStream/SundialKitStream.docc/Documentation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ Add SundialKit to your `Package.swift`:
3838

3939
```swift
4040
dependencies: [
41-
.package(url: "https://github.com/brightdigit/SundialKit.git", from: "2.0.0"),
42-
.package(url: "https://github.com/brightdigit/SundialKitStream.git", from: "1.0.0")
41+
.package(url: "https://github.com/brightdigit/SundialKit.git", from: "2.0.0-alpha.1"),
42+
.package(url: "https://github.com/brightdigit/SundialKitStream.git", from: "1.0.0-alpha.1")
4343
],
4444
targets: [
4545
.target(

0 commit comments

Comments
 (0)