Repository navigation
Rebase the fork onto upstream 2.12.2 - #14
Merged
Merged
Conversation
…nges, and make archiving part of every release (builtbyproxy#141) Co-authored-by: t <t@t>
…is renamed (builtbyproxy#127) Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
…yproxy#128) * fix: log later seasons of shows Serializd keeps as one season Jellyfin libraries ordered by TheTVDB split many anime into seasons that Serializd (TMDb order) lists as one long season, so an episode from Jellyfin season 2 was skipped with "Serializd has no season 2". When Serializd has season 1 but no season 2, the episode is now logged to season 1 at its absolute number, counted from the earlier Jellyfin seasons. Shows Serializd already splits into seasons never fall back, and an unknown earlier season length skips instead of guessing. Local dedup history keeps Jellyfin's numbering so the real-time and catch-up paths agree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: release as 2.10.2 so it doesn't collide with builtbyproxy#127's 2.10.1 Both PRs bumped to 2.10.1; whichever merged second would have shipped no release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: skip single-season fallback episodes past Serializd's season length The fallback trusted Jellyfin's season lengths alone. When Serializd had not picked up a new season yet, or the library was missing the end of season 1, the running number still pointed at a real-looking episode and the watch was logged to the wrong entry in a public diary. Serializd's /show response already carries episodeCount per season, so the fallback now requires it and skips any episode that would land past the end of season 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…uiltbyproxy#142) Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
* fix: restrict the Seerr connection test to admins * fix: keep usernames out of the shared sync progress phase * fix: return a fixed message when the Seerr connection test fails * fix: refuse /Stats and /History when the caller can't be resolved * test: guard the shared progress phase against usernames * fix: run one Serializd watchlist sync at a time and answer 409 while one is going * refactor: remove the single-account and test-connection endpoints no page calls * fix: rate-limit the Letterboxd and Serializd login checks per user and server-wide * test: pin which plugin endpoints are anonymous, signed-in or admin-only * chore: replace private network details with generic examples and read the deploy target from the environment * test: widen the progress privacy and endpoint authorization guards * test: drive the Seerr test failure through a fake transport and tidy the limiter * fix: cap successful login checks too and let the scheduled Serializd watchlist run wait for a manual one * chore: release 2.10.4 --------- Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
…er (builtbyproxy#145) * fix: create Seerr requests as the requesting user so Seerr applies their own approval rights * fix: give each account its own Serializd watchlist collection, tracked by id instead of by name * fix: let only admins name watchlist collections and playlists * fix: hash the account key in the collection record, keep renamed collections unique and say collections are visible server-wide * refactor: pass the sync's cancellation token to the collection rename and tidy the collection record * chore: release 2.10.5
…builtbyproxy#146) * fix: make stored secrets write-only * fix: carry saved secrets across a rename or an admin's owner change, and verify with the saved password * fix: show saved passwords, cookies and the Seerr key as Saved instead of filling them in, on both settings pages * fix: let an admin remove the saved Seerr key, let typed cookies win over the remove box, and match the saved Seerr URL exactly * fix: keep a failed admin save retryable and share one typed, cleared or kept rule for secrets * docs: describe the write-only secret rules in CLAUDE.md * chore: release 2.10.6 --------- Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
* fix: stop the Serializd watchlist sync on a partial read and never record a cancelled episode as failed * fix: sync each Letterboxd account on the right day, once, and stop giving up on films during outages * fix: take ratings the plugin writes as the rating sync baseline instead of pushing them later * docs: describe account-scoped sync history, local viewing dates and the rating import baseline * fix: address review findings on challenge detection, import supersede, outage rule and watchlist caps * fix: give up on a film that errors for a week, mark outage runs, and stop watchlist reads that repeat a page * refactor: detect Cloudflare challenges by page title only and tidy the new tests * chore: release 2.10.7
* fix: run scheduled tasks at staggered times of day * fix: retry Serializd cold starts and share one HttpClient * perf: cap skipped/failed history rows and index per-film lookups * fix: rewrite history and cache files atomically * perf: cache Letterboxd TMDb lookups and stop double-throttling them * perf: reuse the Serializd season cache for watchlist season lookups * perf: share one HttpClient across Letterboxd API and Seerr clients * perf: look up library items by TMDb id in the query, not by full scan * fix: keep every history row the sync and abandon rules read when compacting, and never rewrite a file that did not load cleanly * perf: pace website lookups after the request instead of alongside it, and let tests reset the film caches * fix: retry a Serializd write only when the connection never opened, stop an account's catch-up after repeated failures, and keep cookies off the shared clients * fix: give telemetry its own daily slot and keep a two-day fallback trigger for machines that are off at night * fix: pause an account's Letterboxd run after repeated Cloudflare blocks, and record films without a TMDb id once * perf: keep each account's website session and skip an API login that just failed, so real-time events stop logging in again * perf: link old history rows to user ids in the background, once, instead of during Jellyfin startup * fix: skip the Letterboxd diary import while another Letterboxd sync is running * perf: count movies without loading them, and read existing ratings only for users who sync ratings * fix: let a paused Letterboxd account try one login a day so an outage no longer pauses it for good * docs: note the cached website session and the narrower rating baseline in CLAUDE.md * fix: address security review: check an episode's series, stop daily logins after a week, never push before a user's ratings are read, and drop superseded sessions * fix: address code review: never retry rejected credentials, remember only a definite API refusal, wait for the gate before importing, and test pacing by order * fix: address performance review: stop a Serializd catch-up only on service failures, and wait for the gate before a Serializd import * chore: release 2.10.8 --------- Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
* fix: show load and save failures instead of swallowing them * fix: report the Integrations save result * fix: keep the in-app page working when the admin settings page is cached, by scoping its lookups and opening the settings page instead * fix: set the Letterboxd film rating for a review that has only a rating, instead of failing * fix: on the user page, confirm Remove in the page, report sync, progress, verify and review failures, and offer Review only where it works * fix: on the admin page, save on top of the stored config, run the TV syncs for every user, label the overview as the admin's own, and report every failure * fix: address security review: send review errors as one short line, keep the rating title plain, refuse a non-finite rating, and let Retry call only the loaders * fix: address code-smell review: count a save by its status alone, keep words apart in a rating title, scope the disabled-button style, and pin the dashboard's task keys * docs: note the rating-only review and the dashboard's scoped lookups in CLAUDE.md * docs: reword the in-app page fallback note in CLAUDE.md * chore: release 2.10.9 --------- Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
…#153) * style: readable primary buttons, faint text and disabled state * fix: stop restyling Jellyfin's document and following the OS theme * fix: keep both dashboards inside a phone screen and show each activity row's date there * fix: follow Jellyfin's light or dark theme, with text and status colours readable in both * fix: make the dashboards usable by keyboard and screen reader: nav buttons, a rating slider, real dialogs and labelled fields * fix: send Back to Jellyfin to the server's own base URL, and back through Jellyfin's history when opened in the app * fix: stop the admin page's progress polling once Jellyfin has dropped the page * test: pin both dashboards' contrast, scoped styles, phone layout and keyboard markup * fix: read Jellyfin's theme from the background it paints, which 10.11 keeps off the document while it loads * fix: find the admin page's dialogs through the page itself, so leaving the page cannot throw * docs: note the dashboards' theme, dialog and contrast rules in CLAUDE.md * fix: address security review: never let the browser fill its Jellyfin login into the diary form, and drop typed secrets when the dialog closes * fix: address code-smell review: a readable gold for links and icons in the light palette, the new admin lookups through the page root, and looser markup tests * chore: release 2.10.10 --------- Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
* fix: keep email addresses out of the plugin's logs and out of the log bundle sent to the developer * fix: log only the status and size of a successful Letterboxd review reply, which can echo the review * feat: let an admin regenerate the telemetry instance id, and remember the answer to the opt-in notice * refactor: drop the Serializd username field nothing reads * feat: preview the exact telemetry ping and log bundle before anything is sent, regenerate the telemetry ID, and ask once about telemetry on the admin overview * docs: describe the telemetry previews, Regenerate ID, the opt-in notice, exact error counts and the masked log bundle as they ship * docs: note the telemetry previews and email masking rules in CLAUDE.md * fix: address security review: mask encoded email addresses, keep a quoted review out of a failed post's log, and send the bundle preview's note in a POST body * fix: address code-smell review: cut review replies older releases logged, leave a very short review's error text intact, widen the email mask, and share one test logger * chore: release 2.11.0
…iltbyproxy#156) * fix: cap rate-limit waits at a minute, re-sign the Letterboxd retry, and let a stopped sync cancel its network waits * fix: post a Serializd episode review on the episode its log goes to, including shows Serializd lists as one season * fix: never match a Letterboxd TV entry to a movie on the website login path * fix: serve the full 250-row history page both dashboards ask for * docs: describe the telemetry start-minute window the code actually uses * fix: address security review: read a page's TV marker only from its TMDb button, keep the not-a-film marker out of cache reads, and leave usernames out of the rate-limit log * fix: address code-smell review: count only an explicit TV marker as TV, cancel test waits from inside the request, check the dashboards' history page size against the cap, and tighten the telemetry spec * fix: address performance review: treat a rate limit longer than the client waits as a block, so a Letterboxd run stops after a few instead of trying every film * docs: note the rate-limit cap and the cancellation rule in CLAUDE.md * fix: let the TMDb button decide a TV entry, since live pages label TV entries as movies * chore: release 2.11.1
* feat: search, episode grouping and older history in the activity list * feat: group binge runs in the admin Activity log * feat: page the activity list to its true end, keep one copy of an event seen on two pages, and label the search * fix: word the account dialog's watchlist toggle for the service picked, and drop the dash from the service names * test: pin the activity list's search, paging and the account dialog's service wording * docs: describe the activity search, older history and folded episode runs in the README * fix: address security review: key a repeated event by its Jellyfin user too, and pin the escaping of a folded episode run * fix: address code-smell review: keep a folded run to one account, give its true episode range and any failure, cut only by the filtered services, and point an empty search at older history * chore: release 2.12.0 * test: check the activity pages' history page size settings against the server cap --------- Co-authored-by: Wouter Stulp <wouter@peterprint.nl>
…uiltbyproxy#158) * fix: put a review of a film already in the diary on that entry instead of logging a second watch dated today * test: check live that a review lands on the existing diary entry and the test account is restored * docs: describe where a review of an already-logged film goes in CLAUDE.md * fix: address security review: keep a failed update's reply out of the error, read every page of a film's diary entries, date a new entry on the server's local day, and let the live test delete only its own entries * fix: address code-smell review: read only what the entry lookup needs, refuse a malformed review date, date the tests by the controller's own rule, and make the live test's cleanup failure-safe * fix: address domain review: hold the film's sync lock while a review is placed, and read the diary a second time before deciding no entry exists * chore: release 2.12.1 * fix: cache a Letterboxd API token only with its member id, so a sign-in never reads the diary without one * test: write the member ids the live review test and the client use to its output, and check they match
…byproxy#159) * refactor: serve one shared dashboard script and stylesheet, stamped and cached per plugin version * refactor: load the shared script and stylesheet in both dashboards and drop their duplicated code and styles * feat: say when a review was added to the existing diary entry, and show the server's note for each account * docs: describe the dashboards' shared script and stylesheet in CLAUDE.md * fix: address security review: never cache a debug build's shared files for good, and pin the shared escaper and the anonymous scripts' static content * fix: address code-smell review: read the pages' stamped version from the page itself, anchor the review-notes check on the next method, and drop restated assertions * perf: address performance review: tag the shared files so a revalidation is answered with 304 * fix: find the admin page's root by id when Jellyfin runs its script without a current script * chore: release 2.12.2
* fix(worker): close the download open redirect, cap daily log bundles, keep request logs off * test: give the auth-failure and scheduled-task delegation tests real assertions * test: run the Serializd history tests serially with the other shared-state tests * chore: remove the stale build.yaml that no tooling reads * ci: split release into a read-only build and a minimal publish job that repairs half-finished releases * ci: pin every workflow action to a full commit SHA * ci: require the version to rise above main and stay untagged * ci: let Dependabot watch actions, site npm packages and the other NuGet packages * docs: describe the safer release pipeline and the worker tests in CLAUDE.md * test(worker): check every manifest download URL still passes the stricter path rule * ci: strip multi-line tags from release notes, warn on superseded versions, keep the manifest sorted * ci: skip the rebuild when repairing a release whose asset is already published * ci: run the worker tests on every PR
… key revocation behaviour (builtbyproxy#155)
* docs: archive the shipped auth-circuit-breaker OpenSpec change and sync its spec * docs: state the 10.11.9 SDK floor in CLAUDE.md * docs: point site, security and issue-template links at the renamed Jellyscribe repo * docs: update the site for the 10.11.9 floor, optional File Transformation, the current setup flow and the one-way Seerr mirror * docs: rewrite the README setup and dashboard guide for the current UI, the one-way Seerr mirror, the uncounted manifest and the PR template * docs: note that downloads are still counted with the GitHub manifest and clarify the breaker archive notes * docs: link the auth breaker live check to its tracking issue * docs: correct the install-counter release note that called the fingerprint unlinkable
Jellyfin installs Jellyscribe from fork/manifest.json instead of the upstream repository. fork/release.sh builds and tests the plugin, publishes the zip as a GitHub release and lists it in the manifest. Versions are the upstream version plus a fourth number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit fe6ea36)
Logged episodes and diary entries reached Serializd, but the show never got a status, so the profile's Shows tab (Currently watching / Watched / ...) stayed empty. The first time an episode of a show is logged, real time or catch-up, the show is now marked currently watching via POST /currently_watching. It is sent once per show per account, never for a show whose every episode in Jellyfin is already played, and a failure there does not fail the episode log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 81fc238)
The sidebar brand block carried a second subtitle line crediting the upstream author; this fork keeps only the product subtitle there. The license, README and other credits are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit a31297d)
The README still pointed installs, releases and badges at builtbyproxy, so following it would install upstream instead of this fork. It now explains the fork, lists what it adds, gives the fork's plugin repository URL and release steps, and says that telemetry and log uploads still go to upstream's endpoints. The royalty.dev badge and .github/FUNDING.yml (GitHub's Sponsor button) are removed since they fund upstream, not this fork. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 34b7e54)
At 540px and below the When column is hidden, which left phone users with no idea when anything was logged, and the status chips wrapped into three or four rows above the table. Show the date in the title's subtitle line at that width, and make the chip rows one horizontally scrolling strip using the same rule as the mobile nav. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit c1ede4d)
The account modal listed twelve switches in one flat column, mixing the everyday ones with rarely-touched tuning, and showed Seerr options on servers with no Seerr configured. Remove deleted an account on one click. Split the switches into Sync, Watchlist & Seerr, and a collapsed Advanced section (skip already-synced, stop on first failure, Seerr backfill). The admin page hides the Seerr rows when no Seerr URL is set, keeping them in the form so saving preserves their values. Both pages ask for confirmation before removing an account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit cef09b9)
The fork drops upstream's telemetry, log upload and install-count mirror, so the README no longer describes them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit b91713b)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 86ed5c2)
This fork is standalone, so it must not upload server log bundles to the upstream author's diagnostics backend. Drops the PreviewLogs/SendLogs endpoints, the bundle builder and uploader, and their tests. The local Logs tab still reads Jellyfin's log files through GetLogs; its elevation check moves to LetterboxdControllerTests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 75fe02f)
This fork is standalone and should not report usage data to the upstream author's ingest worker, even opt-in. Removes TelemetryService, its constants (ingest URL and key), the persisted TelemetryData config, the weekly TelemetryTask, the preview endpoint and every RecordError / OnSyncEvent hook in the runners. Logging and error handling around those hooks are unchanged. Old config XML files still load: XmlSerializer skips the now-unknown <Telemetry> element. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 8cd00c1)
RepositoryMigrationService added the upstream author's Cloudflare Worker manifest URL to Jellyfin's plugin repositories so every catalog poll could be counted as an install. This fork is standalone and installs from its own manifest, so drop the migration, its hosted-service registration, the CatalogMigrationDone flag and their tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit e2261a2)
The backing endpoints are gone, and this standalone fork should not offer to send usage data or log bundles to the upstream author. Drops the "Anonymous telemetry" settings panel, the "Send to developer" button and its confirm box, and the JS that read/saved the Telemetry config and posted to Telemetry/SendLogs. The Logs tab still shows local log lines. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 3feefa3)
Only a "currently watching" history key short-circuited the status check, and a finished show never gets one. So every catch-up walked every episode of every finished show again, and an unfinished show with new episodes was walked twice per run (pre-check plus the marking pass). A show seen as finished now gets a "finished" history key for that account and is never checked again. The runner also memoises the result per show for the run. Unfinished shows are still marked currently watching once per account, and failed marks are still retried. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit fc4299a)
The finished marker is now permanent, so a show still airing would get it the moment you caught up on its latest episode and never show as currently watching again. Being caught up on a continuing show means still watching it; only a show whose status is Ended can be finished. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 10dcff5)
A tripped auth breaker or an abandoned film only showed up in the logs and the activity log, so an admin found out days later that an account had stopped syncing. Configuring an ntfy topic URL (plus optional token, encrypted at rest like the Seerr API key) now sends a push when: - a Letterboxd account's auth breaker opens (high priority), via AuthBreaker.NotifyOpenedAsync, which every breaker call site uses - the scheduled runner gives up on a film after MaxConsecutiveSyncFailures failed attempts Sends never throw into the sync path, and the same event is sent at most once per 24h. An admin-only Notifications/Test endpoint and a "Send test" button in Integrations let the admin check the settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 0dd2382)
A show that ended and was fully played in Jellyfin stayed on the Serializd "currently watching" list forever, or was never marked at all when it was finished at first sight. Now both the playback handler and the catch-up runner mark it watched (watched_v2 with every numbered season id) and take it off currently watching, once per account. The watched mark is recorded only after watched_v2 succeeds, so a failed call is retried on the next run. The currently-watching removal only logs a warning on failure, since the show may never have been on that list. A show counts as pending until it is marked watched, so finished shows still trigger a catch-up login, and stop doing so once done. The marker is "showwatched" because KindWatched already names the per-episode watched history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit e221c5a)
Serializd is the main service for most users, but it has no auth breaker, so a broken login only showed up as a log line on every run. SerializdApiClient now throws a SerializdAuthException when /login answers 401/403, while 5xx after the cold-start retries and network errors keep their existing types, so Render waking up never reads as a bad password. SerializdServiceFactory catches that exception for the background paths (catch-up, watchlist, diary import, real-time playback), which pass the Jellyfin username, and sends a high-priority ntfy alert. The existing 24h dedupe keeps it to one message a day while the login stays broken. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit b38117a)
worker/, site/ and openspec/ are upstream's telemetry server, website and planning docs, none of which this fork runs. build.yaml, deploy.sh, codecov.yml, the root manifest.json and upstream's docs-deploy, integration, PR-title and version-gate workflows only served upstream's setup. release.yml now runs fork/release.sh on every push to main when the version has no tag yet, using the merged PR's "## Release notes" as the changelog, so a merged PR ships without a manual step. ci.yml keeps the build/test, the SDK floor check and the Jellyfin 12 probe. release.sh uses a local dotnet when present, so it runs on GitHub's runners as well as in Docker locally. The templates, SECURITY.md and CLAUDE.md now point at this repository. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 8ddf983)
The dashboards printed dates with toLocaleDateString/toLocaleTimeString, so the format followed each browser's locale (often US month-first) rather than the European day-first format users expect. One shared formatDate in jellyscribe.js now renders dd-MM-yy HH:mm (24-hour, local time) for every history row, group row, the mobile subtitle and the Activity log, and dd-MM-yy for the "login failing since" date on account cards on both pages. The review modal's date input keeps its ISO value, which the input type requires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 9a06060)
… asset main is protected now, so the old flow (release.sh committing fork/manifest.json to main) can't work, and the user wants nothing release-related in fork/. Publishing a release with tag v<version> now runs release.yml: a read-only build job tests the tag and builds it with the tag as AssemblyVersion, and a separate publish job, which runs none of the repository's code, attaches the zip and a manifest.json that extends the previous release's. Jellyfin reads the plugin repository from releases/latest/download/manifest.json. This also closes the security review's finding that the release token was exposed to the build. ci.yml gets an explicit read-only token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit b276ef8)
The fork now sits on builtbyproxy/Jellyscribe v2.12.2 with its own changes re-applied on top, so the version becomes the upstream version plus the fork's fourth number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fork's main is replaced by upstream 2.12.2 plus the fork's own changes re-applied on top. This merge only links the old fork history so the branch can go into the protected main through a PR; its tree is this branch's tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebuilds the fork on top of upstream v2.12.2, then re-applies the fork's own changes. Releases as 2.12.2.1.
Upstream merged most of the fork's work itself (builtbyproxy#142, builtbyproxy#144, builtbyproxy#146, builtbyproxy#148, builtbyproxy#149, builtbyproxy#153, builtbyproxy#157 contain the fork's commits under its author; builtbyproxy#145 and builtbyproxy#159 reimplemented fork ideas), so a plain merge produced ~110 conflicts between two versions of the same code. Instead this branch starts from
upstream/mainand cherry-picks only what upstream doesn't have. A final-s oursmerge links the old fork history so the protectedmaintakes it as a normal PR, no force-push.Re-applied fork changes (cherry-picked with
-x, original author kept)jellyscribe.js)release.ymlon published release, manifest as release asset)Dropped in favour of upstream
One behaviour-related test change: the fork's "film abandoned → ntfy" test now throws
FilmNotFoundException, because upstream only gives up on a film after 3 permanent failures; a generic error no longer abandons. Assertions unchanged.Verified: full suite
Passed: 1346, Skipped: 17, Failed: 0(dotnet 9, Release); no telemetry references left (git grep);upstream/mainis an ancestor of this branch.Follow-up, not in this PR:
release.ymlstill uses tag-pinned actions (@v4…); upstream pins to SHAs.🤖 Generated with Claude Code