Integrate live phone and watch remote prototype with guarded motion control

This commit is contained in:
2026-09-18 19:11:52 +04:00
parent 3e787543c0
commit 8131f4f873
54 changed files with 4355 additions and 329 deletions
+11 -9
View File
@@ -24,16 +24,18 @@ Apple TN3135 restricts ordinary watch apps' low-level networking, including URLS
| 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/iPhone | Setup, manual remote, status and troubleshooting | Live composition with explicit demo mode |
| Apps/Watch | Session controls, touch remote, calibration UI | Live composition with explicit demo mode |
| 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 | Source/test package and injection seams ready; live WCSession implementation pending |
| Adapters/MotionCapture | Core Motion, coordinate calibration, normalization | Planned |
| Adapters/SecureStorage | Keychain token and trust persistence | Planned |
| Packages/WristivoKit/RemoteCore | Commands, envelopes, admission and receipts | Implemented and tested |
| Packages/WristivoKit/SamsungProtocol | Key mapping and frame/URL encoding | Encoding and bounded event parser |
| Packages/WristivoKit/GestureCore | Normalized directional excursion state machine | Conservative calibrated classifier; hardware thresholds unvalidated |
| Adapters/TVTransport | iPhone URLSession WebSocket state machine | Integrated prototype; hardware pending |
| Adapters/WatchBridge | WCSession lifecycle and live delivery | Live delegates, bounded messages and session negotiation |
| Adapters/MotionCapture | Core Motion, coordinate calibration, normalization | Integrated prototype; hardware pending |
| Adapters/SecureStorage | Keychain token and trust persistence | Integrated prototype; hardware pending |
Adapters/PhoneControl owns testable iPhone setup orchestration and selected-TV metadata. Apps/iPhone/PhoneAppComposition constructs one TVConnectionActor, one authorization store and one phone WCSession delegate. It publishes only the selected opaque ID, display name and readiness to the watch. Phone and watch commands have separate session admission state in the same TV actor and share its serialized socket drain.
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.
+10 -3
View File
@@ -1,12 +1,12 @@
# Command contract v1
Source of truth: `Packages/WristivoKit/Sources/RemoteCore`, including `WatchSession.swift`. The integration owner maintains these types. The v1 control-plane DTOs, codec and actor protocol are now defined. WCSession delivery and the production phone actor are still to be implemented; protocol definitions are not a functioning handshake.
Source of truth: `Packages/WristivoKit/Sources/RemoteCore`, including `WatchSession.swift`. The integration owner maintains these types. The v1 control-plane DTOs, codec and actor protocol are now defined. WCSession delivery and the production phone actor are integrated. Handshake behavior is covered by fake-session tests; real paired-device delivery is pending.
## Commands and envelope
`RemoteCommand`: up, down, left, right, select, back, home, playPause, volumeUp, volumeDown, mute. Wire values are the enum's raw strings. Unknown values fail decoding. No raw arbitrary Samsung keys from UI or watch.
`CommandEnvelope`: `schemaVersion` (1), `id` (UUID), `sessionID` (UUID), `televisionID` (UUID), `sequence` (UInt64), `issuedAt` (Date), `expiresAt` (Date), `command`. UUIDs identify local opaque records, not TV serial numbers or network addresses. Date encoding on the future bridge is explicitly JSON milliseconds since Unix epoch; both encoders/decoders must set the same strategy. Package round-trip tests alone are not sufficient to validate that adapter.
`CommandEnvelope`: `schemaVersion` (1), `id` (UUID), `sessionID` (UUID), `televisionID` (UUID), `sequence` (UInt64), `issuedAt` (Date), `expiresAt` (Date), `command`. UUIDs identify local opaque records, not TV serial numbers or network addresses. Date encoding on the bridge is explicitly JSON milliseconds since Unix epoch; both encoders/decoders must set the same strategy. Package round-trip tests alone are not sufficient to validate that adapter.
A session is issued by the phone for one selected paired TV, bound to the currently activated paired WCSession. The watch cannot select an arbitrary target by manufacturing an envelope. `BeginRemoteSessionRequest` returns `RemoteSessionGrant` with v1, sessionID, televisionID, issuedAt and maximumCommandLifetimeMilliseconds (1...1000); `EndRemoteSessionRequest` ends that exact session and returns `RemoteSessionEnded`. Errors use `RelayFailure`, which conforms to Error for Result return values. A new phone process, TV switch, re-pair, bridge deactivation or app stop invalidates old authorization. Starting a session must never issue a TV key.
@@ -30,8 +30,15 @@ Existing `RemoteTransport.send(_ envelope: CommandEnvelope) async -> CommandRece
The local `WatchPeerGeneration` is a fresh UUID per phone-side bridge activation. It is not Codable and must not cross the wire, persist, identify watch hardware, or come from the remote message. B serializes lifecycle delivery, awaits activation before forwarding requests, and passes the captured generation on every call. The phone actor rejects requests from non-current peers and ignores delayed deactivation for old peers. Repeated activation of the same peer is idempotent; activating a new peer invalidates previous grants. Repeated begin requests create fresh sessions and invalidate the previous session; B must serialize starts and ignore delayed replies after a lifecycle or local request-generation change. Stale end requests return sessionInvalidated and never end a newer session. After every suspension, the actor rechecks generation/session/target/deadline before sending. A protocol cannot enforce these semantics; A's tests must prove them.
GestureCore receives normalized inputs from the future MotionCapture adapter. Its thresholds are algorithm fixtures, not physically calibrated degrees or validated human-motion confidence. Sensor coordinate transforms and physical traces are required before claiming wrist-swipe recognition. Watch and phone UI depend on domain contracts, never Samsung frame strings.
GestureCore receives normalized rotation-rate inputs from the MotionCapture adapter. Its thresholds are algorithm fixtures, not physically calibrated degrees or validated human-motion confidence. Sensor coordinate transforms and physical traces are required before claiming wrist-swipe recognition. Watch and phone UI depend on domain contracts, never Samsung frame strings.
## Compatibility change policy
An additive optional field may remain v1 only if existing behavior stays safe. New command semantics, changed time units or altered authorization require a new schema version and explicit negotiation. Unsupported versions fail closed. Mixed-version phone/watch installations must show update guidance and preserve accessible phone control.
## Integration decision — 2026-09-18
PhoneControl composes one TVConnectionActor with KeychainTVAuthorizationStore. `sendPhoneCommand` creates a local envelope; watch envelopes enter through `submitWatchCommand`. Separate local/watch session counters feed a single actor-owned drain, with exactly one admission consumption per command. Phone actions do not replace the watch grant. Peer replacement or grant rotation during an active write closes the ambiguous socket; reconnect is explicit and never replays.
Configuration context now includes `isConnectionReady: Bool` (default false when absent) alongside the optional opaque ID/name. It never contains hostnames, certificates, tokens or commands. Old receivers that reject this additive key fail closed; deploy matching prototype phone/watch builds. A context snapshot is advisory, not authority: the phone actor still issues and validates every grant.
+29
View File
@@ -0,0 +1,29 @@
# First-device prototype
Integration branch: `integration/first-device-prototype`. Use this branch's Xcode project, not the original agents' worktrees. The integration commit accompanies this document; record `git rev-parse HEAD` in every device test. No remote push or signing configuration has been changed by the integrator.
## What is connected
- iPhone live setup → stable opaque TV identity → iPhone Keychain → one TVConnectionActor → TLS WebSocket.
- Watch Connect → phone-issued session → watch touch commands → same TV actor.
- Watch physical neutral calibration → explicit Start → up to ten seconds of sampled wrist rotation → conservative classifier → same live relay.
- Foreground interruption, reachability loss, expiry and Stop halt motion. No command backlog or automatic replay. Wrist/crown changes clear calibration.
- Demo is an explicit mode. Entering phone Demo disconnects live TV control. Watch Demo stops motion and ends its local relay session. Demo touch actions do not contact the TV.
## First run
1. Open `Wristivo.xcodeproj`, select your signing team in Xcode and install the iPhone/watch apps on the paired test devices. Device installation/provisioning remains a user step; unsigned builds do not prove it works.
2. Keep both apps foreground initially. On iPhone enter the TV address from the TV's network settings. Tap **Pair / pair again**, grant local-network access if prompted, and approve **Wristivo** using the existing TV controls.
3. If TLS fails and **Review TV certificate** appears, inspect the selected address and fingerprint. Approval is a separate explicit action, followed by a fresh Pair action. The fingerprint from the same connection does not independently authenticate the TV. A changed fingerprint discards the old token and requires pairing again. There is no plaintext fallback.
4. Test one iPhone direction and observe the TV separately. Stop if the TV does not pair, the certificate cannot be reviewed, or a command does not behave as expected. Do not mark compatibility from a transport receipt.
5. On watch tap **Connect to iPhone**, then test one watch touch direction. Touch controls do not need motion permission or calibration.
6. Choose the wrist/crown orientation, hold still for one second and tap **Calibrate**. Calibration uses actual sensor samples and times out after eight seconds if stability is not achieved. Tap **Start** for a ten-second motion session. Test one deliberate direction, returning to neutral. Axis mappings and thresholds are hypotheses until evaluated on hardware.
7. Verify Stop, expiry, app inactivity, relay loss and re-arm behavior before broader gesture trials. Record exact metadata and results using Q's plan and the hardware template.
Saved TV recovery uses only the stored token; it never silently falls back to pairing. If unavailable, unlock the phone, check network/permissions, then reconnect or pair explicitly. Forget disconnects and removes both the saved selection and security record. A deletion failure retains the identity so deletion can be retried.
## Pending gates
Physical TV pairing/TLS/key behavior; phone lock, wake and relaunch; watch sleep/inactivity; calibration and direction precision/recall; false triggers; battery; VoiceOver and layouts; signed install and archive privacy report. No app icons, App Store listing, distribution, trademark clearance or compatibility certification is completed by this integration.
Keep Q's original dated plan as a planning snapshot. Its demo-only observations describe the earlier worktree; the integration validation and privacy audit describe this build. Only later measured device evidence can close hardware gates.
+6 -6
View File
@@ -1,6 +1,6 @@
# Security and privacy design
Status: policy for production adapters; foundation demo performs no network or sensor access.
Status: integrated prototype policy and implementation. See the dated [static privacy audit](test-evidence/2026-09-18-integration-privacy-audit.md); signed archive and physical behavior remain unverified.
## Threats and controls
@@ -20,11 +20,11 @@ Self-signed certificates may be present on compatible TVs. Default trust must fa
| Data | Location | Retention / deletion |
| --- | --- | --- |
| TV nickname, local ID, address, capabilities | Phone local store (planned) | Until forget/reset; prevent unintended cloud sync |
| TV token and trust pin | iPhone Keychain (planned) | Until forget/revoke/re-pair; device-bound policy |
| Selected TV label and opaque ID | Watch context (planned) | Replace on selection; clear on forget |
| TV nickname, local ID, address, capabilities | iPhone device-only Keychain | Until forget/reset; prevent unintended cloud sync |
| TV token and trust pin | iPhone device-only Keychain | Until forget/revoke/re-pair; device-bound policy |
| Selected TV label and opaque ID | Watch application context | Replace on selection; clear on forget |
| Raw motion | Watch memory during active session | Discard immediately after bounded processing; no default recording |
| Calibration preferences | Local watch/phone (planned) | User-resettable, no cloud sync by default |
| Calibration preferences | Watch memory for this launch | User-resettable, no cloud sync by default |
| Diagnostic metrics | Local bounded buffer (planned) | No identifiers/tokens/raw motion; explicit export only |
No backend, account, ads, tracking or analytics SDK is included. Do not declare future data practices as implemented. If motion recordings are required for QA, ask explicit informed consent, store locally outside git, define deletion time and never upload by default. Export only redacted developer-selected evidence.
@@ -33,7 +33,7 @@ Keychain accessibility must be chosen against actual locked-phone relay needs. P
## Permissions and manifest
Production phone setup will need NSLocalNetworkUsageDescription. Motion capture needs an accurate motion purpose string where required by the adopted API/platform. Add permission strings when adapters are introduced; the demo requests neither. Manual unicast address entry is the baseline. SSDP/multicast discovery and Wake-on-LAN may need separate Apple networking entitlement review; do not enable blanket capabilities speculatively. NSBonjourServices entries apply only to the actual Bonjour service types used, not generic SSDP.
Phone setup declares NSLocalNetworkUsageDescription. Motion capture needs an accurate motion purpose string where required by the adopted API/platform. The watch declares NSMotionUsageDescription. Explicit demo controls request neither. Manual unicast address entry is the baseline. SSDP/multicast discovery and Wake-on-LAN may need separate Apple networking entitlement review; do not enable blanket capabilities speculatively. NSBonjourServices entries apply only to the actual Bonjour service types used, not generic SSDP.
The current PrivacyInfo.xcprivacy describes the current demo's lack of tracking, collection and required-reason API declarations. It is not a release approval or a blanket policy for future code. Re-audit FileTimestamp/SystemBootTime/DiskSpace/UserDefaults and other required-reason APIs, dependency manifests and data flows after each adapter. Declare truthful approved reasons actually applicable to the implementation. The public privacy policy and App Store answers must match the final binary and include support/contact details before submission.
+16
View File
@@ -40,3 +40,19 @@ Xcode required local Swift package manifest-cache write permission. Temporary sc
- No Gitea remote creation, authentication, push or CI execution. Owner will create the private repository.
Current app behavior is explicitly a local demo. The raw-motion pipeline, live adapters, final signing, icons, privacy policy and submission materials remain future milestones. Use Tests/Hardware/session-template.md for dated evidence when those pieces are implemented. Never convert a pending test to passed because a unit test or compilation succeeded.
## Integrated live prototype — 2026-09-18
Branch: `integration/first-device-prototype`. This record supersedes the demo-only state above for the accompanying integration commit. Q's dated plan remains a historical read-only review, not physical acceptance.
- **72 automated tests passed** across portable packages: WristivoKit 29 (RemoteCore 12, SamsungProtocol 7, GestureCore 10); WatchBridge 18 (Common 5, Phone 6, Watch 7); TVTransport 12; SecureStorage 6; PhoneControl 7. The combined check ran all packages; final focused runs covered the additional invalid-sample, corrupted-pin and explicit-certificate-consent regressions.
- `WRISTIVO_AGENT_BUILD=1 bash Scripts/check.sh --apps`: both generic unsigned iOS and watchOS app builds passed. Final source changes also passed an incremental iPhone build including its embedded watch target.
- `git diff --check`: passed. Privacy plist syntax: passed.
- Inspected generated app Info.plists: local-network purpose on phone, motion purpose on watch; both bundle PrivacyInfo.xcprivacy. No UIBackgroundModes or blanket NSAppTransportSecurity exception. Phone declares all four interface orientations.
- Fake tests exercise relay timeout with a suspended coordinator, bounded outstanding requests, stale peer/end/grant handling, reachability disarm, duplicate responses, finite TV writes, ready-socket revocation, stable saved-TV identity, partial deletion recovery, explicit pin consent, changed pin token removal and no replay after ambiguous sends.
Host restrictions: nested manifest sandbox disabled only for these local dependency-free packages; caches redirected to temporary paths, with scoped Xcode manifest-cache permission. CoreSimulator service was unavailable, but generic device compilation succeeded. No simulator launch or UI runtime check is claimed. Compiler emitted the tooling notice that AppIntents metadata extraction was skipped; no AppIntents integration is included.
Still **not run**: signed installation/Keychain tests, physical pairing or TLS, actual Samsung key behavior, real WatchConnectivity reachability/wake, locked or terminated phone, motion recognition/false triggers, accessibility runtime, battery/latency, signed archive/privacy report and App Store review. Prototype builds do not close those gates.
Use [FIRST-DEVICE-PROTOTYPE.md](FIRST-DEVICE-PROTOTYPE.md) and [Q's plan](test-evidence/2026-09-18-q-hardware-release-plan.md) for the next steps. No code was pushed or distributed.
+2 -1
View File
@@ -59,7 +59,8 @@ Before dispatch, I creates a branch/worktree from the same baseline commit and r
| Workstream | Owner/task | Base SHA | State | Evidence / blockers |
| --- | --- | --- | --- | --- |
| A–Q implementation | Unassigned | Set at dispatch | Planned | Requires hardware and agreed contracts |
| A–F implementation | Parallel implementation agents + integrator | a92698e / 3e78754 | Combined on integration/first-device-prototype | See VALIDATION.md; physical gates pending |
| Q hardware/release | Owner-run Q task | a92698e planning snapshot | Planning complete; device execution pending | docs/test-evidence/2026-09-18-q-hardware-release-plan.md |
| I foundation | Coordinating engineer | Initial repository | Prepared | See VALIDATION.md |
## Merge acceptance
@@ -0,0 +1,20 @@
# Integrated prototype static privacy/API audit — 2026-09-18
Scope: tracked source and local package graph on `integration/first-device-prototype`. This is a static review and unsigned build check, not a signed archive privacy report or App Store acceptance.
| Surface | Implemented use / retention | Declaration / remaining evidence |
| --- | --- | --- |
| iPhone URLSession | User-selected TV, TLS WebSocket, ephemeral session; credentials never logged or sent to watch | NSLocalNetworkUsageDescription; real prompt/denial and ATS/TLS behavior pending |
| WatchConnectivity | Live bounded commands/replies; latest opaque TV ID, label and readiness in context | No tokens, hostnames, motion samples, certificates or command backlog in context |
| Core Motion | Watch device-motion rotation rates at requested 50 Hz, neutral calibration, bounded active sessions | NSMotionUsageDescription; samples in memory; physical permission/lifecycle behavior pending |
| Security / CryptoKit | Per-TV token/pin and selected-TV metadata on iPhone, SHA-256 certificate comparison | Device-only Keychain, candidate AfterFirstUnlock accessibility to evaluate locked-phone relay; no shared access group or cloud sync |
| Required-reason APIs | No direct UserDefaults/AppStorage, systemUptime/mach_absolute_time, file timestamps, disk-space queries or active-keyboard enumeration found in app/adapter/core sources | Empty NSPrivacyAccessedAPITypes retained for reviewed source; ContinuousClock and CM sample timestamps replace boot-time API calls |
| Collection / tracking | No developer backend, analytics, ads or third-party runtime SDK | Empty collected-data categories and tracking=false retained; archive and store answers require release review |
App-generated data stays between the user's devices and selected TV. This does not excuse a release privacy policy. No raw motion persistence/export was added. Calibration and orientation are held in watch memory. Forget removes selected-TV metadata, token and trust record; device Keychain deletion needs signed hardware evidence. No background workout/audio/location entitlement or blanket ATS exception was introduced.
The certificate approval screen explains unauthenticated first-use trust. Approval stores only the exact per-TV SHA-256 pin. Challenge failure stops the connection; a UI review candidate does not itself approve trust. Changed-certificate approval drops prior credentials.
Source audit used searches for the required-reason API families plus manual review of every adapter and the two composition roots. Both app Info.plists and bundled PrivacyInfo.xcprivacy must be checked in the generated build; a signed release archive privacy report remains mandatory.
References: [Apple required-reason API categories](https://developer.apple.com/documentation/bundleresources/app-privacy-configuration/nsprivacyaccessedapitypes/nsprivacyaccessedapitype), [Apple local-network privacy TN3179](https://developer.apple.com/documentation/technotes/tn3179-understanding-local-network-privacy). Local-network permission has no general status-query API; the UI does not claim that a failed socket proves denial.
@@ -0,0 +1,50 @@
# Q hardware and release review — 2026-09-18
Status: planning and read-only review. No physical-device, TV, accessibility-runtime, signed-install, or release-archive test was run. This record is for the integrated commit; it must not be treated as acceptance evidence for the current dirty worktree.
## Review basis
- Baseline reviewed: `a92698e1e6a6ab33c2e4cef47a4c54fb1f59ac20` (worktree also contains uncommitted changes from other workstreams).
- Documents: `PRODUCT`, `ARCHITECTURE`, `CONTRACTS`, `PLATFORM-FEASIBILITY`, `GESTURE-SPEC`, `SECURITY-PRIVACY`, `RELEASE-CHECKLIST`, `VALIDATION`, `BRAND-AND-IP`, `DEPENDENCIES-AND-ASSETS`, and `Tests/Hardware/session-template.md`.
- Static checks run: `git diff --check` passed; `plutil -lint Resources/PrivacyInfo.xcprivacy` passed.
- Existing validation says 14 package tests and unsigned generic iOS/watchOS builds passed, but no simulator launch, signed install, physical relay, motion, TV, accessibility runtime audit, or archive privacy report was performed.
## Findings and release impact
1. The hardware matrix has no dated session record yet. The candidate devices are only user-reported: Apple Watch Ultra 2, iPhone 13 Pro Max, and Samsung `QA85Q8FAAUXZN`. Record exact Settings/label values, OS/firmware builds, region, wrist/crown orientation, topology, commit, and debugger state before any result is called a pass.
2. The following cases are mandatory and currently pending: pairing denial/timeout/revocation, certificate change, locked or suspended phone, phone/watch reboot, inactive watch, network loss/packet loss, clock skew, duplicate/stale/wrong-session messages, TV-off behavior, and ordinary-motion false triggers.
3. `Resources/PrivacyInfo.xcprivacy` is syntactically valid and empty for the demo. It is not release evidence. After integration, audit both executable targets and every linked SDK/adapter for local-network, motion, Keychain, WatchConnectivity, required-reason APIs, data collection, and purpose strings; generate and inspect the archive privacy report.
4. The current iPhone UI has an accessibility hint written as `"Sends one (command.title) command"`; this will be spoken literally unless corrected by the owning UI agent. Verify the integrated UI with VoiceOver, Dynamic Type, contrast/non-color status cues, touch targets, haptic alternatives, and manual fallback. This is a review finding, not an implementation change by Q.
5. The current watch shell marks calibration complete in the demo path without physical calibration evidence. Keep the demo label and do not use it as recognition evidence. Integrated hardware testing must prove calibration, explicit arm, neutral return, disarm on inactivity, and re-arm after resume.
6. No compatibility or TV-execution claim is supportable yet. A socket write/transport receipt is not a TV acknowledgement. Release copy must name only tested model/firmware combinations and retain the independent Samsung/Apple disclaimer and provisional-brand review.
7. No beta distribution is authorized until developer membership, signing/provisioning, privacy/support materials, and archive review are available. Personal-team device testing is separate from TestFlight/App Store distribution.
## Physical setup required before testing
Use the owner's paired devices first, without assuming “latest” versions:
- iPhone: exact model, iOS version and build from Settings; signed integrated app build number and commit.
- Watch: exact model, watchOS version/build, left or right wrist, crown toward/away from hand, paired iPhone, and whether the watch app was launched from the Home Screen with Xcode detached.
- TV: model code from Settings and physical label, region, firmware/Tizen version, TV power state, and whether the TV was factory-reset or already has a Wristivo authorization.
- Network: same LAN or guest/VLAN, Wi-Fi bands/AP isolation, IPv4/IPv6 if relevant, and whether the phone/watch/TV changed networks during a case. Redact addresses, tokens, certificate material, and household identifiers.
- Timing/evidence: synchronized video or a justified same-clock method; separate monotonic clocks must not be compared directly. Record warm/cold state, battery levels, display state, sensor rate, and debugger attached/detached.
- People/data: consenting testers, no personal accounts or copyrighted TV content in captures, raw motion outside git with an explicit deletion date, and redacted screenshots/video only.
## Execution procedure for the integrated commit
1. Record the session header from `Tests/Hardware/session-template.md`, integrated commit/build, exact hardware, network topology, permissions, and debugger state. Install cleanly, then repeat key lifecycle cases with Xcode detached.
2. Reset the test fixture. On the phone, grant local-network access only when requested. On the TV, start pairing and verify the displayed controller name is `Wristivo`; approve with the existing remote. Capture the user-visible state, never the token or certificate secret.
3. Repeat setup with local-network denial, TV denial, timeout, revoked authorization, forgotten TV, changed certificate, TV off, wrong network, and network interruption. Confirm recoverable UI, no queued command, no silent trust acceptance, and explicit re-pair where required.
4. Establish the phone touch baseline: send each supported touch command one at a time and verify the observed TV effect separately from the app receipt. Include back/home/playback/volume/mute and record unsupported/uncertain outcomes without retrying automatically.
5. Establish the watch touch relay baseline: reachable phone, locked phone, suspended phone, phone app terminated, watch display sleep, watch app inactive, phone reboot, watch reboot, and phone out of range. Record delivery, latency, failures, and whether any stale action executes after recovery.
6. For gestures, keep tuning and final evaluation samples separate. For each wrist/crown configuration, run 20 prompted trials per direction across at least five consenting testers where practical. Include return-to-neutral, held pose, reverse motion, diagonals, wrist lowering, conversation gestures, reaching, posture changes, and resting while armed. Count TP/FP/FN, wrong direction, duplicate, missed, and no-command trials; do not discard failures.
7. Interrupt every armed run with scene inactivity, notification/app switch, relay loss, target switch, sensor error, stop, expiry, and resume. Confirm sensing stops, pending candidates clear, no command is replayed, and explicit re-arm plus fresh neutral baseline is required.
8. Exercise protocol admission with controlled redacted fixtures or an approved test harness: future timestamp, stale/expired, lifetime over one second, time skew, duplicate ID, non-increasing sequence, wrong session/TV/schema, malformed/oversize payload, and reconnect after ambiguous transport failure. Confirm fail-closed rejection and no automatic replay.
9. Measure latency from motion completion to observed TV effect for warm and cold/wake paths. Report sample size, p50/p95, failures/timeouts, and timing method. Measure battery/thermal impact for 30 minutes of repeated use against an idle/disarmed baseline with starting/ending levels and display/sensor conditions.
10. Run accessibility review on phone and watch: VoiceOver rotor/order and labels, Larger Text/Dynamic Type, contrast and non-color state cues, 44-point phone controls, smallest declared watch layout, touch-only operation with motion disabled, haptic alternatives, and error recovery. Record each failure, not just a screenshot of the happy path.
11. Audit the final signed archive: generated privacy manifests and required-reason declarations, Info.plist usage strings, entitlements, SDK/dependency/asset provenance, demo labeling, unsupported claims, support URL/privacy policy, review notes, and signing/membership readiness. Do not distribute a beta until the release owner signs these gates.
## Required result format
Copy `Tests/Hardware/session-template.md` for each integrated commit. Every row must say pass, fail, or not run and include measured evidence. Add the gesture confusion matrix, latency and battery tables, privacy/asset/accessibility findings, exact build/commit, and unresolved risks. Keep all currently unrun cases marked **pending/not run**; unit tests, generic builds, simulated TV behavior, and a successful socket write cannot substitute for physical evidence.