Files
wristivo/docs/ARCHITECTURE.md

61 lines
4.2 KiB
Markdown

# Architecture
## Decision
Use native SwiftUI applications and a local Swift package. The watch owns motion capture and recognition; the phone owns TV credentials and networking. No backend is required. Gitea stores development source, not user data.
```mermaid
flowchart LR
A[Watch Core Motion] --> B[GestureCore: calibrated discrete intent]
C[Watch buttons] --> D[WatchBridge: live message]
B --> D
D --> E[iPhone session / command admission]
F[iPhone buttons] --> E
E --> G[TVTransport actor]
G --> H[Samsung TV: paired local WebSocket]
I[Keychain token + TV trust record] --> G
G --> J[Send receipt / failure]
J --> D
```
Apple TN3135 restricts ordinary watch apps' low-level networking, including URLSessionWebSocketTask. A TV remote does not qualify for the audio, VoIP or tvOS discovery exceptions. See PLATFORM-FEASIBILITY. WatchConnectivity may wake the phone, but this does not grant unlimited phone background execution. Phone-lock/relaunch usability is a physical-hardware gate.
## Boundaries
| Location | Responsibility | Current state |
| --- | --- | --- |
| Apps/iPhone | Setup, manual remote, status and troubleshooting | Local demo UI |
| Apps/Watch | Session controls, touch remote, calibration UI | Local demo UI |
| Apps/Shared | Command presentation | Implemented |
| Packages/WristivoKit/RemoteCore | Commands, envelopes, admission and receipts | Foundation implementation |
| Packages/WristivoKit/SamsungProtocol | Key mapping and frame/URL encoding | Pure encoding, no socket |
| Packages/WristivoKit/GestureCore | Normalized directional excursion state machine | Algorithm seam, no raw sensor classifier |
| Adapters/TVTransport | iPhone URLSession WebSocket state machine | Planned |
| Adapters/WatchBridge | WCSession lifecycle and live delivery | Planned |
| Adapters/MotionCapture | Core Motion, coordinate calibration, normalization | Planned |
| Adapters/SecureStorage | Keychain token and trust persistence | Planned |
Package target source directories are under Sources. Imported modules use the module names, not the package name. OS adapters stay platform-specific. The integrator adds targets/dependencies or file memberships when implementations arrive.
## States and ownership
TV connection: `disconnected → connecting → awaitingApproval → ready`; errors lead to `denied`, `unauthorized`, `untrusted`, `timedOut` or `unavailable`. Socket-open alone is never `ready`. Require the model's authorization event. Changing target destroys the old connection and control session. Tokens never travel to Watch.
Watch: `idle → calibrating → ready → armed → paused`. A scene phase other than active, sensor error, TV switch, phone unavailability or stop disarms and clears accumulated motion. Resuming requires explicit re-arm and fresh neutral baseline. No automatic gesture on launch.
One iPhone actor serializes commands, session authorization, admission and TV send operations. Avoid holding unbounded work across `await`: actor reentrancy still requires cancellation/generation checks when a TV or session changes. At most one in-flight TV send and a small bounded queue; drop expired items. No backlog in WatchConnectivity transferUserInfo or application context.
## Prototype order
Build a phone-to-TV vertical slice first. Run a watch-button relay slice alongside raw motion capture/calibration work with a fake command sink. Only integrate gesture-to-TV output after each slice passes separately. UI agents work against fake services using shared contracts. The demo never silently becomes a live transport.
## Alternatives and decisions
- ADR-001: phone relay required by watch network constraints.
- ADR-002: active sessions only; no background mode misuse.
- ADR-003: no TV app required for initial local controller pairing. Pairing identity is a network controller label, not Bluetooth certification or TV app store registration.
- ADR-004: manual address first; discovery deferred to avoid blocking the free-account prototype on multicast entitlement work.
- ADR-005: no runtime third-party libraries in foundation; compatibility protocol remains an isolated replaceable adapter.
Contract changes require an integration decision entry with date, reason, affected agents, migration and tests. Do not maintain different command models in each app.