Skip to content

feat(overlays): add force processing and reset concurrency gating#2827

Merged
enoch85 merged 24 commits into
Maintainerr:developmentfrom
MrLinford:feat/overlay-phase-1-reapply-parity
May 10, 2026
Merged

feat(overlays): add force processing and reset concurrency gating#2827
enoch85 merged 24 commits into
Maintainerr:developmentfrom
MrLinford:feat/overlay-phase-1-reapply-parity

Conversation

@MrLinford

@MrLinford MrLinford commented May 1, 2026

Copy link
Copy Markdown
Collaborator

Description & Design

This change adds force-processing support to overlay operations and gates reset against concurrent processing runs.

What changed:

  • Moved OverlayProcessorRunResult and overlayProcessRequestSchema to @maintainerr/contracts for shared use
  • Added optional force flag to overlay processing endpoints to bypass stale-state skip logic
  • Gated DELETE /overlays/reset to return 409 if a processor run is in progress (prevents concurrent mutations)
  • Updated overlay settings summary to include the Skipped count
  • Simplified processor status cleanup and refactored duplicate UI code

Why this matters:

  • Force processing allows operators to rebuild overlays when templates change, even if the item state hasn't changed
  • Resetting concurrency gating prevents poster mutation conflicts with in-flight overlay processing
  • Clearer UI feedback with Skipped count in manual run results
  • Shared type contracts eliminate type mismatches between server and UI

Related issue

AI-Assisted Development

AI-assisted portions of this PR:

  • Initial implementation scaffolding for the force-processing backend flow
  • UI wiring for global and collection-scoped reapply actions
  • Test scaffolding and wording iteration for the operator UX changes
  • Review-fix follow-up for processor mutual exclusion and UI gating alignment
  • Final tightening pass to reduce duplicate UI code and keep the Phase 1 implementation smaller

What I personally reviewed, changed, or validated:

  • Reviewed the controller, processor, and UI behaviour end-to-end
  • Adjusted the implementation to preserve existing overlay state/revert semantics instead of introducing a parallel reapply path
  • Verified the processor locking change at the service boundary so collection-scoped runs cannot overlap with other overlay processing
  • Confirmed reset remains available while overlays are globally disabled
  • Confirmed collection reapply is gated by both collection overlay support and global overlay settings
  • Confirmed the UI behaviour and copy align with the intended operator flows
  • Removed unrelated devcontainer/UI bundle work from this PR branch
  • Ran focused server tests and focused UI tests on the clean PR branch

Why this solution fits this project’s coding standards and design:

  • It reuses the existing overlay processor and shared state/revert logic instead of duplicating behaviour
  • It keeps UI feedback inline and consistent with existing settings/action patterns
  • It uses existing shared UI primitives such as Modal, PendingButton, SaveButton, and settings feedback helpers
  • It keeps controller routing, processor behaviour, and UI action components separated
  • It keeps the media-server abstraction untouched and does not add provider-specific branching
  • It uses focused tests around the touched slices and keeps the changes scoped to the overlay surface

Note: The author is fully responsible for the correctness, testing, and maintainability of this change, regardless of the tooling used.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I understand the code I am submitting and can explain how it works
  • I have performed a self-review of my code
  • I have linted and formatted my code
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes

How to test

  1. Enable overlays with at least one overlay-enabled collection and a valid overlay template
  2. In Overlay Settings, click "Run Now" and verify the success alert displays: "Processed: X, Reverted: Y, Skipped: Z, Errors: 0"
  3. Use "Reset All Overlays" and confirm original artwork is restored
  4. Verify that Reset is available even when overlays are globally disabled (it's a recovery action, not a processing action)
  5. Test concurrency: Trigger a forced overlay run, then immediately click Reset — confirm it's rejected with a 409 error
  6. Run the focused test suite:
yarn workspace @maintainerr/server test -- overlays.controller.spec.ts
yarn workspace @maintainerr/ui test -- src/components/Settings/Overlays/index.spec.tsx

Validation performed

✓ Server tests: 44/44 pass (includes reset-while-disabled and reset-while-running 409 scenarios)
✓ UI tests: 13/13 pass (includes Run Now force flag and reset availability)
yarn format / yarn lint / tsc --noEmit all clean
yarn workspace @maintainerr/server build and vite build both clean

Scope

This PR includes:

  • Force-processing support in the overlay API and the processor
  • Reset concurrency gating with 409 response
  • Shared contracts for OverlayProcessorRunResult and overlay process request
  • UI updates to display skipped count in manual run summaries
  • Focused test coverage for force vs normal runs and reset gating
  • Collection detail render-order fix required by collection-level overlay actions
  • Code simplification: refactored duplicate UI code and streamlined processor status management

Notes for reviewers

The Notifications/index.spec.tsx hardening is included in this PR. This is unrelated to overlays; if you'd prefer, it can be split into a separate PR.

Key commits in this clean PR branch:

  • f42d2613 feat(overlays): add force reapply processing flow
  • 08d7cdaa feat(ui): add reapply all overlays action
  • 528a2ccc feat(ui): add collection overlay reapply action
  • bb87c3f5 feat(ui): clarify overlay action semantics
  • 9e208c15 fix: prevent collection detail render crash
  • 49d686d6 fix(overlays): serialize collection reapply actions
  • 3b86c94b refactor(overlays): tighten phase one implementation

@MrLinford MrLinford requested a review from enoch85 as a code owner May 1, 2026 17:21
@MrLinford

Copy link
Copy Markdown
Collaborator Author

Quick note on the Phase 1 PR size: the current PR shows +1101 / -198, but that number is inflated by focused regression coverage and a required safety fix for a collection-detail.

Runtime/product code is much smaller than the raw diff suggests. The larger pieces are mainly:

  • overlay-processor.service.spec.ts: +306 lines of backend regression coverage
  • ReapplyOverlaysButton/index.spec.tsx: +142 lines of UI coverage
  • Settings/Overlays/index.spec.tsx: +122 lines of UI coverage
  • CollectionDetailPage.spec.tsx: +108 lines for the render-order regression
  • overlays.controller.spec.ts: +81 lines for API force-flag coverage

So roughly ~750 lines of the PR are tests/specs, and the actual runtime implementation is closer to the intended target. The final tightening pass also removed duplicate UI implementation by collapsing TriggerRuleButton into the existing TriggerRuleActionButton, moved overlay result formatting into a tiny UI helper, and simplified processor status cleanup.

I intentionally kept the focused tests in the PR because the changes touch poster mutation, forced reapply behavior, reset/reapply semantics, UI gating, and processor mutual exclusion. Those are release-sensitive paths, and the tests are what make the smaller implementation safe to review and maintain.

One included fix, fix: prevent collection detail render crash, adds a small page regression test and a two-line render-order fix. I kept it in this PR because the new collection-level reapply action depends on that page rendering safely once collection data loads.

If preferred, I can split the render-order crash fix into its own PR to reduce the visible Phase 1 diff, but I’d recommend keeping the focused overlay tests with the feature work.

This comment was marked as resolved.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread apps/server/src/modules/overlays/overlays.controller.ts Outdated
Comment on lines +359 to +362
if (this.status === 'running') {
this.logger.warn('Overlay processor is already running, skipping');
return this.createEmptyResult();
}
@enoch85

enoch85 commented May 3, 2026

Copy link
Copy Markdown
Collaborator

@SmolSoftBoi Don't do Copilot reviews please. Review it yourself. 👍

@MrLinford

Copy link
Copy Markdown
Collaborator Author

Addedtwo focused commits:

52236b7b fix(overlays): simplify manual reapply controls
47d4dc8d test(ui): harden notification save spec

@enoch85

enoch85 commented May 7, 2026

Copy link
Copy Markdown
Collaborator

@MrLinford is this ready to be merged?

Will have a look this weekend if the answer is yes.

@MrLinford

Copy link
Copy Markdown
Collaborator Author

I believe so.
PR updated with discussed change, also added harden notification save spec

- Promote process result + request schema to @maintainerr/contracts so
  server and UI share one wire shape; drop the duplicate UI interface
  (skipped was incorrectly optional) and the inline zod schema in the
  controller.
- Remove the appliedMediaItems recursion sentinel from the public
  processCollection signature so the lock check can't be bypassed by a
  truthy empty array; processAllCollections now calls the internal
  helper directly.
- Gate DELETE /overlays/reset against concurrent processing and add
  spec coverage for both reset-while-disabled and reset-while-running.
- Surface the skipped count in the inline overlay summary alert.
- Replace the TriggerRuleButton re-export shim with a direct import of
  TriggerRuleActionButton at the one usage site, and revert the no-op
  canTestMedia change on CollectionDetailPage.

enoch85 commented May 7, 2026

Copy link
Copy Markdown
Collaborator

@MrLinford — pushed 44d5cbca on top of your branch with the review-fix items from my pass. Net −88 lines.

What changed:

  • Moved OverlayProcessorRunResult + overlayProcessRequestSchema into @maintainerr/contracts. Drops the duplicate UI interface (where skipped was incorrectly optional) and the inline zod schema in the controller.
  • Removed the appliedMediaItems recursion sentinel from the public processCollection signature; processAllCollections now calls processCollectionInternal directly so the lock check can't be bypassed by a truthy empty array.
  • Gated DELETE /overlays/reset against concurrent processing — it returns 409 if a run is in progress. Added spec coverage for both reset-while-globally-disabled (still works) and reset-while-running (rejected).
  • The inline overlay-summary alert now surfaces the Skipped count.
  • Deleted the TriggerRuleButton/ re-export shim; the one importer in MediaCard/MediaModal now points at TriggerRuleActionButton directly.
  • Reverted the no-op canTestMedia={Boolean(ruleGroup?.useRules)} on CollectionDetailPage; the parent conditional already guarantees that.

Validated locally:

  • yarn format / yarn lint / tsc --noEmit (server, UI, contracts) clean — no errors, no warnings.
  • Server unit tests: 44/44 pass.
  • UI unit tests: 13/13 pass.
  • yarn workspace @maintainerr/server build and vite build both clean.
  • Playwright smoke against the seeded UI (mocked /api/overlays/*) covering: toggle-and-save flow, missing-cron post-save modal, Run Now sending force: true, the new Skipped field in the inline alert, the reset confirm modal title change, and the new 409 reset gate. All green-

Note on the description: the PR body still describes Reapply All, Reapply This Collection, and the ReapplyOverlaysButton component / spec, but those were removed in 52236b7b fix(overlays): simplify manual reapply controls. Worth updating the description (and the title — Phase 1 reapply parity no longer matches the trimmed scope) before merge so reviewers aren't looking for code that isn't there. Also the unrelated Notifications/index.spec.tsx hardening probably wants to be split into its own PR.

Could you pull and verify the flows on your end? Particularly: enabling overlays then saving, Run Now with the new Skipped line, and that Reset still works while overlays are globally disabled but is rejected with a clear inline error if you somehow trigger it during a run. If anything looks off, push back and I'll iterate.

@enoch85

enoch85 commented May 8, 2026

Copy link
Copy Markdown
Collaborator

@MrLinford Just waiting for your testing here on this.

I'm thinking this will go into 3.11.0.

@MrLinford

Copy link
Copy Markdown
Collaborator Author

@MrLinford Just waiting for your testing here on this.

I'm thinking this will go into 3.11.0.

Planning to do this at the weekend, not sure what day yet.

@MrLinford MrLinford changed the title feat(overlays): complete Phase 1 reapply parity and operator UX feat(overlays): add force processing and reset concurrency gating May 10, 2026
@MrLinford

Copy link
Copy Markdown
Collaborator Author

@MrLinford — pushed 44d5cbca on top of your branch with the review-fix items from my pass. Net −88 lines.

What changed:

  • Moved OverlayProcessorRunResult + overlayProcessRequestSchema into @maintainerr/contracts. Drops the duplicate UI interface (where skipped was incorrectly optional) and the inline zod schema in the controller.
  • Removed the appliedMediaItems recursion sentinel from the public processCollection signature; processAllCollections now calls processCollectionInternal directly so the lock check can't be bypassed by a truthy empty array.
  • Gated DELETE /overlays/reset against concurrent processing — it returns 409 if a run is in progress. Added spec coverage for both reset-while-globally-disabled (still works) and reset-while-running (rejected).
  • The inline overlay-summary alert now surfaces the Skipped count.
  • Deleted the TriggerRuleButton/ re-export shim; the one importer in MediaCard/MediaModal now points at TriggerRuleActionButton directly.
  • Reverted the no-op canTestMedia={Boolean(ruleGroup?.useRules)} on CollectionDetailPage; the parent conditional already guarantees that.

Validated locally:

  • yarn format / yarn lint / tsc --noEmit (server, UI, contracts) clean — no errors, no warnings.
  • Server unit tests: 44/44 pass.
  • UI unit tests: 13/13 pass.
  • yarn workspace @maintainerr/server build and vite build both clean.
  • Playwright smoke against the seeded UI (mocked /api/overlays/*) covering: toggle-and-save flow, missing-cron post-save modal, Run Now sending force: true, the new Skipped field in the inline alert, the reset confirm modal title change, and the new 409 reset gate. All green-

Note on the description: the PR body still describes Reapply All, Reapply This Collection, and the ReapplyOverlaysButton component / spec, but those were removed in 52236b7b fix(overlays): simplify manual reapply controls. Worth updating the description (and the title — Phase 1 reapply parity no longer matches the trimmed scope) before merge so reviewers aren't looking for code that isn't there. Also the unrelated Notifications/index.spec.tsx hardening probably wants to be split into its own PR.

Could you pull and verify the flows on your end? Particularly: enabling overlays then saving, Run Now with the new Skipped line, and that Reset still works while overlays are globally disabled but is rejected with a clear inline error if you somehow trigger it during a run. If anything looks off, push back and I'll iterate.

From the testing I have done, all looks good.

Can't test this, though.

"Test concurrency: Trigger a forced overlay run, then immediately click Reset — confirm it's rejected with a 409 error"

As you can't hit Reset while Run Now is running 😄

@enoch85 enoch85 merged commit e6862fb into Maintainerr:development May 10, 2026
10 checks passed
maintainerr-automation Bot added a commit that referenced this pull request May 10, 2026
* build(deps): bump fast-uri from 3.0.6 to 3.1.2 (#2862)

Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.0.6 to 3.1.2.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](fastify/fast-uri@v3.0.6...v3.1.2)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add typed TanStack Query test helpers and migrate spec mocks (#2863)

* Add typed React Query test helpers

* Reuse existing deferred helper in queryResults

* fix(storage-metrics): merge shared volumes across hosts when byte-exact (#2852)

* fix(storage-metrics): merge shared volumes across hosts when signature is byte-exact

Resolves #2841.

* style: apply prettier formatting

---------

Co-authored-by: Kristian Matthews-Kennington <kristian@matthews-kennington.com>

* build(deps-dev): bump typescript-eslint from 8.59.1 to 8.59.2 (#2850)

Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.59.1 to 8.59.2.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.2/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.59.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat(overlays): add force processing and reset concurrency gating (#2827)

* feat(overlays): add force reapply processing flow

* feat(ui): add reapply all overlays action

* feat(ui): add collection overlay reapply action

* feat(ui): clarify overlay action semantics

* fix: prevent collection detail render crash

* fix(overlays): serialize collection reapply actions

* refactor(overlays): tighten phase one implementation

* style(ui): format collection detail spec

* fix(overlays): use named zod import

* fix(overlays): simplify manual reapply controls

* test(ui): harden notification save spec

* refactor(overlays): tighten phase 1 review fixes

- Promote process result + request schema to @maintainerr/contracts so
  server and UI share one wire shape; drop the duplicate UI interface
  (skipped was incorrectly optional) and the inline zod schema in the
  controller.
- Remove the appliedMediaItems recursion sentinel from the public
  processCollection signature so the lock check can't be bypassed by a
  truthy empty array; processAllCollections now calls the internal
  helper directly.
- Gate DELETE /overlays/reset against concurrent processing and add
  spec coverage for both reset-while-disabled and reset-while-running.
- Surface the skipped count in the inline overlay summary alert.
- Replace the TriggerRuleButton re-export shim with a direct import of
  TriggerRuleActionButton at the one usage site, and revert the no-op
  canTestMedia change on CollectionDetailPage.

---------

Co-authored-by: Craig Linford <craig.linford@sas.com>
Co-authored-by: enoch85 <mailto@danielhansson.nu>

* build(deps-dev): bump @suites/unit and @suites/doubles.jest to 3.1.x (#2865)

The two packages augment each other's types; bumping only one causes
StubbedInstance/Mocked type mismatches. Bumps both in lockstep,
superseding #2846 and #2848.

* build(deps): bump node from 24.15.0-alpine3.22 to 26.1.0-alpine3.22 (#2857)

* build(deps): bump node from 24.15.0-alpine3.22 to 26.1.0-alpine3.22

Bumps node from 24.15.0-alpine3.22 to 26.1.0-alpine3.22.

---
updated-dependencies:
- dependency-name: node
  dependency-version: 26.0.0-alpine3.22
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(docker): install corepack for Node 26+ where it's no longer bundled

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: enoch85 <mailto@danielhansson.nu>

* build(deps-dev): bump typescript from 5.9.3 to 6.0.3 (#2713)

* build(deps-dev): bump typescript from 5.9.3 to 6.0.3

Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](microsoft/TypeScript@v5.9.3...v6.0.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(server): set explicit rootDir for TypeScript 6 build

TS 6 no longer infers rootDir from input files; it defaults to the
tsconfig directory. Setting rootDir explicitly in the build config
preserves the dist/<file> layout that mirrors src/<file>.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: enoch85 <mailto@danielhansson.nu>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kristian Matthews-Kennington <kristian@matthews-kennington.com>
Co-authored-by: enoch85 <mailto@danielhansson.nu>
Co-authored-by: Craig Linford <clinford86@gmail.com>
Co-authored-by: Craig Linford <craig.linford@sas.com>
enoch85 added a commit that referenced this pull request May 10, 2026
)

Documents the force flag on overlay processing endpoints and the 409
gating on DELETE /overlays/reset (#2827), and points contributors at
the new TanStack Query test helpers (#2863).
maintainerr-automation Bot added a commit that referenced this pull request May 11, 2026
* docs: sync overlay processing API and add UI test-utils reference (#2866)

Documents the force flag on overlay processing endpoints and the 409
gating on DELETE /overlays/reset (#2827), and points contributors at
the new TanStack Query test helpers (#2863).

* fix(rules): scope exclusion cascade by type, not entry point (#2858) (#2867)

Excluding a single episode used to skip every other episode of the same
show. The cascade filter keyed off `Exclusion.parent`, but `parent` is the
entry point of the exclusion request (set to `data.mediaId`, which from the
show overview is always the show id) — not the structural parent. A typed
cascade set driven by `mediaServerId` of `type='show'`/`'season'` rows fixes
the regression without breaking the legacy null-type fallback.

* fix(collections): sort by addDate and group episodes by show (#2868)

* fix(collections): sort by addDate and group episodes by show

Maintainerr is now the source of truth for collection ordering: both the
Plex push and the UI fetch use the same comparator, so what users see in
the collection page matches what the media server displays.

- deleteSoonest now reads collection_media.addDate (drives the visible
  "Leaving in X days" overlay) instead of MediaItem.addedAt (the
  unrelated media-server library date)
- Same-day items tie via UTC day bucketing so the title tiebreaker
  actually fires within a "Leaving Today" group
- Title sort groups episodes/seasons under their show via
  grandparentTitle/parentTitle; movies are unaffected

* refactor(sort): pin missing values to end + DRY numeric branches

- Items missing the sort value (no air date, no rating, no view count, no
  add date) now sort to the end regardless of asc/desc. Previously they
  coerced to 0 and silently sorted to the front in ascending order — an
  item with no air date appeared before one from 1995.
- airDate, rating, watchCount, and deleteSoonest collapse onto one helper
  (compareNumericWithTitleFallback), removing three near-identical case
  bodies in compareMediaItemsBySort.
- airDate now day-buckets like deleteSoonest, so same-day items always
  reach the title tiebreaker instead of comparing by clock time.
- Pin tsBuildInfoFile in apps/server/tsconfig.build.json so nest-cli's
  type-check pass stops emitting a stray tsconfig.build.tsbuildinfo at
  the package root.

* refactor(sort): align deleteSoonest buckets with visible daysLeft

- Bucket deleteSoonest by `ceil((addDate - referenceTime) / dayMs)` so
  items showing the same "Leaving in X days" countdown tie even when
  their addDates straddle UTC midnight. Falls back to UTC-day bucketing
  when no reference time is supplied.
- Wire `referenceTime = now - deleteAfterDays * dayMs` through the two
  collection sort paths (applyCollectionSort + paginated fetch).
- Replace the show-aware title test data — old data alphabetized
  identically under either comparator and didn't actually prove the
  grouping behavior. New data interleaves episode titles across shows
  and asserts on [show, episode] pairs.
- Drop dead `baseUrl` + `paths` from apps/ui/tsconfig.json (unused alias)
  to clear the TS 6 deprecation surfaced in the IDE.

* perf(collections): restore SQL fast path for deleteSoonest paging

Page-loading a collection with `deleteSoonest` was hydrating every row
in the collection before slicing — minutes-long blocking page loads on
collections of a few hundred items, especially on Jellyfin where
`getMetadata` isn't cached at the adapter layer.

`deleteSoonest` orders by `addDate + deleteAfterDays`, but
`deleteAfterDays` is constant per collection, so the only sort key that
matters lives on `collection_media.addDate`. SQL can paginate it
directly without touching MediaItem metadata.

`applyCollectionSort` (the media-server push) still applies the
day-bucketed title tiebreaker via the comparator, so the polished
alphabetical-within-day order is what users see when browsing the
actual Plex/Jellyfin collection. The Maintainerr UI page may show
same-day items in a slightly different order — acceptable because the
primary sort key is correct and Maintainerr's DB remains the source of
truth driving the next push.

Other explicit sorts (airDate / rating / watchCount / title) still go
through hydrate-then-paginate because their sort keys live on
MediaItem, not on collection_media.

---------

Co-authored-by: enoch85 <mailto@danielhansson.nu>
@maintainerr-automation

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.11.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@enoch85 enoch85 added this to the 3.11.0 milestone May 12, 2026
doonga pushed a commit to greyrock-labs/home-ops that referenced this pull request May 13, 2026
…11.1 ) (#29)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/maintainerr/maintainerr](https://github.com/Maintainerr/Maintainerr) | minor | `3.10.1` → `3.11.1` |

---

### Release Notes

<details>
<summary>Maintainerr/Maintainerr (ghcr.io/maintainerr/maintainerr)</summary>

### [`v3.11.1`](https://github.com/Maintainerr/Maintainerr/blob/HEAD/CHANGELOG.md#3111-2026-05-12)

[Compare Source](Maintainerr/Maintainerr@v3.11.0...v3.11.1)

#### Highlights

- Fixed an issue where Jellyfin libraries with "Group films into collections" enabled caused BoxSet members to incorrectly toggle in and out of rule results ([#&#8203;2870](Maintainerr/Maintainerr#2870)).
- Improved error message for invalid Plex library section IDs to better guide users in resolving configuration issues ([#&#8203;2883](Maintainerr/Maintainerr#2883)).
- Enhanced custom collection UX by renaming tags for clarity and adding tooltips to explain collection handling options ([#&#8203;2882](Maintainerr/Maintainerr#2882)).

#### Fixes

- Validated Jellyfin IDs before refresh to prevent errors ([#&#8203;2853](Maintainerr/Maintainerr#2853)).
- Improved error message when Plex library section ID is invalid ([#&#8203;2883](Maintainerr/Maintainerr#2883)).
- Resolved Jellyfin collection add/remove loop for BoxSet items ([#&#8203;2870](Maintainerr/Maintainerr#2870)).
- Clarified custom collection terminology and added warnings for disabling collection handling ([#&#8203;2882](Maintainerr/Maintainerr#2882)).
- Added explicit token permissions to the Fider move job to address CodeQL findings.
- Added environment gate to mitigate TOCTOU vulnerability in the release\_pr workflow ([#&#8203;2879](Maintainerr/Maintainerr#2879)).
- Addressed transitive dependency vulnerabilities by adding Yarn resolutions for specific packages ([#&#8203;2881](Maintainerr/Maintainerr#2881)).

#### Dependencies

- Updated 10 dependencies, including notable packages: vite, typeorm, and [@&#8203;typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/eslint-plugin).

#### New Contributors

- [@&#8203;blixten85](https://github.com/blixten85) made their first contribution in [#&#8203;2881](Maintainerr/Maintainerr#2881)

### [`v3.11.0`](https://github.com/Maintainerr/Maintainerr/blob/HEAD/CHANGELOG.md#3110-2026-05-11)

[Compare Source](Maintainerr/Maintainerr@v3.10.2...v3.11.0)

#### Highlights

- Added support for force-processing overlays and gated reset operations against concurrent processing runs ([#&#8203;2827](Maintainerr/Maintainerr#2827)).
- Improved collection sorting: collections now apply sort order on save and synchronize with the media server ([#&#8203;2860](Maintainerr/Maintainerr#2860)).
- Enhanced storage metrics: potential reclaimable storage is now split into movie, show, season, and episode panels ([#&#8203;2854](Maintainerr/Maintainerr#2854)).

#### Breaking Changes

- None.

#### Features

- Added force-processing support for overlay operations and gated reset operations against concurrent processing runs ([#&#8203;2827](Maintainerr/Maintainerr#2827)).
- Improved storage metrics by splitting potential reclaimable storage into movie, show, season, and episode panels ([#&#8203;2854](Maintainerr/Maintainerr#2854)).

#### Fixes

- Fixed collection sorting to apply on save and synchronize with the media server ([#&#8203;2860](Maintainerr/Maintainerr#2860)).
- Resolved issue where excluding a single episode incorrectly excluded all episodes of the same show ([#&#8203;2867](Maintainerr/Maintainerr#2867)).
- Fixed storage metrics to merge shared volumes across hosts when byte-exact ([#&#8203;2852](Maintainerr/Maintainerr#2852)).
- Fixed Jellyfin retry ID check to align with pre-filter logic ([#&#8203;2853](Maintainerr/Maintainerr#2853)).
- Addressed issue where reclaimed bytes were not credited when `sizeBytes` was not yet cached ([#&#8203;2855](Maintainerr/Maintainerr#2855)).

#### Performance

- None.

#### Database migrations

- Added a new `mediaServerSort` column to the `collection` table to support media server-specific sorting.

#### Internal

- Added typed TanStack Query test helpers and migrated UI spec mocks to use typed builders ([#&#8203;2863](Maintainerr/Maintainerr#2863)).
- Added an architecture overview document detailing the monorepo structure, runtime flow, and core components ([#&#8203;2817](Maintainerr/Maintainerr#2817)).

#### Dependencies

- Updated 5 dependencies, including notable updates to TypeScript and typescript-eslint.

### [`v3.10.2`](https://github.com/Maintainerr/Maintainerr/blob/HEAD/CHANGELOG.md#3102-2026-05-08)

[Compare Source](Maintainerr/Maintainerr@v3.10.1...v3.10.2)

#### Highlights

- Fixed incorrect version comparison logic that caused update notifications to fail for multi-digit version segments ([#&#8203;2838](Maintainerr/Maintainerr#2838)).
- Improved storage metrics by deduplicating reclaimable bytes and adding per-type cleanup byte counters ([#&#8203;2833](Maintainerr/Maintainerr#2833)).

</details>

---

### Configuration

📅 **Schedule**: (in timezone America/New_York)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuNyIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19-->

Reviewed-on: https://git.greyrock.io/greyrock-labs/home-ops/pulls/29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants