<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-node/src/meshbay_node/indexer, branch 0.10</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.10</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.10'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-08-30T15:05:15Z</updated>
<entry>
<title>chore: scrub copyrighted names from tests, comments and docs</title>
<updated>2026-08-30T15:05:15Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-30T15:05:15Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=d5fc45ff907e618d884a8d2d91c1f2b45e6898d1'/>
<id>urn:sha1:d5fc45ff907e618d884a8d2d91c1f2b45e6898d1</id>
<content type='text'>
Real franchise / show / release-group names had crept back into test
fixtures, code comments, a docstring and docs/mediacenter.md while fixing
the saga-match and misclassification bugs. Replace them all with invented
placeholders ("Some Saga", "A Different Show") and shape descriptions
("a franchise-origin film", "a 3-season show"). Behaviour and assertions
unchanged; 738 node tests still pass.

Record the rule in CLAUDE.md so it stops recurring.

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_018BMLQjqFGCize2KtNBT79v
</content>
</entry>
<entry>
<title>fix(node): stop a numbered saga all matching its first film</title>
<updated>2026-08-30T14:31:34Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-30T14:31:34Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=854b76338072979526ce36fbc176c82f6fc5d0bd'/>
<id>urn:sha1:854b76338072979526ce36fbc176c82f6fc5d0bd</id>
<content type='text'>
Every "&lt;Saga&gt; Episode &lt;N&gt; - &lt;subtitle&gt;" file in a numbered franchise
resolved to the series' first entry (a real, older film). `sequel_variants`
stripped "Episode &lt;N&gt;" and offered the bare "&lt;Saga&gt;" as a candidate query;
that matches the first film's original_title at ratio 1.0 and beat PASS 1's
correct-but-lower hit. A franchise's bare name is very often a real,
different film.

When a Part/Episode/Chapitre/… keyword carried the index, sequel_variants
no longer emits the bare base — only "&lt;base&gt; &lt;digit&gt;" and "&lt;base&gt; &lt;roman&gt;".
Without a keyword ("&lt;Franchise&gt; 3") the bare base is still offered, so that
fix is untouched. Verified live against TMDB: the franchise's episodes each
resolve to their own entry; the earlier numbered-sequel, two-part-film and
franchise-subtitle regressions all hold.

docs/mediacenter.md §10.3.

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_018BMLQjqFGCize2KtNBT79v
</content>
</entry>
<entry>
<title>fix(node): stop a movie with a mangled quality tag being shelved as a series</title>
<updated>2026-08-29T16:45:37Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-29T16:45:37Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=00880fd8b9d362ad391c784f1ee31bd62aa18d62'/>
<id>urn:sha1:00880fd8b9d362ad391c784f1ee31bd62aa18d62</id>
<content type='text'>
Found on demo35: "Some.Film.2017.MULTI.108.grp.mkv" — the release name's
"1080p" truncated to "108" — makes guessit read S01E08, so enrich.py's
flat-library branch (elif ep.episode is not None) filed a standalone film
as a series. "Fix match" then only offered TV results for the phantom
show, so there was no way out from the UI.

- title_parse.has_episode_marker(): true only for an explicit SxxExx /
  1x08 / "Episode N" / "Season N" token, not a bare 3-4 digit run.
- enrich.py: the flat-library branch now needs ep.season AND ep.episode,
  plus either a real marker or the absence of a "(2019)"-style year.
  Every genuine flat-dumped episode in the corpus carries a marker, so
  real shows are untouched; the same misparse on "1280" ("...2013.1280...")
  is covered too.

