# RD.1 Watch surface integration

## Authority and selection

The phone is the only composer of watch Rail state. `buildWatchRailTile` accepts
one explicitly selected `ChannelManifest`, re-parses it, requires
`surfaces.watch`, and rejects the adult ring before producing a
`v10.watch-rail.1` payload. `WatchCompanionBridge.pushRailTile` atomically
replaces or clears that one selection over the existing versioned companion
transport.

Neither native companion accepts a manifest or invents channel state. Both cache
only the last validated `rail_tile`, so the chosen channel remains glanceable
while the phone is unreachable.

## Content and behavior

- Rich tiles render the canonical header, state line, and optional glance
  metric.
- Cold/text-only tiles render `faces.spectator.textOnlyDegradation`
  byte-for-byte; the TS, Swift, and Kotlin codecs reject a text-only payload
  whose state line differs from that field.
- The Wear OS provider is the single Rail tile and the first screen in each
  native app is the same restrained, single-channel presence. Existing Today,
  Breath, Streak, and Settings screens remain.
- A live-moment alert can enter the wire shape only when a real decision is
  granted at effective loudness 3 and names a live moment declared by the chosen
  manifest.
- Native clients deduplicate alert ids and emit one gentle click/28 ms
  low-amplitude pulse. They remain silent when haptics are disabled or the
  phone-synced quiet-hours window is active.

## Structural exclusions

`WatchRailRing` is `wellness | games` in TypeScript, Swift, and Kotlin. There is
no adult enum case. The canonical Zod schema also fixes alerts to
`granted: true` and `effectiveLoudness: 3`; both native decoders repeat those
checks at the trust boundary.

## Verification notes

- Contract and bridge suites cover verbatim degradation, adult rejection, real
  grant-3 projection, malformed alert rejection, one-tile replacement/clear, and
  sync replay.
- Swift and Kotlin parity suites cover codec round trips, non-grant rejection,
  haptic deduplication, and quiet-hours silence.
- On the July 22 Linux host, the TypeScript contract/mobile checks run normally.
  Native suite setup remains host-constrained: Swift is not installed, and
  Gradle cannot install Android 36.1 until the Android SDK license is accepted.
  These are environment limitations, not suppressed test failures.
- The full contracts suite also reports its existing common-manifest drift for
  `portfolio-release-gates.ts`; the focused V10 watch contract suite passes
  independently.
