Files

54 lines
3.3 KiB
Markdown

# WristivoKit
Original Swift 6 foundation for the Wristivo prototype. No external dependencies.
Minimum declared platforms: iOS 17, watchOS 10, macOS 14.
- `RemoteCore`: command vocabulary, versioned envelope, receipts, transport contract,
and a stateful admission gate with one-second command lifetime, 250 ms maximum
future clock skew, monotonic sequence numbers, and a bounded 128-ID dedup window.
- `SamsungProtocol`: candidate local-TV WebSocket endpoint and click-frame encoding.
This module opens no sockets, pairs no devices, and supplies no TLS trust exceptions.
- `GestureCore`: deterministic gate for **already-normalized directional input**.
This is not a motion classifier. Raw Core Motion processing, calibration, wrist
orientation, and physical-device validation remain work for the gesture agent.
Run `swift test` from this directory. The tests use Swift Testing.
## Integration contract
Treat `CommandEnvelope` decoding as untrusted structure. A single transport actor
must call `CommandAdmission.admit(_:now:)` immediately before each send, and send
only `.accepted` commands. Do not enqueue commands for reconnection or automatically
retry a failed send. A consumed sequence stays consumed even when sending fails.
Use `startNewSession(televisionID:)` after reconnect, TV change, or a new control
session and convey the returned UUID to the watch before enabling gesture input.
The gate rejects old sessions; keep the actor alive for the entire session.
The caller supplies increasing sequence numbers starting at zero or one. At UInt64
exhaustion begin a fresh session, never wrap. The fixed defaults are prototype safety
policy, not measured latency claims. Both devices require approximately aligned wall
clocks. Use the sender's issue time and expiration; never refresh age upon reception.
Use the same JSON date strategy on both devices; the standard Foundation Codable
strategy is used by this package's round-trip test.
`sentToTransport` means submission to the transport only. It does not mean that the
TV accepted a command or that the on-screen state changed. The transport implementer
must map admission rejection to an appropriate receipt and expose a separate,
truthful pairing/connection state.
`DirectionalGestureGate.arm(sessionID:at:)` requires deliberate user action in the
foreground, followed by neutral input. Inputs use monotonic local seconds and the
normalized range [-1, 1], where positive x means right and positive y means up.
One event is allowed per neutral-to-direction excursion. Defaults propose 0.7
activation, 0.25 neutral, 0.3 seconds between emissions, and ten seconds armed.
Ambiguous diagonals, invalid input, and debounce suppression consume the excursion.
Return to neutral before another attempt. Call `disarm()` when app activity,
connectivity, selected television, or control session changes. Stop actual sensor
delivery in the adapter as well; this pure gate owns no sensor or background task.
Hostnames passed to `SamsungRemoteEncoder.endpoint(host:token:)` are bare hostnames
or IPv4 addresses; bracket IPv6 literals. The client display name is `Wristivo`.
The optional token is a secret and appears in the returned URL: do not log that URL.
The wire format and individual keys, particularly `KEY_PLAYPAUSE`, require physical
TV validation. Implement explicit supported-model capabilities before shipping.