docs/mediacenter.md §10.2. Known gap left open: no operator control over
the movie/show kind itself — a "this is a movie / a show" toggle would.

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_018BMLQjqFGCize2KtNBT79v
</content>
</entry>
<entry>
<title>feat(node): V8–V11 — show-branch ladder, year-aware _best_match, wider sequel_variants</title>
<updated>2026-08-29T13:43:38Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-29T13:43:38Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=5d28d0c96cc8489645178b483835489779cb3887'/>
<id>urn:sha1:5d28d0c96cc8489645178b483835489779cb3887</id>
<content type='text'>
V8: the TV/show branch of _tmdb_search used the old "first candidate over
0.6 wins" shape. It now shares one _tmdb_ladder helper with the movie
branch — score every candidate query, keep the best, fast-path a
confident primary hit. A year lifted off the show's folder name
(title_parse.year_in, e.g. "Some.Show.2022.S01") rescues a sub-0.6 hit
that lands on the exact year. title_parse.clean_query de-dots a
folder-derived title without naive_title's extension-stripping trap.

V9: _best_match gains an optional `year`. When the top result is not a
confident textual hit (ratio &lt; 0.6) and a year was requested, a
different result of that exact release year is preferred — TMDB already
year-filtered the search, so this is a hard corroboration, not the fuzzy
re-rank §3.3 warns against. A confident top hit is never overridden.
search_movie/search_tv forward the year.

V10: sequel_variants widened — trailing Roman→digit as well as
digit→Roman, spelled-out indices (one..twelve / un..douze / ordinals),
and a "Part N" / "Chapitre N" wrapper. Still empty for a trailing word
that is not an index or a 4-digit year.

V11: when the primary hit is already decent (&gt;= 0.6) and there is nothing
more specific to try (no alternative_title, no sequel variant — only a
punctuation restatement left), the ladder returns without the extra
requests. The clean-title common case is back to one call.

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_018BMLQjqFGCize2KtNBT79v
</content>
</entry>
<entry>
<title>fix(node): correct TMDB movie matching, per-file overrides, rematch</title>
<updated>2026-08-29T12:58:58Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-29T12:58:30Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=71b7a310ce938f072fe20f27eeeadd40685f1ad1'/>
<id>urn:sha1:71b7a310ce938f072fe20f27eeeadd40685f1ad1</id>
<content type='text'>
A batch of wrong poster-grid matches found live on a real library
(2026-08-29): a two-volume film's second part matched the first; a
numbered sequel matched a same-year making-of documentary; several
entries of one franchise matched a single early entry whose localized
TMDB title is the franchise name; one matched nothing. One mechanism:
_tmdb_search returned the first candidate query whose title-similarity
ratio merely cleared 0.6, before alternative_title / the Roman-numeral
variant was ever tried.

Matching:
- title_parse: fold guessit's volume/part number back into display_title
  so the parts of a multi-part film stay distinct in the query, the card
  and the override.
- _tmdb_search: keep a strong PASS 1 fast path (ratio &gt;= 0.85, one
  request), otherwise score every candidate query and pick the best. A
  year-exact rescue lifts a sub-0.6 top hit to the confidence floor only
  when TMDB's own year-filtered result lands exactly on the filename's
  year. No local re-ranking of any single result list; no tmdb.py change.

Fix match / rematch:
- _admin_exec_tmdb_override: a movie override touches its own file only
  (guessit gives a whole franchise one display_title); a show override
  still fans out. Corrected files are marked in media_cache.tmdb_override.
- media_cache: tmdb_override table; clear_file_tmdb / clear_tmdb_matches
  drop auto-resolved matches while sparing manual corrections.
- ops.rematch_video + `meshbay-node video rematch` (loopback endpoint +
  CLI verb): re-resolve a group's video matches after a matcher fix.
  file_tmdb is keyed by content hash and otherwise only pruned on
  deletion, so nothing dislodged a cached match before.
- a rename now drops the stale auto match too (daemon
  _reenrich_renamed_video_entries).

UI:
- VideoDetailModal shows the source filename and resolved TMDB id; an
  unmatched poster gets a badge (3 new video.* i18n keys x 10 locales).
  So a wrong match can actually be identified before hitting Fix match.

