tv-anarchy/docs/roadmap.md
Natalie 913135ca8c feat(@applications/tv-anarchy): improve macOS install logic
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-09 20:50:54 -07:00

122 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Status & Roadmap
Where the project is and the de-risked path to the full vision. Architecture is in
[architecture.md](./architecture.md); the mesh design origin is
[`../.project/history/20260608_fleet-manager-mesh-design.md`](../.project/history/20260608_fleet-manager-mesh-design.md).
## Status at a glance
| Area | Status | Note |
|---|---|---|
| App — playback (VLC / mpv / QuickTime) | ✅ Shipped | `blacktv` retired → mpv; no NFS — local players play downloads, else route to black |
| App — library browser | ✅ Shipped | black index fast-path + local `MEDIA_ROOTS` walk + registry fallback (no NFS) |
| App — downloads (search + transmission) | ✅ Shipped | via `mcp` CLI; search needs FlareSolverr |
| App — metadata enrichment + artwork | ✅ Shipped | regex parse + TMDB/IMDb/keyless + ffmpeg frame-grab |
| App — all UI (Home/Player/Library/Search/Downloads/Metadata/Adult/Devices/Logs/Settings) | ✅ Shipped | wired, no TODO/FIXME/`fatalError` debt |
| App — device registry (Devices tab) | ✅ Shipped (registry only) | `DeviceConfig`: type→services presets mapping to fleet classes, per-device load badge; duty *engine* still unbuilt (see fleet below) |
| App — adult content tab | ✅ Shipped | `porn-rotation.py` ported to `PornCollectionService`; `ENABLE_ADULT` compile flag + runtime `pornFeature` setting, concealed by default |
| App — VPN subsystem | ✅ Shipped | OVPN profile/credential stores (Keychain), controller, settings UI |
| App — offline cache + Now Playing/media keys | ✅ Shipped | `OfflineCacheController`, `NowPlayingController`, bandwidth policy |
| iOS app (`TVAnarchyiOS`) | ✅ Shipped (companion) | VLCKit player, library, downloads, remote control via HTTP bridge (default `:8787`); the bridge *server* is not in this repo's `mcp/` tree |
| Distribution (release/update) | ✅ Shipped | `tools/release.sh` → Forgejo on forge.black; `tools/update.sh` installs/updates any node without a toolchain |
| `governor` (`portable-net-tv`) | ✅ Shipped (single-host) | watch tracking + prefetch buffer |
| `mcp` (`plum-control-mcp`) | ✅ Shipped | VLC / black-tv / transmission / display tools |
| `recommender` | ✅ Shipped | enrichment + local recs |
| MLX title refiner | ⚠️ Seam only | `TitleRefiner` protocol + `refiner` hook, never assigned |
| `governor` → fleet orchestrator | ❌ Designed | duty assignment / replication floor / zombie reaper not built |
| `fleet/` (registry, mesh, `peers_for`/`custodians_of`) | ❌ Designed | README + spec, zero code |
| Discord planes | ❌ Designed | control/QA/announce + availability bot |
| Multi-identity / cross-fleet | ❌ Designed | single-fleet foundation must land first |
**Verdict:** the media-client layer is complete and production-grade. The
fleet/mesh layer — the project's defining "private tracker made of your friends" —
is fully specified and entirely unbuilt.
### Repo-state note
The `PlumTV → TVAnarchy` rename and the helper subsystems (`governor/`, `mcp/`,
`recommender/`, `search/`, `fleet/`, `tools/`) were committed to `main` on
2026-06-09 as a series of atomic commits (`41afc1c``b44b5a2`). Stage 0
(hygiene) below is **done**.
## Remaining work — detail
### MLX title refiner (parallel, low-risk)
`Sources/TVAnarchyCore/Metadata/FilenameParser.swift` declares
`public protocol TitleRefiner` and `public static var refiner: (any TitleRefiner)?`,
consulted only when regex yields a <2-char title. No type conforms to it and
`refiner` is never assigned the pipeline is regex-only. Impact is low (regex
handles the vast majority of `SxxEyy` releases); this is a deliberate seam, not
debt. Closing it = an MLX-backed refiner for the messy tail.
### governor → fleet orchestrator
The spec wants the governor's bandwidth-arbitration brain extended to: run
duty-assignment on registry change, enforce the N-copy replication floor (re-pin
before the last copy vanishes), and run a zombie reaper
(`healthy | stalled | dead`; recover from mesh first, public re-search fallback).
Today the governor only does single-host watch-follow + prefetch. The
bandwidth/watch foundations are reusable; the orchestration layer is missing. This
is the actuation layer for the `fleet/` registry without it a registry is inert.
### fleet/ — the mesh subsystem
`fleet/` is README-only. Everything in
[data-model.md](./data-model.md#planned-fleetmesh-data-model) registry, duties,
peer-source policy, `peers_for`/`custodians_of` is design-only.
## Build order (de-risked; each stage independently shippable)
From the design spec. Each stage ships on its own; later stages depend on earlier.
0. ~~**Hygiene (prerequisite)**~~ done 2026-06-09: the `PlumTV → TVAnarchy`
rename and the helper subsystems are committed on `main`.
1. **Host registry + duty assignment, single fleet** (black + apricot + plum +
phone). No mesh, no Discord. Unifies what's run by hand today.
*Partially started on the app side:* the Devices tab + `DeviceConfig`
(`devices.json`) already model device **types** (cellphone/laptop/storage/
seedbox/broadcast fleet classes consumer/roamer/server/seedbox/broadcast)
with overridable per-device **services** presets. What remains is the
governor-side duty *assignment engine* over that registry.
*(Run the governor-generalization track alongside stages 13.)*
2. **Seedbox source + `public_swarm_face` duty.** Adds an always-on custodian;
proves the source model on the zero-risk source first. ("Add a seedbox" is the
single most important onboarding step for non-power-users most multi-device
fleets have zero always-on nodes otherwise.)
3. **`peers_for()` over local sources** (fleet + seedbox + DHT/public). The
user-owned meta-tracker, still single-fleet.
4. **Friend-mesh source + F2F relay.** Federates; the custody floor goes
cross-fleet. Multi-identity lands here.
5. **Private-tracker source, default-closed.** LAST and highest-consequence:
`swarm_isolation` forced to `f2f_only`, un-overridable; `content` share is an
account-killer for the source user. Ship only once F2F isolation is
battle-tested on safe sources.
**Parallel, any time:** MLX `TitleRefiner` (independent, low-risk).
**After a working mesh:** the Discord planes control/ops + QA/community +
release announcements (project home server) and content/availability (private mesh
+ a bot inside users' *own* servers, never the public home server). Discord is a
surface you notify, not a backbone you route through: custody/reaper/F2F run over
WireGuard regardless, and a Discord ban must not take the mesh down.
## Non-goals / explicitly deferred (not defects)
- **`BlackTVTarget` removed.** Intentional auto-migrated at runtime to `MpvTarget`
with `CommandsConfig.blackTVDefaults(bin:)`. Black-TV control still works.
- **No ratio enforcement.** Resolved decision (2026-06-08): ship gift-economy,
build the `custody_capacity` knob, leave it off. First lever is visibility, not
enforcement; hard ratio is a per-group last resort. Ratio anxiety is the pain
being sold against "minus the ratio police."
- **No fingerprint-stripping on private shares.** Resolved decision: **warn hard,
strip never** by default. Stripping re-encodes and destroys the quality that
makes a private release valuable; the friend is protected structurally by
`f2f_only`, the source by the explicit warning. Strip is a per-release opt-in
only, never auto.
- **App doesn't link `governor` or call the MCP server directly.** By design it
shells out to the `mcp` CLI and `recommender` as subprocesses; `governor` runs
independently under launchd.
- **Black-TV watch state not on plum.** Intentional black-local, read over SSH,
never written across NFS.
- **Watch parties** (if built) = synchronized *local* playback; Discord carries
only voice + timestamps, never streamed copyrighted video.