Commit graph

567 commits

Author SHA1 Message Date
8fb16b3220 feat(library): local canonical conversion for id-less notes 2026-08-05 20:55:42 +08:00
75db364a1d fix(library): exclude no_resolve notes from sync no-id count 2026-08-05 20:35:36 +08:00
eb6b3d25d0 fix(library): globalThis setTimeout in modal (test env has no window) 2026-08-05 19:12:23 +08:00
83bf8323e2 fix(library): picker choice lost — Obsidian close() precedes onChooseItem, defer dismiss-settle 2026-08-05 19:11:53 +08:00
1e4567e844 feat(library): two-line candidate picker entries with per-type detail 2026-08-05 16:00:33 +08:00
16b8b242b8 feat(library): picker option to mark notes no_resolve 2026-08-05 15:47:13 +08:00
2686c3fa64 fix(library): proper picker-loop isolation with real regression test
Supersedes 4249952's half-fix: try now wraps pickCandidate too; restores
the 19 controller tests that commit deleted; replaces its source-grep
pseudo-tests with a behavioral two-entry isolation test.
2026-08-05 15:37:19 +08:00
4249952f0a fix(library): isolate per-note failures in candidate picker loop 2026-08-05 15:34:50 +08:00
d7162d3ac2 feat(library): interactive candidate picker for ambiguous resolves 2026-08-05 15:24:50 +08:00
3eb89772c7 fix(library): exclude light novels from anilist manga resolve 2026-08-05 15:00:16 +08:00
8a046a0ea2 feat(library): anilist-primary manga metadata with jikan fallback 2026-08-05 14:46:31 +08:00
d76ed2631b fix(library): surface comic vine api errors + sync summary transparency 2026-08-05 13:13:49 +08:00
f146de1b76 feat: sticky notices for sync/resolve summaries 2026-08-05 12:44:30 +08:00
49d7779bc1 feat(library): book author-hint resolve + ambiguous candidate logging 2026-08-05 11:05:04 +08:00
548e4c8ce0 fix(library): isolate per-type sync failures, suppress dry-run notices
syncAll() ran each enabled type's sync in sequence with no per-type
error handling, so one type throwing (e.g. its vault folder missing)
aborted the whole run and skipped libraryLastSync -- every other
enabled type silently never synced. Each type's runSync is now wrapped
individually: failures are logged (and surfaced via Notice unless
quiet) and the loop continues; libraryLastSync still updates after the
loop regardless.

Also: dry-run sync previews now route spec-level flip notifications
(the "chapter/issue out" Notices) through the log instead of a real
Notice, since a dry run never actually writes the change it's
describing.
2026-08-03 22:09:04 +08:00
ea5ddd9454 fix(library): seed-pass flip guard, manga null-sentinel, mangadex resolve
- comic/manga sync(): a note's first-ever observed issue/chapter number
  (no prior latest_issue/latest_chapter) now seeds the baseline without
  flipping read_status or notifying. Previously `prev === null` counted
  as "newer", so a Read note with no stored baseline flipped to Unread
  on its very first real sync. Flips now require a prior value AND a
  strictly greater candidate AND read_status Read, mirroring the
  watchlist build.ts `prevLast &&` guard.
- manga rss/last_chapter_date: quotedOrNull renders an unset value as
  the literal `null` token; on the next parse that string came back
  truthy, so an unset rss field was fetched as the URL "null" and
  isActive treated it as "has rss -> active" forever. Sentinel is now
  stripped back to '' everywhere it's read from frontmatter.
- manga resolve(): best-effort MangaDex id lookup by title (unique-exact
  match against attributes.title + altTitles) runs alongside the
  existing MAL lookup when the note has no mangadex_id yet. Any failure
  (no match, ambiguous, network error) is logged and skipped, leaving
  the mal_id patch intact.
2026-08-03 22:08:40 +08:00
1d5537742f fix(library): first-pass enrich gate skips post-resolve skeletons
isActive() for book/game/comic only checked for a resolved id, so a
note that had run resolve() but never a real sync() (no read_status/
play_status/status field yet) was treated as static and never
enriched on subsequent runs. Now also requires the status-analog
field canonical render always writes; missing it means sync() hasn't
actually produced output yet.
2026-08-03 22:08:09 +08:00
6225231d67 fix(library): suppress missing-key notices on quiet scheduled syncs 2026-08-03 21:40:21 +08:00
2cce78d664 feat(library): controller, settings, commands, scheduler 2026-08-03 16:59:47 +08:00
278f009a9b feat(library): generic per-type sync engine + resolve 2026-08-03 16:39:00 +08:00
c14da19c47 feat(library): rating line, manga finish-flip notify, game links, dedupe
- render **Rating:** line in manga/book/game/comic body (after read/play
  status, gated on rating != '0' + stars non-empty), matching watchlist's
  render.ts convention
- manga finish-flip now notifies user (final chapters out), matching
  chapter-flip's existing notify path
- game renderGame emits ## Links (Steam by appid, RAWG by url) — fixes
  latent owned-heading strip where user-added Links sections silently
  vanished since games never re-rendered the heading
- move duplicated deriveReadStatus/deriveRating/parseNumOrNull into
  library/convert.ts, import across specs; zero behavior change
2026-08-03 16:29:02 +08:00
d2a6940270 feat(library): comic spec — comic vine + issue flip 2026-08-03 16:16:34 +08:00
cdc653e6e4 feat(library): game spec — steam + rawg 2026-08-03 16:02:56 +08:00
0c8f897e46 fix(library): skip book sync on olid search miss (identity-swap guard) 2026-08-03 15:51:15 +08:00
1c90ae9abc feat(library): book spec — open library 2026-08-03 15:44:48 +08:00
abc3489d27 feat(library): manga spec — jikan enrich, rss/mangadex chapter flip 2026-08-03 15:28:01 +08:00
c398669ae6 feat(library): core types + rss/atom chapter feed parser 2026-08-03 15:07:06 +08:00
1e7e6d1032 docs: phase 2 implementation plan 2026-08-03 14:59:05 +08:00
fdd8609e49 docs: phase 2 multi-type design spec 2026-08-03 14:35:07 +08:00
a5ebb6f088 fix(watchlist): preserve prev country when TMDB tv lacks production_countries
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 15:20:43 +08:00
e0e0462836 fix(watchlist): TV country full name + tmdb_rating precision rounding
TMDB's origin_country returns ISO codes (KR), not full names, causing
a vault regression from South Korea to KR. buildRecord now prefers
production_countries[0].name, falling back to the raw origin_country
code only when absent.

TMDB also now returns vote_average at full precision (6.537), causing
mass diff noise against the vault's 1-decimal convention and spurious
rewrites on precision drift alone. tmdb_rating is now rounded to 1
decimal place.

Loki fixture updated to realistic TMDB shapes (ISO country code +
production_countries) to catch this regression going forward.
2026-07-30 15:00:39 +08:00
fb3f52e4b0 fix(watchlist): preserve custom body sections through sync rewrite
renderNote wiped any ## heading not owned by the renderer (Synopsis,
Cast, Links, My Notes) on every sync, destroying user content like
## Collection graph-link sections. extractCustomSections now pulls
non-owned sections out of the existing body before rewrite, and
renderNote re-emits them verbatim, in original order, between Links
and My Notes.
2026-07-30 14:59:24 +08:00
2c663568ca feat(watchlist): preserve existing TV crew fields until per-episode enrichment 2026-07-30 14:32:42 +08:00
b0f3dce76d fix: null-guard loadData on fresh install (no data.json crashed onload) 2026-07-30 14:00:20 +08:00
699bbf3a9f chore: finish rebrand from upstream obsidian-media-db-plugin
package.json author/description now match manifest.json, release
workflow plugin name and repo-automation.config.json repo ref no
longer point at the upstream project.
2026-07-30 13:24:53 +08:00
a4ba1b8e42 fix(watchlist): stale-read clobber, concurrency guard, leaked timeout, quiet catch-up notices
- SyncDeps.listNotes now returns paths only; new readNote(path) reads
  content immediately before parse/diff/write per note, closing the
  window where an edit made between the initial scan and a later write
  got silently overwritten. resolveMissingIds updated to match.
- WatchlistController gains a syncing flag shared by syncNow and
  resolveMissingIds so overlapping invocations short-circuit instead
  of racing on the same vault notes.
- main.ts registers cleanup for the 30s startup catch-up setTimeout so
  it doesn't fire after unload.
- syncNow takes a quiet flag (used by the scheduled catch-up path) so
  zero-change scheduled syncs don't spam a Notice; manual commands are
  unaffected.
2026-07-30 13:24:33 +08:00
b77a189848 fix(watchlist): resolve 429 backoff + unique-exact-match acceptance 2026-07-30 13:05:31 +08:00
22a409ce9b feat(watchlist): resolve-missing-ids command 2026-07-30 12:54:49 +08:00
aafa3bb1e4 fix(watchlist): surface sync command errors via Notice 2026-07-30 12:49:59 +08:00
f9cc324ead feat(watchlist): settings, commands, catch-up scheduler wiring 2026-07-30 12:44:52 +08:00
e8cb9b93fe fix(watchlist): strip surrounding quotes from prev user fields (notion_url round-trip) 2026-07-30 12:37:52 +08:00
eeaa37469c feat(watchlist): SyncEngine — tiered diff-on-write sync with throttle/backoff 2026-07-30 12:31:00 +08:00
1923bb87b8 fix(watchlist): normalize notion_url null-sentinel in buildRecord prev-read
quotedOrNull renders an empty notion_url as the literal string `null`.
buildRecord read that back verbatim on the next sync pass and re-quoted
it as "null", breaking diff-on-write (every re-sync of a note with no
notion_url appeared changed). Treat the `null` sentinel as empty when
reading prev frontmatter.
2026-07-30 12:30:57 +08:00
79ba40f04d fix: tests/tsconfig baseUrl after root baseUrl addition (typecheck script) 2026-07-30 12:27:21 +08:00
08f63205c2 feat(watchlist): tmdb client — v3/v4 auth, detail + search 2026-07-30 12:22:27 +08:00
0aa6df81a3 feat(watchlist): renderNote — canonical note serializer (golden-tested) 2026-07-30 11:17:22 +08:00
51d630fcd6 feat(watchlist): buildRecord — TMDB detail → canonical record
Port pure fn mapping raw TMDB JSON + prev frontmatter → WatchlistRecord. Fixtures from python reference selftest. TDD: 14 new cases all green.
2026-07-29 23:15:36 +08:00
732ec8adf6 feat(watchlist): note parsing (frontmatter, My Notes, tmdb ref) 2026-07-29 22:55:46 +08:00
cade7104db feat(watchlist): yaml helpers + schema types 2026-07-29 21:47:25 +08:00
e7714736ce docs: watchlist suite implementation plan 2026-07-29 21:06:54 +08:00