ca9a6c509a
Add SSDP discovery plus the main ECP app, state, and key control flows so Milestone 2 has a working Roku foundation with parser and key-mapping tests.
6.1 KiB
6.1 KiB
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 2 — Roku Adapter Foundation scaffold is complete. Begin platform implementation work.
In Progress
- Roku adapter
dev_install()anddev_logs()need developer-web credential handling plus real-device validation
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.
- 2026-04-14 — Implement core Roku ECP adapter in
src/adapters/roku/ - 2026-04-14 —
discover()— SSDP scan returning Roku devices - 2026-04-14 —
list_apps()— fetch installed channel list via ECP - 2026-04-14 —
launch()— launch app by ECP channel ID - 2026-04-14 —
stop_app()— exit current app - 2026-04-14 —
key()— send ECP keypress - 2026-04-14 —
sequence()— send multiple keypresses - 2026-04-14 —
state()— query power state and active app dev_install()— zip upload via ECP dev mode- 2026-04-14 —
dev_reload()— reload the sideloaded app vialaunch/dev dev_logs()— fetch dev logs- 2026-04-14 — Key translation table (TvKey → Roku ECP key string)
- Manual integration test against real Roku device
Milestone 3 — Daemon Core
Goal: tvctld runs, manages devices, and handles the Unix socket.
- Daemon entry point and lifecycle (
src/daemon/mod.rs) - Unix socket listener
- Device registry (
src/daemon/registry.rs)- Load from
devices.jsonon start - Persist on change
- CRUD operations
- Load from
- Discovery service (
src/daemon/discovery.rs)- SSDP scan
- Auto-discover on startup (if configured)
- Interval-based re-scan
- Manual add by IP
- App cache manager (
src/daemon/cache.rs)- Per-platform JSON files
- Organic growth strategy
app refreshinvalidation
- State cache (
src/daemon/state.rs)- In-memory only
- Per-device last-known state
- Timestamp on every entry
- Adapter registry (map platform string → adapter instance)
- Config loading from TOML
Milestone 4 — CLI
Goal: All tvctl commands work against a running daemon.
- CLI entry point and dispatch (
src/cli/mod.rs) - Unix socket client (send commands, receive responses)
tvctl daemoncommandsstartstoprestartstatusinstall(generate systemd user unit)uninstall
tvctl devicecommandslistdiscoveraddselectinforemove
tvctl appcommandslistlaunchstoprefresh
tvctl remotecommandskeysequence
tvctl statetvctl devcommandsinstallreloadlogs
tvctl configcommandslistgetsetresetreload
- Global flags:
--device--json--help--version - Full help text on every command (see AGENT.md definition of done)
- Full help output on bare
tvctl - Friendly error messages with hints on every failure path
--jsonoutput 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/configwith partial update supportPOST /v1/config/reloadtriggers 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 installgenerates 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(respectslog_levelconfig) - README accuracy pass (verify all examples work)
cargo clippycleancargo testpassing- 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 logsstreaming (currently returns last N lines only)- macOS support (launchd instead of systemd)
Completed
- 2026-04-14 — Initialize Cargo workspace (
cargo init) - 2026-04-14 — Add baseline dependencies to
Cargo.toml - 2026-04-14 — Create module skeleton and placeholder docs layout
- 2026-04-14 — Define the adapter contract and core shared data types
- 2026-04-14 — Compile the project cleanly with
cargo build - 2026-04-14 — Add Roku ECP discovery, input, app, and state adapter support with unit tests
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 |