docs/mediacenter.md 10.1 records this and the V8-V13 follow-up backlog
(show-branch ladder, year-aware _best_match, wider sequel_variants, the
0.6-0.85 extra calls, movie grid merge, per-card rematch).

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_018BMLQjqFGCize2KtNBT79v
</content>
</entry>
<entry>
<title>fix(music): stop sharing one folder's cover across unrelated tracks, and merge various-artists compilations into one album</title>
<updated>2026-08-26T16:09:44Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-26T16:09:44Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=6fb948045b9c563ce591da289cdac1df6bed360c'/>
<id>urn:sha1:6fb948045b9c563ce591da289cdac1df6bed360c</id>
<content type='text'>
Two real, confirmed bugs in a large flat music library:

- enrich_audio.py's sibling-cover fallback assumed one folder is one
  release. A large flat "chart ranking" folder mixing dozens of unrelated
  artists carried several distinct WMP AlbumArt-cache guids (one per
  original album a track was ripped from), and the fallback picked
  whichever one WMP had copied to Folder.jpg — attaching one unrelated
  release's cover to every other track in the folder. Now refuses to pick
  a cover at all once 2+ distinct guids show up, rather than guess.

- music-app.js's groupMusicEntries grouped by artist first, album second,
  so a various-artists compilation (many genuinely different per-track
  artists, one shared album tag, no album-artist tag at all — a real
  ~20-track soundtrack rip has exactly this shape) could never be
  recognized as one release: every track landed alone in its own artist's
  bucket and got folded into a singleton pile. Now detects an album key
  shared across 2+ distinct artist keys and merges those tracks into one
  compilation card under a "Various" heading instead.

Both verified against real, previously-affected files and live in the
browser: the shared wrong cover is gone, and the compilation renders as
one card with all its tracks in order.
</content>
</entry>
<entry>
<title>fix(video): recognize "S1"/"S2"-style season folders, not just full words</title>
<updated>2026-08-26T14:24:18Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-26T14:24:18Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=bc94dc672d142e989fa4f483f643d4b43f66b02f'/>
<id>urn:sha1:bc94dc672d142e989fa4f483f643d4b43f66b02f</id>
<content type='text'>
Found live: a real show organized its first season as "House.of.the.Dragon.
S01E01...mkv" inside a folder named "S1" (the show name embedded in every
filename, so grouping worked by guessit's own title alone), but its later
seasons as "S02E01. Episode's Own Title.mkv" inside "S2"/"S3" — no show
name in any filename at all, relying entirely on the folder. Those seasons
showed up as loose individual entries instead of grouped under the show:
season_from_folder_name only recognized "season"/"saison"/"livre" as full
words, so "S2" didn't register as a season folder at all, and the
ancestor-based show-grouping fix (previous commits) never triggered for
those seasons.

A bare "S" + 1-2 digits as the *whole* folder name is now recognized too —
anchored to the entire name so it can't match some unrelated folder that
merely starts with "s" followed by digits.
</content>
</entry>
<entry>
<title>fix(video): fix two remaining bugs in Specials numbering and long-season episodes</title>
<updated>2026-08-26T14:04:00Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-26T14:04:00Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=c81eaa0bd07e360ec03406dfc63267c3013a0319'/>
<id>urn:sha1:c81eaa0bd07e360ec03406dfc63267c3013a0319</id>
<content type='text'>
1. A season spanning more than one folder (a per-book Bonus folder nested
   inside every numbered season) got the same synthetic episode numbers
   handed out again in each folder independently — three unrelated
   Specials all showing up as "S0E01". _synthetic_episode_number now ranks
   across the whole show for the target season, not just one file's own
   folder.

2. guessit reads a bare 3-digit leading episode number as a concatenated
   season+episode guess rather than a plain episode number — "100" parses
   as season=1, episode=0, not episode=100, with nothing in its output
   distinguishing that from a real 2-digit episode. A season-like ancestor
   already overrides guessit's season (previous commit); this applies the
   same fix to episode via a direct regex on the leading number, capped at
   3 digits so a leading year (4 digits) is never misread the same way.

