# torttube milestones ## M0 — Scaffold [current] - [x] `Sulkta-Coop/torttube` on LAN Gitea - [x] Layout: `addon/` (Python) + `sidecar/` (Rust workspace) - [x] GPL-3.0 license headers - [ ] crafting-table build target produces a static aarch64 sidecar binary ## M1 — sidecar resolve - [ ] reads `{"op":"resolve","id":""}` from stdin - [ ] calls rustypipe → returns `{"streams":[…],"title":"…","duration_s":N}` - [ ] handles age-restricted + region-restricted as typed errors, not panics - [ ] sig decoding verified against a known-good video - [ ] DASH manifest URL or per-itag direct stream URL — whichever inputstream.adaptive prefers ## M2 — SponsorBlock - [ ] `{"op":"sponsorblock","id":""}` → segments array - [ ] SHA-256 prefix lookup (privacy-preserving — only send first 4 hex chars) - [ ] category filter honoured from addon settings (skip / mute / show only) - [ ] cache per-session ## M3 — Kodi addon plays one video - [ ] `addon.xml` + `main.py` register as video plugin - [ ] hardcoded list of 3 test videos - [ ] select → sidecar `resolve` → stream URL → Kodi player - [ ] verified end-to-end on LibreELEC RPi at `192.168.0.158` ## M4 — search + channel browse - [ ] search box → sidecar `{"op":"search","q":"…"}` → results - [ ] channel browse → `{"op":"channel","id":"…"}` - [ ] playlist browse → `{"op":"playlist","id":"…"}` - [ ] result thumbnails + duration + uploader ## M5 — SponsorBlock skipping - [ ] background thread on `Player()` polls position - [ ] when position enters a skip segment → `xbmc.Player().seekTime(end)` - [ ] toast on skip + skip-counter in settings - [ ] category toggles in `settings.xml` ## M6 — install + cross-compile - [ ] crafting-table builds `torttube-sidecar.aarch64` + `.armv7` - [ ] `addon.zip` ships with platform detect via `xbmc.getCondVisibility('system.platform.linux.raspberrypi')` - [ ] one-shot install path documented for LibreELEC `/storage/.kodi/` ## Upstream PR targets (parallel, opportunistic) Pick one as we hit it organically — don't gate milestones on these. - NPE #1357 (JDoc) — smallest, just to land a credible PR - NPE #1444 (typed errors) — clean signal/contract change - rustypipe — file issues + PRs on codeberg as we hit gaps