aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-24 14:33:20 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-24 14:33:20 +0200
commit0b0da86f1f9d6f0b1a27b5e1e1658c42de9f356a (patch)
treeba8daf5dcf050d44b7b0e766babbfda8fadac59f /docs
parent6af05abf410bbd038ce7fa6915a659defc509071 (diff)
downloadmeshbay-0b0da86f1f9d6f0b1a27b5e1e1658c42de9f356a.tar.gz
feat(node,hub): season-specific overviews, manual TMDB match correction, and wizard polish
Two operator-facing fixes for a real 3-season show whose automatic TMDB match was wrong at the show level: per-season overview/air_date tabs in the detail modal (falling back to the show-level text when a season's own is empty), and a "Fix match…" search-and-correct affordance that re-resolves every file sharing the corrected show's display_title. New signed op OP_TMDB_OVERRIDE and two read-only pairs (season_meta_req/resp, tmdb_search_req/resp), MNP_VERSION 0.5 -> 0.6. Also: the create-group wizard gets a spinning indexing indicator and an app-selection step, group settings default the TMDB language to the operator's own locale (never as a global default), and a file renamed mid-session now re-triggers title parsing instead of being silently skipped by the enrichment dedup guard. Fixes two bugs found during this work: the search overlay's z-index lost to the base video-overlay class and rendered invisibly, and season_meta's own empty overview didn't fall back to the show-level one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LAmyXtc6dAADsH23ydXQpY
Diffstat (limited to 'docs')
-rw-r--r--docs/apps.md19
-rw-r--r--docs/mediacenter.md80
2 files changed, 92 insertions, 7 deletions
diff --git a/docs/apps.md b/docs/apps.md
index 931114d..a032f56 100644
--- a/docs/apps.md
+++ b/docs/apps.md
@@ -5,13 +5,18 @@
> `meshbay-draft-v6.md` §2.7 for why this exists and what it changes; this
> document is the how-to.
-A group has "applications" — Chat and Files today, Videos/Music/Photos planned
-(a poster-grid browser, a music player, an album viewer). None of the
-planned ones need an MNP protocol change: video/audio/image files are already
-classified by the node's indexer (`meshbay_node/indexer/indexer.py`, `type:
-video|audio|image`) and flow through the same `index_sync`/`file_req`/
-`stream_req` messages Files and `VideoPlayer` already use. Adding one is a new
-file plus one registry entry — nothing about the group shell changes.
+A group has "applications" — Chat, Files, and Videos today (a poster-grid
+browser; see `docs/mediacenter.md`), Music/Photos planned (a music player, an
+album viewer). Video/audio/image files are already classified by the node's
+indexer (`meshbay_node/indexer/indexer.py`, `type: video|audio|image`) and
+flow through the same `index_sync`/`file_req`/`stream_req` messages Files and
+`VideoPlayer` already use — Music/Photos need no MNP change beyond that.
+Videos itself did need one: TMDB metadata (`media_meta_req`/`resp`), per-season
+overview (`season_meta_req`/`resp`), and operator match correction
+(`tmdb_search_req`/`resp`, `tmdb_override`/`_ack`) are all additive message
+pairs on top of the same index/chunk plumbing, not a replacement for it.
+Adding a new app is still a new file plus one registry entry — nothing about
+the group shell changes.
---
diff --git a/docs/mediacenter.md b/docs/mediacenter.md
index a165d64..66232f8 100644
--- a/docs/mediacenter.md
+++ b/docs/mediacenter.md
@@ -530,6 +530,85 @@ makes outbound third-party network calls (once TMDB is on) — the operator
opts a group into it explicitly via the existing Settings checklist, same
gesture as any other app.
+### 5.7 Season-specific overview, and correcting a wrong automatic match
+
+Found live, 2026-08-24, on a real 3-season show: TMDB's own search
+consistently resolved every season's folder to the same *season-3-specific*
+promotional entry — a wrong `tmdb_id`, not a MeshBay grouping bug (§3.3's
+`_best_match` deliberately trusts TMDB's own top result, per that section's
+own postmortem). Two independent problems, two independent fixes:
+
+**A show's own `overview` (§5.4) is one static field that does not
+necessarily describe every season alike.** New request/response pair, read
+lazily per selected tab (same virtualization discipline as `media_meta_req`,
+never fetched for a season the operator hasn't clicked):
+
+```
+season_meta_req { tmdb_id, season } # tmdb_id is whatever media_meta_resp
+ # already resolved — never re-searched here
+season_meta_resp { tmdb_id, season, confidence, name, overview, air_date,
+ poster_thumb_hash }
+```
+
+`video-app.js`'s `VideoDetailModal` shows a season tab bar
+(`Season 1` / `Season 2` / … / `Specials`) whenever a show has more than one
+season, defaulting to whichever season the representative episode belongs
+to. Selecting a tab both filters the episode list to that season and swaps
+in that season's own `overview`/`air_date` — falling back to the show-level
+`overview` when a season's own comes back empty (TMDB has no season-level
+text for every show), the same per-field fallback shape §5.4's English
+fallback already established, just one level further down when there is
+nothing at all to show otherwise.
+
+**An operator needs a way to correct a wrong match** when TMDB's own
+top-ranked result is simply wrong — no amount of local re-ranking fixes
+this (§3.3's last row is exactly the mistake that would repeat). Two more
+message pairs, the second an admin op:
+
+```
+tmdb_search_req { query, media_type } # media_type: "movie" | "tv"
+tmdb_search_resp { query, media_type, results: [{ tmdb_id, title, year,
+ poster_thumb_hash }] }
+
+tmdb_override { path, tmdb_id, media_type } # admin op, subject =
+ # "path={path},tmdb_id={tmdb_id},media_type={media_type}"
+tmdb_override_ack { path, tmdb_id, media_type } # broadcast to every connected peer
+```
+
+`tmdb_search_req` is deliberately **not** admin-gated — it is read-only (the
+same TMDB lookup the automatic matcher already performs on everyone's
+behalf) and returns nothing that isn't already visible in the search
+results a browser could get by hand. `media_type` is echoed back in the
+response, not only the query: a client that fires a movie search and a tv
+search for the same title in close succession needs it to tell the two
+responses apart for keyed matching (`transport.js`), the same reordering
+hazard §5.4's first postmortem already covers for `media_meta_req`.
+
+`tmdb_override`, once signed, is applied to **every index entry sharing the
+resolved file's `display_title`** (`webrtc_server.py`'s
+`_admin_exec_tmdb_override`) — the same grouping the poster grid itself uses
+(§3.4/V6) — not just the one file the operator happened to right-click,
+so the correction actually sticks for every episode of the show, and
+broadcasts a `tmdb_override_ack` to every connected peer so an already-open
+grid/modal picks up the change without a reconnect (`video-app.js`'s
+`useMediaMeta` subscribes to a module-level generation counter, bumped on a
+successful override, that forces every mounted tile/modal to refetch).
+
+New adminop: `OP_TMDB_OVERRIDE = "tmdb_override"` (`adminop.py`), following
+`OP_VIDEO_ROOT`/`OP_TMDB_CONFIG`'s exact shape — signed for the same reason:
+`media_cache` is shared node-wide, not per-viewer, so an unsigned override
+would let any member vandalize another show's metadata for everyone.
+
+**Bug found live, 2026-08-24**: the search overlay (a second, later
+`.video-overlay` sibling, opened on top of the detail modal) rendered
+completely invisibly the first time it shipped — present in the DOM
+(confirmed via the accessibility tree), inert on screen. Cause: its own
+`z-index: 1` lost to the base `.video-overlay` class's `z-index: 200` that
+the detail modal underneath it already used; both are `position: fixed`,
+so an explicit z-index always wins over DOM order regardless of which
+element mounted later. Fixed by giving `.video-search-overlay` an explicit
+`z-index: 210`.
+
---
## 6. Node-side implementation, concretely
@@ -620,6 +699,7 @@ centralization was for (one computation, reused by every member).
| V4 | Multi-audio-track / subtitle-track surfacing in the detail view | Out of scope for this pass — `video-player.js`'s existing track handling is unchanged; Videos only adds discovery and metadata |
| V5 | `Music`/`Photos` apps | Explicitly out of scope, per `apps.md` — this document only builds `video-app.js` and the shared node-side machinery (TMDB client, thumbnail cache, title parser) that a future audio/photo app could also reuse |
| ~~V6~~ | ~~Two folders of the same show, named by different release groups, can produce two separate poster-grid cards~~ | **Closed, 2026-08-24.** Rather than fuzzy title matching (real design decision, still deferred), `PosterGrid` now merges raw show-groups client-side once each group's TMDB lookup resolves to the same confident `tmdb_id` (`onMetaResolved` reports each `PosterCard`'s resolved meta upward; a `useMemo` groups by id, combining episodes/seasons into one card). This only merges what TMDB already agrees is one show — a genuinely unmatched show still gets its own card, which is correct. Confirmed live: `OVNIs.S01...`/`Ovnis-S01...` now render as a single "OVNI(s)" card with both seasons |
+| ~~V7~~ | ~~A show's automatic TMDB match can be wrong at the show level (not just mis-ranked locally), and a wrong match's `overview` can read as scoped to one season~~ | **Closed, 2026-08-24 — §5.7.** Per-season tabs (own `overview`/`air_date`, falling back to the show-level text when empty) plus an operator-only "Fix match…" search-and-correct affordance, applied to every file sharing the resolved `display_title`. Confirmed live on the operator's real "War of the Worlds" 3-season show, itself matched to a wrong season-3-specific 1988 promotional TMDB entry: season tabs correctly filtered episodes and swapped in each season's own air_date, and the search overlay returned real TMDB candidates for a manual correction |
## 11. Acceptance before shipping