Build FLX as a fast, observable, testable personal media platform with a rock-solid foundation. Optimize for correctness, low latency, excellent television UX, predictable failure behavior, and future replaceability of implementation details.
- Read README.md, architecture.md, and relevant ADRs.
- Inspect the current implementation and tests before proposing changes.
- When working on a running Phoenix application, use Tidewave runtime inspection before guessing from static code alone. Tidewave is dev-only.
- Identify which architectural seam owns the change. Do not bypass a behaviour because the concrete implementation is convenient.
- For performance claims, establish or update a benchmark.
- For runtime/hardware claims, define an executable oracle.
Do not couple domain code directly to concrete implementations that are intended to remain replaceable. Preserve these boundaries:
- Media.OSProcess
- Media.Hardware.Provider
- Media.Transcode.Executor
- Media.Scanner
- Media.Search
- Media.Fingerprint
- Media.Watcher
Playback planning must remain pure domain logic and must not perform I/O.
- Prefer OTP supervision and explicit process ownership over ad-hoc background tasks.
- Use DynamicSupervisor/Registry/GenServer/Task.Supervisor for live runtime work where appropriate.
- Durable restart-safe background work belongs in Oban, not in a live playback process.
- Avoid large media binaries flowing through BEAM mailboxes. Let the kernel, filesystem, HTTP server, FFmpeg, and native playback stacks move media bytes.
- Make cancellation and ownership explicit. A dead playback session must not leave FFmpeg or descendants running.
- Keep Tidewave and similar development-only tooling out of production releases.
- FFmpeg and ffprobe are external executables for the MVP.
- Construct argv as structured arguments, never as shell-concatenated strings.
- Parse progress and diagnostics separately from media output.
- Successful process exit is not sufficient evidence of correctness. Validate output with ffprobe and domain-specific oracles.
- Hardware acceleration may only be marked healthy after a real probe verifies the expected device path.
Intel Quick Sync and NVIDIA acceleration are MVP requirements.
- Model accelerators by capabilities, not by brand-specific branching in unrelated modules.
- QSV, NVIDIA, and software are providers under the same contract.
- Discovery must distinguish compiled support from usable support.
- Preserve device identity and driver/runtime versions in diagnostic evidence.
- Software fallback must remain functional and visible. Silent hardware fallback is a bug.
Rust is an acceleration option, not the default owner of the system.
- Heavy scanning/search/fingerprinting/watching work should enter through the documented behaviours.
- Prefer an external Rust Port executable for heavyweight long-running work so BEAM failure isolation remains intact.
- Use Rustler only for small bounded hot functions where in-process execution is justified by measurements.
- Do not introduce Rust because a workload sounds low-level. Introduce it after evidence shows the Elixir implementation is the limiting factor or a Rust-native library materially changes the tradeoff.
Verification is part of implementation, not cleanup.
Expected techniques include:
- unit and integration tests
- property tests
- PropCheck StateM models for runtime protocols
- invariant checks
- dependency/boundary assertions
- failure injection
- process/resource leak oracles
- real QSV/NVIDIA certification tests
- benchmark baselines
Any change to playback planning, hardware selection, process ownership, search semantics, or reconciliation behavior should come with a model, invariant, contract test, or benchmark appropriate to the risk.
- Use Logger as the canonical logging API.
- Use structured Logger metadata with stable semantic keys.
- Use Telemetry as the canonical event source for measurements.
- Use OpenTelemetry primarily for tracing unless the Erlang SDK status changes enough to justify a broader role.
- Do not create high-cardinality metric labels from media titles, file paths, session IDs, or user identifiers.
- Correlate logs, traces, and diagnostic evidence with stable IDs.
- New long-running or performance-sensitive paths should expose timing and resource measurements from the start.
- Source media is immutable.
- Media identity is not a path.
- Raw ffprobe output should be retained so normalized metadata can be reinterpreted later.
- Search indexes, thumbnails, transcode caches, embeddings, and other projections must be rebuildable.
- Schema changes must preserve the distinction between canonical state and derived state.
Share product code aggressively, but never force platform parity through a lowest-common-denominator player or focus model. Narrow platform adapters are expected for playback, focus/navigation, virtualization, and other areas where native behavior materially improves the experience.
The required MVP targets are Google TV, tvOS, and Web. Android and iOS should remain natural follow-on targets rather than rewrites.
- Prefer small, reviewable slices.
- Keep docs and ADRs synchronized with expensive architectural changes.
- Do not silently replace an established seam. If a seam is wrong, update the ADR and contract intentionally.
- Preserve benchmark and verification evidence when making performance claims.
- Fix root causes rather than layering retries around unknown failure modes.