4.9 KiB
4.9 KiB
Tasks: Routing
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 6: User Story 4 — Routing and repeating between endpoints (Priority: P3)
Goal: Physical MIDI hardware as a first-class endpoint, and routes carrying any endpoint to any other — including a physical device repeated over the network or Bluetooth.
Independent Test: Plug in a physical device, route it to another endpoint, play it, verify arrival; unplug and replug and verify the route resumes on its own (quickstart scenario 3).
Tests for User Story 4
- T105 [P] [US4] Tests in
crates/core/tests/router.rscovering one-to-many and many-to-one delivery, cycle detection, broken-route reporting, and delivery continuing to reachable destinations when others are unavailable (FR-030a–b, FR-033, FR-035) - T106 [P] [US4] Test in
tests/integration/repeater.rsasserting a physical device routed to a network session survives unplug and replug with no stuck notes on the remote side (SC-010c) — incrates/daemon/tests/repeater.rs, two daemons joined by a real session over loopback; it found that silencing never reached a network session, and running the same thing across two machines found R-046
Implementation for User Story 4
- T111a [US4] Implement route suspension and resumption for every endpoint kind in
crates/core/src/router.rsandDaemon::router, keeping a route's configuration intact while either endpoint is unavailable and resuming delivery when it returns (FR-032) - T112 [US4] Implement the route graph with validation — no self-route, source has an input side, destination has an output side, no duplicate pairs — in
crates/core/src/router.rs(FR-015b, FR-030, FR-030b, data-model §5) - T113 [US4] Implement cycle detection on every route mutation in
crates/core/src/router.rs, marking affected routesLoopDetectedand warning without blocking creation (FR-033) - T114 [US4] Implement
OriginTagper-message loop suppression and the network session identifier incrates/core/src/router.rsandcrates/rtpmidi/src/session.rs, so cross-machine repeater loops are caught (research R-013, RISK-9) — caught without a wire marker, at the session-to-session route where every such loop closes, by recognising MIDI a session sent moments ago coming back; the route is switched off and the history says why;crates/core/src/loops.rs, R-062 - T115 [US4] Implement the routing hot path in
crates/daemon/src/dataplane.rsfanning messages from source ring buffers to destination ring buffers with no allocation, locks or logging (Principle III) - T117 [US4] Implement route request handlers (
CreateRoute,DeleteRoute,SetRouteEnabled) and physical device handlers (ListPhysicalDevices,ForgetPhysicalDevice,ResolveAmbiguousDevice) incrates/daemon/src/handlers/routes.rs(FR-031, FR-034) - T118 [P] [US4] Implement
route list|create|delete|enable|disablecommands incrates/cli/src/route_cmd.rs(contracts/cli-interface.md §4)
Checkpoint: The repeater works — hardware in one room drives hardware in another.
Phase 11: Convergence
- T160 Make stored routes identify their endpoints unambiguously across kinds that share a name, and use that in
Router::build, duplicate checks and rename rewriting, per FR-030, FR-004 (partial) — done: routes carry an optional kind per end, written when a name is shared or becomes shared; an unqualified shared name reads as broken - T177 Reword the GUI's loop note so it no longer says messages circulate, since delivery is direct-only, per FR-033 (contradicts) — done: worded as the command-line guide words it
Phase 12: The redesigned window
- T183 Let one route carry MIDI both ways: a
both_waysroute setting in the configuration and contract, the router delivering in both directions with loop detection covering both, an RPC to change a route's ends andboth_ways,route create --both-ways, and the window's route dialog, per FR-034a, FR-033 — done:both_wayson a route in the configuration and contract (Route.both_ways14,CreateRouteRequest.both_ways5, newUpdateRouteRPC); the router delivers back from the destination's MIDI In to the source's MIDI Out of the same numbers under the same route, refuses a route that would carry what a two-way route already does, marks a two-way route broken when a connector of the way back is missing, and treats one as an edge each way for loops without calling A and back a loop; editing a route silences it first and keeps whether it is switched on; silencing a two-way route stops notes at both ends, including when its destination goes away;route create --both-ways,route edit, and one shared route dialog in the window with a Both ways switch and ↔ on the row. Every new check was mutation-tested.