Skip to content

Step 5: Logging polish + strict-concurrency flag flip + DocC catalog update #19

Description

@itsniper

Goal

Final polish pass after the architectural refactor: tighten residual Sendable conformances in the logging layer, enable swift-version 6 + -strict-concurrency=complete everywhere, update the DocC catalog to match the new public surface.

Context

See the investigation report at docs/investigations/swift6-concurrency-audit-2026-05-13.md, sections Recommendations §C, Migration order Step 5, and Preventive Measures.

The Willow 7.0 upgrade (commit 3657f45) resolved the bulk of the logging-layer concurrency issues. Only small polish remains.

Deliverable (Step 5 of 5 in the migration plan)

  1. ReliaBLEConfig explicit Sendable. Change public struct ReliaBLEConfig { … } to public struct ReliaBLEConfig: Sendable { … }. Compiler-synthesized today, but explicit is better as a public API surface.
  2. Verify OSLogWriter synthesizes Sendable under -strict-concurrency=complete. If it doesn't (e.g., on a future SDK where OSLog's Sendable status changes), add @unchecked Sendable (matches upstream Willow.OSLogWriter):
    public final class OSLogWriter: LogModifierWriter, @unchecked Sendable {  }
  3. Enable Swift 6 mode + complete strict concurrency in Package.swift for both ReliaBLE and ReliaBLEMock targets:
    .target(
        name: "ReliaBLE",
        swiftSettings: [
            .enableExperimentalFeature("StrictConcurrency"),
            .swiftLanguageMode(.v6),
        ]
    )
  4. DocC catalog update. Add a new Concurrency.md page documenting:
    • ReliaBLEManager is Sendable and callable from any actor (MainActor SwiftUI and background actors).
    • All actions are async.
    • All event surfaces return fresh per-subscriber AsyncStreams.
    • SwiftUI consumers should use .task { for await … } patterns.
    • BluetoothActor is internal; consumers should not reference it directly.
  5. Architecture diagram (optional) in DocC showing the isolation graph (ReliaBLEManagerBluetoothActor → delegate shim → CB).
  6. Smoke test: construct a ReliaBLEManager inside Task.detached and exercise every public method. See Tests/ReliaBLETests.
  7. Peripheral Sendable test: capture a Peripheral in a detached task; failure to compile catches accidental non-Sendable field regressions.

Decision: do NOT document the LoggingService.enabled race in DocC

The race is benign last-write-wins, inherited verbatim from Willow 7.0's deliberate upstream choice. A separate issue (itsniper/Willow#3) tracks the upstream fix; ReliaBLE will inherit it transparently when it lands. No ReliaBLE-side workaround or DocC note needed.

Acceptance criteria

  • swift build -strict-concurrency=complete clean on both targets.
  • swift test passes including the new smoke + Peripheral Sendable tests.
  • DocC builds clean (swift package generate-documentation). New Concurrency.md page renders.
  • ReliaBLEConfig: Sendable explicit.

Not in scope

  • SwiftLint rules / CI wiring — that's NFR 11 (separate parent issue).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions