<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-node/tests/test_rename_reenrichment.py, branch 0.13</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.13</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.13'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-09-06T16:16:57Z</updated>
<entry>
<title>feat(node): Phase 2 server side — one directory setting for every app</title>
<updated>2026-09-06T16:16:57Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-06T16:16:57Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=85a2ec47b7ad334208a3dbb091fadccc7631785c'/>
<id>urn:sha1:85a2ec47b7ad334208a3dbb091fadccc7631785c</id>
<content type='text'>
`video_root` (a string), `audio_root` (a string) and `photo_roots` (a list)
said the same thing three ways: three roster accessors, three ops, three MNP
messages, three admin-op subjects. They become `set_app_directories(app_key,
paths)` and its single-directory wrapper, stored under `&lt;app&gt;_directories` and
keyed by the app's registry name — so an application can be added without
touching this layer, which is the whole claim of the plugin architecture.

The three old names still work. Their MNP messages are handled, and the roster
falls back to the old key when the new one is unset, so a node upgraded into
this keeps working with no migration step — the plan called for a script, and
a script nobody runs on the machine where it matters is worse than a fallback.

Two things are new rather than moved:

The paths are validated. The setters this replaces accepted anything, so a
typo — or a path left behind when a root was removed — was stored happily and
then matched no entry, leaving an app showing an empty tab with nothing to
distinguish "misconfigured" from "no files yet". Deliberately not
`RootSet.resolve()`: that also refuses a currently-unavailable root, and an
operator must be able to point an app at a library on a drive they ejected.

The legacy scalar is derived, never stored. `video_root` still rides on the
handshake ack for MNP 1.0 clients; kept as a second stored value it would
drift from the list within one run, which reads as "it works after a restart".

Also here: chat's own two settings (a directory, which must be on a read-write
root because it is a destination rather than a view, and a link-preview switch
gating the unfurl path — checked before the cache, or turning it off would
still serve every preview already fetched), the `app_directories`,
`chat_directory` and `chat_link_preview` MNP messages, the plural
`&lt;app&gt;_directories` on the handshake ack, and `music` as the app's one
identifier where storage said `audio` and the registry said `music`.

The Music enricher now resolves a boundary per configured directory rather
than one for the group: with several, a single boundary is wrong for all but
one of them, and for Music that is the difference between reading a folder as
an artist and reading it as a release.

Suite: 11 failures, all pre-existing.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_011pvMdvLBG92jyhvD5pD6us
</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>feat(node,hub): season-specific overviews, manual TMDB match correction, and wizard polish</title>
<updated>2026-08-24T12:33:20Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-24T12:33:20Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=0b0da86f1f9d6f0b1a27b5e1e1658c42de9f356a'/>
<id>urn:sha1:0b0da86f1f9d6f0b1a27b5e1e1658c42de9f356a</id>
<content type='text'>
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 -&gt; 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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01LAmyXtc6dAADsH23ydXQpY
</content>
</entry>
</feed>
