midi-harbor/specs/006-bluetooth-midi/tasks.md
2026-09-28 13:59:10 -05:00

5.9 KiB

Tasks: Bluetooth MIDI

Tasks from the task list, under the phase each was done in and by their original numbers. Phases are the order the project was built in, across every spec; 001's tasks give that order in full.

Phase 1: Setup (Shared Infrastructure)

Stage 0 spikes (retire RISK-2 and RISK-3 before committing dependencies)

  • T008 [P] Spike in spikes/ble-peripheral/ evaluating ble-peripheral-rust 0.2 on macOS and bluer 0.17 on Linux for BLE MIDI peripheral role, and blew 0.5 as a unified alternative — resolves RISK-2 (research R-006)

Phase 2: Foundational (Blocking Prerequisites)

Platform seam and fake

  • T037 [P] Define the BluetoothPlatform trait (scan, connect, disconnect, advertise) in crates/platform/src/bluetooth/mod.rs

Phase 8: User Story 6 — Bluetooth LE MIDI both directions (Priority: P5)

Goal: Connect out to BLE MIDI peripherals, and advertise this computer as one.

Independent Test: Scan, connect a peripheral, route it; separately advertise and connect from a phone or tablet (quickstart scenario 5).

Gate: the peripheral half depends on spike T008. If it failed on macOS, ship Linux-first and record the declared limitation per the plan's Complexity Tracking note.

Tests for User Story 6

  • T128 [P] [US6] Property tests in crates/blemidi/tests/codec.rs covering the 13-bit timestamp with wraparound, running status across packet boundaries, and SysEx split across packets (research R-006)
  • T129 [P] [US6] Fuzz target in fuzz/fuzz_targets/blemidi_codec.rs asserting no panic or unbounded allocation on hostile peripheral input (Principle V)
  • T130 [P] [US6] Test in tests/integration/bluetooth_unavailable.rs asserting missing adapter, adapter off and permission denied each report a specific reason and leave other features working (FR-021, FR-053)

Implementation for User Story 6

  • T131 [US6] Implement the BLE MIDI packet codec in crates/blemidi/src/codec.rs — service 03B80E5A-EDE8-4B33-A751-6CE34EC4C700, characteristic 7772E5DB-3868-4112-A1A9-F2669D106BF3, timestamp reconstruction with wraparound tracking (FR-019)
  • T132 [US6] Implement the BLE central role over btleplug 0.13 in crates/platform/src/bluetooth/central.rs — scan, connect, subscribe to notifications, write without response (FR-016, FR-017)
  • T133 [P] [US6] Implement the macOS BLE peripheral backend in crates/platform/src/bluetooth/peripheral_macos.rs using the crate chosen by spike T008 (FR-018)
  • T134 [P] [US6] Implement the Linux BLE peripheral backend in crates/platform/src/bluetooth/peripheral_linux.rs using bluer 0.17 GATT server and LE advertisement registration (FR-018)
  • T135 [US6] Implement pairing memory and automatic reconnection on device return in crates/daemon/src/bluetooth.rs (FR-020)
  • T136 [US6] Implement Bluetooth request handlers (StartBluetoothScan, StopBluetoothScan, ConnectBluetoothDevice, DisconnectBluetoothDevice, ForgetBluetoothDevice, SetPeripheralAdvertising) in crates/daemon/src/handlers/bluetooth.rs
  • T137 [P] [US6] Implement bluetooth scan|connect|disconnect|forget|advertise commands in crates/cli/src/bluetooth_cmd.rs, exiting 4 with guidance when unavailable (contracts/cli-interface.md §3)

Checkpoint: All four endpoint kinds are complete and mutually routable.

Phase 11: Convergence

  • T156 CRITICAL: Silence the destinations of every route from a Bluetooth source when its link is lost or a central leaves the advertised port, with a failure-injection test, in crates/daemon/src/bluetooth.rs per FR-026, Constitution I, US6/AC3 (contradicts) — done: both paths silence the routes from the source, with a test for each that failed before
  • T162 Map Bluetooth MIDI device timestamps to local time and deliver received messages by them rather than in arrival order, with a test, per FR-019, US6/AC4 (missing) — done: messages held to device time against the latest arrival, at most 10 ms (R-075)
  • T169 Follow the Bluetooth central's adapter state after startup and report the adapter as off when it is off or switched off, per FR-021, US6/AC6 (partial) — done: the central reads the radio's power at startup and follows btleplug's state updates, reporting the adapter off, or the refused permission on macOS, and forgetting what was in range; the daemon's scan plan already stops and restarts the scan from the capability; verified live on the Mac on 2026-09-23, where switching Bluetooth off in Control Center showed "the adapter is switched off" in capabilities within a second and switching it on showed it available again
  • T170 Give Bluetooth failures accurate reasons instead of AdapterUnavailable when there is no adapter, BlueZ is missing, or service discovery or subscription fails on a working radio, per SC-012 (partial) — done: service discovery and subscription failures on a radio that is still on are protocol_error with the radio's detail; for no adapter, one switched off or a missing BlueZ the owner chose to say only that Bluetooth is not available, so adapter_unavailable carries no advice and capabilities names the cause (R-077)
  • T171 Count malformed Bluetooth MIDI packets per endpoint and expose the count additively in the traffic counters, per Edge Case: malformed input (partial) — done: the central and both peripheral roles count each discarded packet on the endpoint's ring, and the dispatch task adds it to packets_malformed (field 9 of TrafficCounters), shown in status --json, the diagnostic report and the window's loss summary; ring overflow, which was only logged, now reaches messages_dropped the same way
  • T175 Make the GUI's Disconnect on a Bluetooth row close the Bluetooth link instead of calling the session-only disconnect, which fails, per FR-044 (contradicts) — done: a Bluetooth row's Disconnect calls the Bluetooth disconnect, with a test