# ADAPTER.md # tvctl Adapter Contract The adapter layer isolates platform-specific TV control protocols from the rest of `tvctl`. Everything above this layer speaks the normalized tvctl data model; everything below it speaks the platform's native protocol. ## Required Trait The canonical trait lives in `src/adapters/mod.rs`: ```rust pub trait TvAdapter: Send + Sync { async fn discover(&self) -> Result>; async fn state(&self, device: &Device) -> Result; async fn launch(&self, device: &Device, app: &str) -> Result<()>; async fn stop_app(&self, device: &Device) -> Result<()>; async fn key(&self, device: &Device, key: TvKey) -> Result<()>; async fn sequence(&self, device: &Device, keys: Vec) -> Result<()>; async fn list_apps(&self, device: &Device) -> Result>; async fn dev_install(&self, device: &Device, zip: &[u8]) -> Result<()>; async fn dev_reload(&self, device: &Device) -> Result<()>; async fn dev_logs(&self, device: &Device) -> Result>; } ``` ## Rules - The adapter surface is the boundary between normalized and platform data. - Adapters translate normalized `TvKey` values into platform-specific input. - Platform support belongs in a dedicated subdirectory under `src/adapters/`. - Dev-mode methods may return `NotSupported` when a platform lacks that feature. - The CLI, daemon, and HTTP API must not contain platform-specific logic.