Skip to main content

series

Resolved series catalog

📄️ Incremental release feed: series with coverage activity, ordered by `(updatedAt, id)` after an opaque cursor. A consumer (e.g. a Codex release plugin) polls this a few times a day, stores `nextCursor`, and only ever receives series whose coverage changed since its last poll. Keyset, not offset, so it's gap-free and dupe-free while series are re-stamped concurrently; delivery is at-least-once, so consumers upsert by `seriesId`.

Incremental release feed: series with coverage activity, ordered by

📄️ Add a series straight from a metadata provider, for series with no discovered release yet. Reuses the resolver's `upsert_series_from_metadata` (the same path the review link-by-provider flow uses), so the row is provider-backed and carries its `series_external_ids` mapping — future discovered releases auto-resolve to it. Idempotent on `(provider, externalId)`: an existing mapping returns `200` with the existing row; a fresh fetch returns `201`. When `wishlist` is set (the default) the series is clipped to the wishlist.

Add a series straight from a metadata provider, for series with no

📄️ Clear `metadata_hash` for every provider-backed series row in scope so the next refresh tick rewrites them. The persist layer short-circuits the series UPDATE when the incoming provider payload hashes to the stored value; that's the right call for steady-state refreshes, but it strands existing rows whenever a new denormalized column lands on the `series` table (the upstream payload is unchanged → hash matches → write skipped → new column stays NULL forever).

This endpoint is the operator escape hatch for that scenario. It runs

📄️ Recompute every release's volume/chapter span and every series' `highest_volume` / `highest_chapter` mark from the stored file lists (titles as fallback). Network-free and idempotent. Unlike the incremental bump that runs when a release is linked, this is an authoritative pass: a series' marks are *replaced* with the MAX across its currently-linked releases, so it also corrects values an earlier, more eager parser over-counted and clears marks on series whose releases no longer parse to anything.

Use it after changing the span-parsing logic, or to backfill a catalog