# ROADMAP.md # tvctl — Feature Roadmap and Milestone Tracker # Agents: update this file as work is completed. See AGENT.md for instructions. # Last updated: 2026-04-14 --- ## Current Focus **Milestone 5 — HTTP API** CLI coverage is complete. Begin exposing the same surface over loopback HTTP. --- ## In Progress - Milestone 5 has not started yet; CLI validation and polish are complete enough to move on --- ## Milestone 1 — Project Foundation _Goal: A compiling Rust project with correct structure and no logic yet._ _Completed 2026-04-14. See Completed below._ --- ## Milestone 2 — Roku Adapter _Goal: Can communicate with a real Roku TV over ECP._ - [x] 2026-04-14 — Implement core Roku ECP adapter in `src/adapters/roku/` - [x] 2026-04-14 — `discover()` — SSDP scan returning Roku devices - [x] 2026-04-14 — `list_apps()` — fetch installed channel list via ECP - [x] 2026-04-14 — `launch()` — launch app by ECP channel ID - [x] 2026-04-14 — `stop_app()` — exit current app - [x] 2026-04-14 — `key()` — send ECP keypress - [x] 2026-04-14 — `sequence()` — send multiple keypresses - [x] 2026-04-14 — `state()` — query power state and active app - [x] 2026-04-14 — `dev_install()` — zip upload via ECP developer web installer with Digest auth - [x] 2026-04-14 — `dev_reload()` — reload the sideloaded app via `launch/dev` - [x] 2026-04-14 — `dev_logs()` — fetch BrightScript debugger output from the live dev socket - [x] 2026-04-14 — Key translation table (TvKey → Roku ECP key string) - [x] 2026-04-14 — Automated live validation against `58" Hisense Roku TV` at `10.10.0.136` --- ## Milestone 3 — Daemon Core _Goal: tvctld runs, manages devices, and handles the Unix socket._ - [x] 2026-04-14 — Daemon entry point and lifecycle (`src/daemon/mod.rs`) - [x] 2026-04-14 — Unix socket listener - [x] 2026-04-14 — Device registry (`src/daemon/registry.rs`) - [x] Load from `devices.json` on start - [x] Persist on change - [x] CRUD operations - [x] 2026-04-14 — Discovery service (`src/daemon/discovery.rs`) - [x] SSDP scan - [x] Auto-discover on startup (if configured) - [x] Interval-based re-scan - [x] Manual add by IP - [x] 2026-04-14 — App cache manager (`src/daemon/cache.rs`) - [x] Per-platform JSON files - [x] Organic growth strategy - [x] `app refresh` invalidation - [x] 2026-04-14 — State cache (`src/daemon/state.rs`) - In-memory only - Per-device last-known state - Timestamp on every entry - [x] 2026-04-14 — Adapter registry (map platform string → adapter instance) - [x] 2026-04-14 — Config loading from TOML --- ## Milestone 4 — CLI _Goal: All tvctl commands work against a running daemon._ - [x] 2026-04-14 — CLI entry point and dispatch (`src/cli/mod.rs`) - [x] 2026-04-14 — Unix socket client (send commands, receive responses) - [x] 2026-04-14 `tvctl daemon` commands - [x] `start` `stop` `restart` `status` - [x] `install` (generate systemd user unit) - [x] `uninstall` - [x] 2026-04-14 `tvctl device` commands - [x] `list` `discover` `add` `select` `info` `remove` - [ ] `tvctl app` commands - [x] 2026-04-14 `list` `launch` `stop` `refresh` - [ ] `tvctl remote` commands - [x] 2026-04-14 `key` `sequence` - [x] 2026-04-14 `tvctl state` - [x] 2026-04-14 `tvctl dev` commands - [x] `install` `reload` `logs` - [x] 2026-04-14 `tvctl config` commands - [x] `list` `get` `set` `reset` `reload` - [x] 2026-04-14 Global flags: `--device` `--json` `--help` `--version` - [x] 2026-04-14 Full help text on every command (see AGENT.md definition of done) - [x] 2026-04-14 Full help output on bare `tvctl` - [x] 2026-04-14 Friendly error messages with hints on every failure path - [x] 2026-04-14 `--json` output verified on every command --- ## Milestone 5 — HTTP API _Goal: Full /v1/ API running on 127.0.0.1:7272._ - [ ] axum server setup in `src/api/mod.rs` - [ ] All routes implemented (see PROJECT_MAP.md API surface) - [ ] Standard response envelope on all routes - [ ] Error responses with `code` + `message` + `hint` - [ ] Device addressable by UUID or friendly name on all routes - [ ] `PATCH /v1/config` with partial update support - [ ] `POST /v1/config/reload` triggers live config reload in daemon - [ ] Integration test: curl all endpoints against running daemon --- ## Milestone 6 — Polish and Release Prep _Goal: Ready for real use._ - [ ] Shell completions (bash, zsh, fish) via clap - [ ] `tvctl daemon install` generates correct systemd unit file - [ ] First-run experience: helpful output when no devices discovered yet - [ ] Daemon startup message with socket path and HTTP port - [ ] Log output via `tracing` (respects `log_level` config) - [ ] README accuracy pass (verify all examples work) - [ ] `cargo clippy` clean - [ ] `cargo test` passing - [ ] Cross-compile test (x86_64 + aarch64) - [ ] GitHub Actions CI (build + clippy + test) - [ ] First binary release --- ## Post-MVP (Do Not Implement in v1) These are captured here so they are not forgotten, but they are explicitly out of scope until Milestone 6 is complete and stable. - [ ] Google TV / Android TV adapter (ADB) - [ ] Fire TV adapter (ADB variant) - [ ] WebSocket live state updates - [ ] Event watching / triggers - [ ] Device groups (send command to multiple TVs) - [ ] Automation rules engine - [ ] Home Assistant integration - [ ] Web UI (consumes HTTP API, no business logic) - [ ] `tvctl dev logs` streaming (currently returns last N lines only) - [ ] macOS support (launchd instead of systemd) --- ## Completed - [x] 2026-04-14 — Initialize Cargo workspace (`cargo init`) - [x] 2026-04-14 — Add baseline dependencies to `Cargo.toml` - [x] 2026-04-14 — Create module skeleton and placeholder docs layout - [x] 2026-04-14 — Define the adapter contract and core shared data types - [x] 2026-04-14 — Compile the project cleanly with `cargo build` - [x] 2026-04-14 — Add Roku ECP discovery, input, app, and state adapter support with unit tests - [x] 2026-04-14 — Add env-gated live Roku integration tests and validate against the Hisense TV on the LAN - [x] 2026-04-14 — Implement Roku developer-mode install/log support and validate sideloading on the Hisense TV - [x] 2026-04-14 — Add daemon config loading, runtime paths, persisted registry/cache stores, and discovery foundations - [x] 2026-04-14 — Add daemon Unix socket IPC plus working `daemon` and `device` lifecycle/discovery commands - [x] 2026-04-14 — Finish Milestone 3 with registry CRUD, periodic discovery, manual add, and app-cache refresh plus live daemon validation - [x] 2026-04-14 — Add daemon-backed app control, remote input, state queries, and dev workflows with live Roku CLI validation - [x] 2026-04-14 — Add config list/get/set/reset/reload plus systemd user-service install/uninstall commands - [x] 2026-04-14 — Finish Milestone 4 with help, JSON-mode, config socket-reload, and secret-redaction polish --- ## Decision Log Significant decisions made during development should be logged here so future agents understand why things are the way they are. | Date | Decision | Reason | |------|----------|--------| | 2026-04-14 | Full design completed before any code written | Intentional — design-first approach | | 2026-04-14 | Samsung deprioritized | Unstable app IDs per region/model make universal support unreliable | | 2026-04-14 | No pre-populated app database | Organic cache from live TV data is more accurate and zero-maintenance | | 2026-04-14 | Unix socket for CLI, HTTP for tool builders | Clean security boundary, loopback-only by default | | 2026-04-14 | User-level systemd service | No root required, correct ownership model |