Both confirmed against the real library this whole fix was found on:
per-book Bonus features across two books no longer collide, and a real
100th-episode file now resolves to episode 100 instead of 0.
</content>
</entry>
<entry>
<title>fix(video): group every episode under the show's own folder, not a per-file guessit title</title>
<updated>2026-08-26T13:51:10Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-26T13:51:10Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=b1543faad87fd865f8746711ab5f10ac4f331e8b'/>
<id>urn:sha1:b1543faad87fd865f8746711ab5f10ac4f331e8b</id>
<content type='text'>
The mechanism itself was wrong, not just the TMDB matching: a bare episode
numbering convention with no show name in the filename at all
(`001    Episode's Own Title.ext`, no SxxExx, no show prefix — entirely
ordinary on its own) makes guessit invent a "title" from whatever text
follows the number. That text is the individual episode's own name, and
differs for every episode in the folder — trusting it, as the code did,
groups nothing together at all: every episode became its own single-
episode "show", searched against TMDB by that one-off title alone.

Whenever a season-like ancestor folder exists (a numbered season, or
Specials/Bonus/Extras -&gt; season 0), its own root folder now names the show
unconditionally — never a per-file guessit title, which cannot tell a
show's real name from an individual episode's one-off name when the
filename carries no reliable ShowName/SxxExx structure. The walk continues
past *every* consecutive season-like ancestor, not just the first: a
per-season Bonus folder (Show/Season N/Bonus/file.ext) is nested two
levels inside the show, both "Bonus" and "Season N" season-like on their
own, and stopping at the first would hand back "Season N" as the show's
name instead of "Show".

Also adds "livre" ("book") to the season-word vocabulary (§3.4) — some
shows number their seasons that way (Roman numerals) rather than
"season"/"saison".

Supersedes _title_from_show_siblings from the previous commit (removed):
that fallback assumed a per-file title could still be trusted often
enough to be worth borrowing from a sibling season folder — this fix
means it never needs trusting in the first place once a season-like
ancestor exists.

Verified directly against the real library this was found on, not just
synthetic tests: every sample file (a numbered episode, a Book/Bonus
feature, a Book-root "making of") now resolves to the show's real name.
</content>
</entry>
<entry>
<title>fix(video): a Specials/Bonus folder's episodes were matched to TMDB as unrelated standalone movies</title>
<updated>2026-08-26T13:29:05Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-26T13:22:17Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=4c45792c861c47d44ebdbbab4130e37fba5d6795'/>
<id>urn:sha1:4c45792c861c47d44ebdbbab4130e37fba5d6795</id>
<content type='text'>
Found live: a "Specials" folder full of one-off-named bonus episodes had
every file appear as its own poster, matched against TMDB by its own
title, because guessit finds no season/episode grammar at all in a
filename with no SxxExx of its own — so the classification (episode vs
standalone movie), based solely on that, fell to the movie branch. Real,
unrelated films happened to share several of those one-off titles and
matched confidently, one per Special, cluttering the Videos view with
dozens of wrong posters instead of grouping under the show.

An ancestor folder saying this is part of a show — a numbered season, or
Specials/Bonus/Extras -&gt; season 0 — is now trusted over the filename
having no SxxExx of its own. The show's name can't come from this file's
own guessit title (that's the bug) or from siblings in the same Specials
folder (every one of them has the same gap) — it's borrowed from the
show's ordinary season folders next door, which do carry it in the usual
ShowName.SxxExx shape (_title_from_show_siblings). A synthetic, stable
episode number (alphabetical rank among the folder's video files) stands
in for the real one nothing in a Specials folder provides.

Generic, not specific to a folder literally named "Specials": the same
fallback fires for any season-like ancestor folder whose files lack
per-file episode grammar, numbered seasons included (covered by a
dedicated test).

Also hardens _title_from_siblings to require the sibling's own episode
number too, not just a title — otherwise it would borrow one Special's
one-off title as if it were representative, on a folder like this one.

Existing already-indexed entries will need a rescan (restart the node) to
be re-enriched under this logic — nothing re-derives them on its own.
</content>
</entry>
</feed>
