Commits
b5f3331: [335] Extract Commonsense content-rating preview helpers (POC for Step 9) (#1679) (@chaz Larson)2985b39: Validate shared playlist_files on /autosave_library (#1678) (@chaz Larson)b74f9a5: Route playlist_files server errors back to their rows (#1677) (@chaz Larson)bd73d2e: [334] Extract shared library-files-editor subsystem (43 → 1 impl) (#1676) (@chaz Larson)e6d17f0: [333] Fix playlist row button order to match the other three kinds (#1675) (@chaz Larson)b0f51ff: [332] DRY the four build*FileRow builders in 025-libraries.js (#1674) (@chaz Larson)177c9ca: [331] Extract externalYamlEditor into modules/ (#1334 Step 9 direction) (#1673) (@chaz Larson)25aad76: [330] duplicate config v1 (#1672) (@bullmoose20)26612bc: updated readme (#1670) (@bullmoose20)dc86650: [329] import with anchors (#1669) (@bullmoose20)36e5e4d: [328] Validate fix for logscan (#1668) (@bullmoose20)a4c5417: [327] fix 404 (NOT FOUND) (#1667) (@bullmoose20)6a18239: [326] Preserve leading/trailing whitespace in Plex library name (#1665) (@chaz Larson)b97a7f4: [325] fix trimmed spaces and install persistence (#1666) (@bullmoose20)49af723: Bump ruff from 0.15.22 to 0.16.0 (#1661) (@dependabot[bot])0b5580a: [324] improve separator preview and green/red bars (#1663) (@bullmoose20)e58aeb9: [323] plex page fixes (#1660) (@bullmoose20)9c3fd4b: [322] v1 yml editor for collections, metadata, overlays, playlists (#1659) (@bullmoose20)147795e: [321] more details on separator id logic (#1658) (@bullmoose20)fa692df: [320] Route analytics log-keep reads through getAppConfig; add ESLint guard (#1657) (@chaz Larson)975bf0c: [319] added new grouping for mass_*_updates (#1656) (@bullmoose20)ffc4019: Bump actions/setup-python from 6 to 7 (#1642) (@dependabot[bot])351dc9c: Bump actions/setup-node from 6 to 7 (#1632) (@dependabot[bot])b3f1103: [318] fix for selarators with dropdowns (#1655) (@bullmoose20)c0fdfbc: [317] bars fixed (#1654) (@bullmoose20)2e034e9: [316] Bump gitpython from 3.1.52 to 3.1.55 (#1648) (@dependabot[bot])cb5a890: [315] Bump pre-commit from 4.6.0 to 4.6.1 (#1649) (@dependabot[bot])eeee177: [314] fix the emitted config (#1651) (@bullmoose20)018a6c3: [313] fixes for several issues (#1647) (@bullmoose20)45cfb62: [312] fixes for several warnings (#1645) (@bullmoose20)d16458b: [311] many fixes (#1643) (@bullmoose20)e34485c: [310] Fix mirror of content ratings (#1641) (@bullmoose20)415b122: [309] fixes (#1640) (@bullmoose20)f006de9: Bump ruff from 0.15.21 to 0.15.22 (#1639) (@dependabot[bot])c0004d9: [308] Bump gitpython from 3.1.51 to 3.1.52 (#1637) (@dependabot[bot])62cf44f: [307] Mirror button fix (#1638) (@bullmoose20)85f3c20: [306] logical groupings for overlays with ratings part 1 (#1636) (@bullmoose20)a22603f: [305] Fix analytics (#1635) (@bullmoose20)e37029c: [304] New env vars (#1634) (@bullmoose20)7a376fc: [303] Yamtrack (#1633) (@bullmoose20)7e08b4e: [302] Bump plexapi from 4.18.1 to 4.18.2 (#1624) (@dependabot[bot])a16dd06: [301] Bump gitpython from 3.1.50 to 3.1.51 (#1625) (@dependabot[bot])1dfcfbb: [300] added content rating (#1631) (@bullmoose20)fdd56b6: [299] organized the charts (#1630) (@bullmoose20)b060592: [298] aspect and resolution added (#1629) (@bullmoose20)4afabf2: [297] audio_language and subtitle_language added (#1628) (@bullmoose20)f2568c8: [296] Country region continent collection trmplate variables (#1627) (@bullmoose20)093b766: [295] Franchise based collectionless collection template variables (#1626) (@bullmoose20)4f42d57: [294] added director producer writer (#1623) (@bullmoose20)0e758e1: [293] added anioist myanimelist letterboxd (#1622) (@bullmoose20)3ae2452: [292] added tmdb trakt simkl (#1621) (@bullmoose20)c6a9c38: [291] added basic tautulli imdb charts (#1620) (@bullmoose20)aa14c86: [290] added award (#1619) (@bullmoose20)20104e3: [289] year and decade added (#1618) (@bullmoose20)1b2afed: [288] added genre other_chart and actor (#1617) (@bullmoose20)5d7c263: [287] Region studio network collection template variables (#1616) (@bullmoose20)e448fcf: [286] added seasonal (#1615) (@bullmoose20)3a7f80a: [285] added streaming (#1614) (@bullmoose20)9e59da3: [284] added and reorged universes (#1613) (@bullmoose20)711c51f: [283] added support for csv strings (#1612) (@bullmoose20)3b46647: [282] fixed (#1610) (@bullmoose20)5c7c7b6: [281] fixed arr persistence (#1609) (@bullmoose20)b555079: [280] fix kometaupdate js (#1608) (@bullmoose20)1d9ac97: Reshape PR template to make prominent (#1607) (@chaz Larson)0ecf20e: ESLint setup follow-up cleanups (closes #1345) (#1606) (@chaz Larson)e6c97ad: [279] Convert 4 namespace-object files to ES modules (#1346 finish) (#1605) (@chaz Larson)78bee4b: Bump ruff from 0.15.20 to 0.15.21 (#1604) (@dependabot[bot])b67cb9f: Update README for Step 4 shipped-image build wiring (#1600) (@chaz Larson)5bb5289: [278] fix 2 failing tests (#1603) (@bullmoose20)a156a75: [277] correct branch reporting from container runs (#1601) (@bullmoose20)99709e2: Wire npm build into PyInstaller release matrix (#1334 step 4 follow-up B) (#1599) (@chaz Larson)5e235c6: Wire npm build into Docker image (#1334 step 4 follow-up A) (#1598) (@chaz Larson)cb17d43: [276] Serve Vite-built assets in production with source fallback (#1334 step 4 activation) (#1597) (@chaz Larson)12dfce7: Activate Vite build in CI + fix auto-discovery bug (#1334 step 4) (#1596) (@chaz Larson)577aeee: [275] Remove step 2f compat shims and consolidate accordion tests (#1346 cleanup) (#1595) (@chaz Larson)6eac96f: [274] Extract separator/preview cluster (#1346 step 2f, fully decouples eventHandler <-> overlayHandler) (#1594) (@chaz Larson)b4bb0d9: [273] Migrate accordion-highlight callsites to direct imports (#1346 step 2f completion) (#1593) (@chaz Larson)033e4ba: [272] Extract accordion-highlight state to shared module (#1346 step 2f, unblocks Step 9) (#1592) (@chaz Larson)b7df4de: [271] Split 900-kometa.js part 29: extract prepare-state toggler (-20 lines) (#1591) (@chaz Larson)435a4a4: [270] Split 900-kometa.js part 28: extract run-status formatters (-40 lines) (#1590) (@chaz Larson)a33f6f9: [269] Split 900-kometa.js part 27: extract CLI flag catalog + label renderer (-134 lines) (#1589) (@chaz Larson)5b1d2cc: [268] Split 900-kometa.js part 26: extract logscan renderer + poller (-156 lines) (#1588) (@chaz Larson)e6fe069: [267] Split 900-kometa.js part 25: extract validation-display helpers (-109 lines) (#1587) (@chaz Larson)f64900f: Fix #1584: Sonarr wizard strands unvalidated users with invalid paths (#1586) (@chaz Larson)408aa66: [266] Roadmap Step 6 finish: extract arrPageBase.js from Radarr/Sonarr (#1585) (@chaz Larson)852e525: [265] Split 900-kometa.js part 24: extract run-progress panel (-324 lines) (#1583) (@chaz Larson)7d66f10: [264] Cleanup: remove dead sync-success path and fix logBox[0] scroll bugs (#1582) (@chaz Larson)fb24052: [263] Split 900-kometa.js part 23: extract callUpdateKometa (THE BOSS FIGHT) (#1581) (@chaz Larson)3cb85c3: [262] Split 900-kometa.js part 22: extract runKometaStatusPass (#1580) (@chaz Larson)46b59a8: [261] Split 900-kometa.js part 21: extract validateKometaRoot (#1579) (@chaz Larson)0c351dc: [260] Split 900-kometa.js part 20: extract probeKometaRoot (#1578) (@chaz Larson)4db50bf: [259] Split 900-kometa.js part 19: extract run-command section visibility (#1577) (@chaz Larson)361dfb7: [258] Split 900-kometa.js part 18: extract checkKometaUpdate (#1576) (@chaz Larson)05a2a78: [257] Split 900-kometa.js part 17: extract update-progress polling (#1575) (@chaz Larson)981bdb4: [256] Split 900-kometa.js part 16: extract update rollup badge + button label (#1574) (@chaz Larson)1beb738: [255] Split 900-kometa.js part 15: extract update-phase badge + status log (#1573) (@chaz Larson)13fe9fc: [254] Cleanup: move isRunCommandValid to _util.js; retire buildCommand callbacks-bag (#1572) (@chaz Larson)957d9f7: [253] Split 900-kometa.js part 14: extract run controls (Run Now + Recovery buttons) (#1571) (@chaz Larson)afeeacf: [252] Cleanup: retire syncKometaBranchRollupBadge callbacks-bag in _headerBadges.js (#1570) (@chaz Larson)ae92ed5: [251] Split 900-kometa.js part 13: extract Kometa branch/version management (#1569) (@chaz Larson)edcafd9: [250] Split 900-kometa.js part 12: extract generic UI helpers (tooltips + copy button) (#1568) (@chaz Larson)d49d9e4: [249] Split 900-kometa.js part 11: extract run-status sparklines (#1567) (@chaz Larson)c4b56fb: [248] Split 900-kometa.js part 10: extract remaining rollup badge functions (#1566) (@chaz Larson)f9f4d94: [247] Prep for 900-kometa.js splits: migrate 10 KOMETA_* flags to kometaState (#1565) (@chaz Larson)a05ce83: [246] Split 900-kometa.js part 8: extract run-command builder + active-command state (#1564) (@chaz Larson)d085e92: [245] Split 900-kometa.js part 7: extract runtime configuration readers to _runtime.js (#1563) (@chaz Larson)21f51ab: [244] Split 900-kometa.js part 6: extract validation gate + migrate showYAML to state (#1562) (@chaz Larson)21093a3: [243] Split 900-kometa.js part 5: extract header-style grid + fix 2 latent bugs (#1561) (@chaz Larson)73b685e: [242] Split 900-kometa.js part 4: extract pure header-badge helpers to _headerBadges.js (#1560) (@chaz Larson)9566b97: [241] Split 900-kometa.js part 3: extract polling handles to _state.js (foundational) (#1557) (@chaz Larson)b190c65: [240] Split 900-kometa.js part 2: extract maintenance-window helpers (#1556) (@chaz Larson)ed2b393: [239] Add startup preflight for missing stdlib C extensions (sqlite3, _ssl) (#1555) (@chaz Larson)61572e8: [238] Split 900-kometa.js part 1: extract pure util helpers to modules/kometa/_util.js (#1554) (@chaz Larson)32bd7a3: Vitest: cover EventHandler.attachLibraryListeners + confirm jQuery sweep clean (Step 8) (#1553) (@chaz Larson)a4c6ef9: Vitest: cover ImageHandler.getLibraryOverlays (Step 8 continued) (#1550) (@chaz Larson)d29cdf4: [237] fix the markers linewrap and unknown (#1552) (@bullmoose20)5162342: Vitest: cover eventHandler.js pure predicates + accordion highlighting (Step 8) (#1548) (@chaz Larson)ca809ec: [236] Fix: jQuery straggler .removeAttr() in 900-kometa.js breaks Final validation page (#1549) (@chaz Larson)b20466a: Vitest: cover imageHandler.js pure helpers + core methods (Step 8) (#1547) (@chaz Larson)7f241cd: Vitest: cover validationHandler.js (50 tests, Step 8 coverage push) (#1546) (@chaz Larson)0191164: [235] [234] Step 7: Remove jQuery entirely (kill the CDN dep) (#1545) (@chaz Larson)dd178de: [234] run marker fix part2 (#1544) (@bullmoose20)ac84a62: [233] [233] Step 7 Phase 2: Drop jQuery from 000-base.js (#1543) (@chaz Larson)3fa121f: [232] [232] Step 7 Phase 2: Drop jQuery from validationHandler.js (#1542) (@chaz Larson)26bc50a: [231] [231] Step 7 Phase 2: Drop jQuery from 900-kometa.js (#1541) (@chaz Larson)74e6e2a: [230] run marker fix part1 (#1540) (@bullmoose20)c45dc0e: [229] Step 7 Phase 2: Drop jQuery from 905-analytics.js + extract elementGroup helper (#1538) (@chaz Larson)839d768: [228] Step 7 Phase 2: Drop jQuery from 915-imagemaid.js (#1537) (@chaz Larson)12edbda: [227] Step 6: Extract createOauthValidator factory + migrate Trakt and MAL wizards (#1536) (@chaz Larson)c05c595: [226] Data-table refactor: 49 standard advisories -> Advisory records (follow-up to #1529) (#1535) (@chaz Larson)590095b: Extract confirm-flow validators + library-mapping validator (#1533) (@chaz Larson)12e91f8: Extract shared cache-load + preview-mapped report builders (#1534) (@chaz Larson)b00fb29: Extract Plex + TMDb credential validation from import_config_preview (#1532) (@chaz Larson)8216c35: Extract upload-bundle handling from import_config_preview (#1531) (@chaz Larson)bb38c3e: Extract shared helpers from import_config_routes (#1530) (@chaz Larson)3642a73: [225] Extract Phase 2 line-scan detector; drop dead current_year code (#1529) (@chaz Larson)e7e8bbf: [224] Extract build_advisory_messages to its own module (#1528) (@chaz Larson)ed8ecdf: [223] Sprint 5 kickoff: Extract issue-counts builder from recommendations engine (#1527) (@chaz Larson)5930bfb: [222] Split output_overlays.py into rating-slot and type-cleanup clusters (#1526) (@chaz Larson)d6e852f: [221] Extract rollups + step-status derivation from workspace_status.py (#1525) (@chaz Larson)e8cab97: Extract remaining 5 clusters from process_control.py (#1524) (@chaz Larson)ea11603: Extract remaining 5 clusters from process_control.py (#1524) (@chaz Larson)a67ec06: [220] Extract shared state + marker-file writers from process_control.py (#1523) (@chaz Larson)6b6ab10: [219] Extract process-metric calculators from process_control.py (#1522) (@chaz Larson)682bb12: [218] Extract service-connectivity validators from validations.py (#1521) (@chaz Larson)0958324: [217] Extract YAML file/folder validators from validations.py (#1520) (@chaz Larson)27c6d22: [216] Extract overlay-source-override image handling from validations.py (#1519) (@chaz Larson)226aa29: [215] Extract per-library service-override handling to importer_services (#1518) (@chaz Larson)22f3cae: [214] Extract per-library operations dispatch loop into importer_operations (#1517) (@chaz Larson)88e9a08: [213] Extract per-library settings block to importer_library_settings (#1516) (@chaz Larson)c5d296f: [212] Extract per-library metadata_files handling to importer_metadata (#1515) (@chaz Larson)6f89e14: [211] Extract per-library overlay_files handling to importer_overlays (#1514) (@chaz Larson)f57bb59: [210] Extract per-library collection_files handling to importer_collections (#1513) (@chaz Larson)b83d393: [209] Extract top-level simple-section handling to importer_simple_sections (#1512) (@chaz Larson)63dafe4: [208] Extract playlist config parser to importer_playlists (#1511) (@chaz Larson)a81f711: [207] Extract 3 library-operation handlers to importer_operations (#1510) (@chaz Larson)6497342: [206] Hoist LANGUAGE_WEIGHT_TEMPLATE_KEYS + 3 pure helpers out of prepare_import_payload (#1507) (@chaz Larson)9825576: [205] Extract import-time value coercion helpers to importer_value_coercion (#1506) (@chaz Larson)2efbaea: [204] Extract library-type inference to importer_library_types (#1505) (@chaz Larson)522a591: [203] Delete dead duplicate _coerce_import_bool + add regression test (#1504) (@chaz Larson)d07b1a0: [202] Extract YAML import-report annotation to importer_yaml_annotation (#1503) (@chaz Larson)964915a: [201] Extract incomplete-run resume machinery to logscan_incomplete_resume (#1502) (@chaz Larson)9549702: [200] Extract imagemaid analyzer + progress snapshot into focused modules (#1500) (@chaz Larson)b86b978: Implement retry logic for Docker manifest creation (#1501) (@chaz Larson)3ac305f: [199] Cross the finish line: extract remaining small helpers (Sprint 3 finale) (#1498) (@chaz Larson)526c812: [198] Extract recommendation post-processing helpers to logscan_recommendations_engine (#1497) (@chaz Larson)902a201: [197] Extract extract_progress to modules/logscan_progress_engine (#1496) (@chaz Larson)f756aaa: [196] Extract make_recommendations to modules/logscan_recommendations_engine (THE BIG ONE) (#1495) (@chaz Larson)1bbcc6a: [195] Extract library/section stats to modules/logscan_library_stats (#1494) (@chaz Larson)7f464dc: [194] Extract maintenance analysis to modules/logscan_maintenance (#1493) (@chaz Larson)4550bf5: [193] Extract content-parsing helpers to modules/logscan_content_extractors (#1492) (@chaz Larson)6219625: [192] Extract system-tuning recommendation builders to modules/logscan_recommendations (#1490) (@chaz Larson)1083545: [191] Extract finished-run parsing to modules/logscan_finished_runs (#1489) (@chaz Larson)e83f111: [190] Extract PMS version helpers to modules/logscan_pms_versions (#1488) (@chaz Larson)f133412: [189] Extract process_libraries_block; drop dead _EMPTY_OUTPUT sentinel (#1487) (@chaz Larson)ab215b4: [188] Extract emit_and_validate_config from build_config's final phase (#1486) (@chaz Larson)0c8a5c5: [187] Extract retrieve_config_sections into output_render (was inline in build_config) (#1485) (@chaz Larson)d390115: [186] Add LibrariesBundle.to_section_kwargs() to unpack for build_libraries_section (#1484) (@chaz Larson)4845fbb: [185] Extract build_libraries_section to modules/output_libraries_section (new module) (#1483) (@chaz Larson)0775a08: [184] Switch build_libraries_section to keyword args; drop 315 lines of test filler (#1482) (@chaz Larson)1437f37: [183] Extract ORDERED_CONFIG_SECTIONS and apply_final_transformations to new module (#1481) (@chaz Larson)4c903de: [182] Extract deferred playlist_files toggle orchestration into output_playlists (#1480) (@chaz Larson)a5295e7: [181] Extract library-data extraction into LibrariesBundle + new module (#1479) (@chaz Larson)f486262: [180] Extract playlist_files / webhooks / apprise normalizers into new module (#1478) (@chaz Larson)45614ab: [179] Extract render_yaml_header into modules/output_yaml_header.py (new module) (#1477) (@chaz Larson)ce0846f: [178] Extract group_by_library into modules/output_grouping.py (new module) (#1476) (@chaz Larson)635b7af: [177] Extract build_overlay_files_for_library + helpers.strip_library_suffix (#1475) (@chaz Larson)c3893ed: [176] Kill dead code: rating-pair cleanup loop is redundant after prune (#1474) (@chaz Larson)43d2c03: [175] Extract build_overlay_entries into modules/output_overlay_builder.py (new module) (#1473) (@chaz Larson)d276823: [174] Extract build_collection_files into modules/output_collections.py (#1472) (@chaz Larson)1cfed92: [173] Extract per-overlay-type cleanup + overlay_sort_key to output_overlays.py (#1471) (@chaz Larson)0d4828f: [172] Extract overlay_lookup_name + reorder_rating_template_vars into output_overlays.py (#1470) (@chaz Larson)6845b91: New optimizations tor gap analyser (#1467) (@bullmoose20)3043a0b: [171] Extract prune_rating_template_vars into modules/output_overlays.py (#1469) (@chaz Larson)48ab567: [170] Kill dead code: remove Content Rating + Original Title dedicated blocks (#1468) (@chaz Larson)8c8cb0c: [169] Whale carve #7: extract 3 walker loops (settings, ops, service overrides) - biggest single carve (#1465) (@chaz Larson)4099f6e: [168] Whale carve #6: extract build_grouped_mass_update_operations (17 ops in one loop) (#1464) (@chaz Larson)125ea3c: [167] Whale carve #5: extract build_template_variables + kill 6 redundant if-blocks (#1463) (@chaz Larson)1d64da0: [166] Whale carve #4: extract build_top_level_fields (#1462) (@chaz Larson)1d4818a: [165] Whale carve #3: extract 4 small ops (mappers, backup, poster+background) (#1461) (@chaz Larson)4f8f1c8: improve gap analyzer (#1466) (@bullmoose20)be45689: [164] Whale carve #2: extract build_mass_genre_update_operation (#1460) (@chaz Larson)69124c8: [163] First carve of the whale: extract build_delete_collections_operation (#1459) (@chaz Larson)ae81d70: [162] Extract dump_section (YAML serializer) into output_dump.py - output.py drops below 2000 lines (#1458) (@chaz Larson)6a567b8: [161] DRY: collapse 4 duplicate section-header renderers to one render_section_header call (#1457) (@chaz Larson)71acf6f: [160] Baby elephant down: extract reorder_library_section (with DRY collapse) into output_reorder.py (#1456) (@chaz Larson)64e1aaf: [159] First elephant down: extract optimize_template_variables → output_optimize.py (#1455) (@chaz Larson)6def268: [158] Sweep the floor: clean_section_data + _rewrite_custom_font_paths → output_postprocess.py (#1454) (@chaz Larson)2119394: [157] Extract section_heading + add_border_to_ascii_art from output.py (#1453) (@chaz Larson)a3a9158: [156] Move asset directory normalizers into output_values.py (#1452) (@chaz Larson)aecfe9e: [155] Move 2 collection-config walkers into output_collections.py + bonus DRY (#1451) (@chaz Larson)eec8b9f: [154] Extract collection/franchise template-var normalizers from output.py (#1450) (@chaz Larson)47f0214: [153] Extract + DRY the three file-block-entry parsers from output.py (#1449) (@chaz Larson)2288f90: [152] Move 4 playlist template-var normalizers into output_playlists.py (#1448) (@chaz Larson)99ff336: [151] Extract 9 defaults-discovery helpers from output.py to output_defaults.py (#1447) (@chaz Larson)7f34a90: [150] Extract 8 playlist helpers from output.py to output_playlists.py (#1446) (@chaz Larson)3489047: [149] Extract 10 value-coercion primitives from output.py to output_values.py (#1445) (@chaz Larson)cb581ab: Bump rojopolis/spellcheck-github-actions from 0.62.0 to 0.63.0 (#1443) (@dependabot[bot])19ff267: [148] Hoist 6 credential parsers out of import_config_preview (#1444) (@chaz Larson)5cb849c: Rename modules/helpers/_legacy.py to _constants.py (#1442) (@chaz Larson)619bab3: [147] Extract _named_config.py from _legacy.py; fix stale re-export shims (#1441) (@chaz Larson)5a5385e: [146] Extract _kometa_paths.py from _legacy.py (#1440) (@chaz Larson)6f66818: [145] Consolidate json-schema sync into _schema.py (#1439) (@chaz Larson)28e5afd: [144] Remove dead perform_kometa_update; move perform_quickstart_update to _qs_update.py (#1438) (@chaz Larson)24415ba: [143] Extract _plex.py from _legacy.py (#1437) (@chaz Larson)77e555d: [142] Extract _zip_update.py from _legacy.py (#1436) (@chaz Larson)eaccf0e: [141] Extract _logging.py from _legacy.py (#1435) (@chaz Larson)10fb8c5: [140] Playlist vars (#1434) (@bullmoose20)a916dec: [139] Extract _pid.py from _legacy.py (#1432) (@chaz Larson)4f8a108: [138] Extract _kometa_version.py from _legacy.py (#1431) (@chaz Larson)c1ff855: [137] Remove dead install mode functions from _legacy.py (#1429) (@chaz Larson)9b3ebe9: [136] fix aggressive cleanup (#1430) (@bullmoose20)8024ba7: [135] Fix Docker crash: wrap git import in try/except (#1428) (@chaz Larson)44f8a74: [134] Extract _update_cache.py from _legacy.py (#1426) (@chaz Larson)438a640: fixed tests (#1427) (@bullmoose20)44da910: Extract _update_cache.py from _legacy.py (#1425) (@chaz Larson)ad50b80: [133] Extract _qs_update.py from _legacy.py (#1424) (@chaz Larson)118df4d: [132] Extract _version.py from _legacy.py (#1423) (@chaz Larson)dbd266a: [131] Extract _schema.py from _legacy.py (#1418) (@chaz Larson)3e72921: [130] Bump pillow from 12.2.0 to 12.3.0 (#1420) (@dependabot[bot])ba3f994: [129] Fix xtra folders (#1422) (@bullmoose20)a9b502b: [128] Extra variables (#1421) (@bullmoose20)5dae0ce: [127] fixes based on 6 failing tests part 3 (#1419) (@bullmoose20)e64e663: [126] Extract _os.py from _legacy.py (#1416) (@chaz Larson)78268dc: [125] Fix tests (#1417) (@bullmoose20)8c1176c: [124] Extract _forms.py from _legacy.py (#1415) (@chaz Larson)391b4eb: [123] Extract _git.py from _legacy.py (#1414) (@chaz Larson)ccda706: [122] Extract _settings.py from _legacy.py (#1413) (@chaz Larson)f8eb454: [121] Extract _redact.py + _file_utils.py from _legacy.py (#1412) (@chaz Larson)a6813c8: [120] Extract _restart.py from _legacy.py (#1411) (@chaz Larson)36a3aac: [119] Extract _misc.py from _legacy.py (#1410) (@chaz Larson)0963233: [118] Extract _plex_cache.py from _legacy.py (#1409) (@chaz Larson)e90ab44: [117] Extract _artifacts.py from _legacy.py (#1408) (@chaz Larson)561308d: [116] Extract _fonts.py + _overlays.py from _legacy.py (#1407) (@chaz Larson)bae362f: Extract _fonts.py from _legacy.py (#1405) (@chaz Larson)d2753e5: [115] Extract _cli.py + _templates.py from _legacy.py (#1404) (@chaz Larson)bb78098: added npm install as part of --setup (#1402) (@bullmoose20)c17099b: added run_tests.py (#1401) (@bullmoose20)8db60f7: [114] Fix helpers package namespace drift (10 -> 0 pre-existing test failures) (#1400) (@chaz Larson)971ac36: Fix remaining pre-existing test failures (#1399) (@chaz Larson)89608d5: [113] Fix 8 pre-existing test failures (#1398) (@chaz Larson)ce16140: Consolidate linting — remove standard in favour of ESLint (#1397) (@chaz Larson)1473de5: [112] Export private helper functions for test compatibility (#1396) (@chaz Larson)88f6f74: [111] Decompose helpers.py into package (Step 3) (#1395) (@chaz Larson)7f61a45: [110] Convert 025-libraries.js to ES module; finish Step 2 (#1394) (@chaz Larson)e3536b0: [109] Convert overlayHandler.js to ES module; last helper conversion (#1393) (@chaz Larson)4b8aedf: [108] Convert eventHandler.js to ES module (#1391) (@chaz Larson)3dcce3a: [107] Languages overlays (#1392) (@bullmoose20)2df3070: [106] Convert imageHandler.js to ES module (#1390) (@chaz Larson)89ad977: [105] Convert validationHandler.js to ES module (#1389) (@chaz Larson)10007a7: [104] Convert rgbaPicker.js to ES module; add dynamic import() to 025-libraries.js loader (#1388) (@chaz Larson)1e4df12: [103] Convert 900-kometa.js to ES module (#1387) (@chaz Larson)0996cf2: [102] Convert 905-analytics.js to ES module; fix redirect-path template_uses_module bug (#1386) (@chaz Larson)d52cdd8: [101] Convert 915-imagemaid.js to ES module (#1385) (@chaz Larson)fe63b39: Tighten ESLint config; add regression-guard tests (#1384) (@chaz Larson)35bd1e0: [100] Restore window.jumpTo shim; fix regression from PR #1382 (#1383) (@chaz Larson)901d5f0: [99] Retire window.jumpTo / window.loading shims; CustomEvent test seam (#1382) (@chaz Larson)4487e4d: [98] Eliminate color-picker macro IIFEs (Group B) -- inline-handler sprint complete (#1381) (@chaz Larson)130836c: Bump actions/checkout from 6 to 7 (#1379) (@dependabot[bot])488a44e: Update playwright requirement from >=1.60.0 to >=1.61.0 (#1380) (@dependabot[bot])300debe: [97] Eliminate runtime-injected inline handlers + opt-in HTML helper (#1378) (@chaz Larson)ea10e76: [96] Eliminate inline navigation handlers via data-attributes (Group A) (#1377) (@chaz Larson)9a6025c: [95] Fix broken webhooks onchange + eliminate inline handlers (Group C) (#1376) (@chaz Larson)c034fa0: [94] Eliminate inline event handlers from Trakt + MAL templates (#1375) (@chaz Larson)1b40452: [93] Migrate Trakt + MAL to oauthValidationHelpers (#1334 Step 6 PR 4d - FINAL) (#1374) (@chaz Larson)a9777bd: [92] Migrate TMDB to createApiKeyValidator (#1334 Step 6 PR 4c) (#1372) (@chaz Larson)8bcab0e: Update gap analyser script (#1373) (@bullmoose20)0c8f762: [91] Migrate Plex to createApiKeyValidator (#1334 Step 6 PR 4b) (#1371) (@chaz Larson)303e4d5: [90] Migrate Radarr + Sonarr to createApiKeyValidator (#1334 Step 6 PR 4a) (#1370) (@chaz Larson)e27a8be: [89] Migrate 3 multi-field wizards to createApiKeyValidator (#1334 Step 6 PR 3) (#1369) (@chaz Larson)34531b7: [88] Migrate 4 simple wizards to createApiKeyValidator (#1334 Step 6 PR 2) (#1368) (@chaz Larson)c199fba: [87] Add createApiKeyValidator factory + migrate 060-mdblist (#1334 Step 6 PR 1) (#1367) (@chaz Larson)59f9bc0: Add Vitest coverage for 3 shared validation modules (#1334 Step 8) (#1366) (@chaz Larson)aefef89: [86] Drop jQuery from 16 wizard ES modules (#1334 Step 7 — Phase 1) (#1365) (@chaz Larson)51596d0: [85] Migrate front end to window.QS_AppConfig (#1334 Step 5, Phase B) (#1364) (@chaz Larson)dbb2f97: update run-tests.ps1 with -repocheck (#1361) (@bullmoose20)eed74b9: [84] Add GET /api/app-config endpoint (#1334 Step 5, Phase A) (#1358) (@chaz Larson)2008ef6: Add Vitest with jsdom and a first suite for validationPageBase.js (#1334 Step 8) (#1357) (@chaz Larson)fd5e82a: [83] Convert 001-start, 027-playlist_files, 100-anidb, 150-settings to ES modules (#1334 Step 2) (#1360) (@chaz Larson)d775c09: Add Vite scaffolding for the frontend build pipeline (PR for #1334 Step 4) (#1356) (@chaz Larson)77e526d: [82] Convert 14 simple wizard scripts to ES modules (PR 2b of #1346) (#1349) (@chaz Larson)29f0416: Exclude auto-managed PART file from pre-commit hooks (#1355) (@chaz Larson)8a42c75: [81] Extract shared validation helpers + convert base scripts and 080-gotify to ES modules (PR 2a of #1346) (#1348) (@chaz Larson)4ff6633: Pin black==26.5.1 and add a pre-commit hook to enforce it locally (#1354) (@chaz Larson)bed0b77: Bring tests/e2e/conftest.py in line with black format (#1353) (@chaz Larson)48b21e4: eslint_warning_cleanup_4 part 1 (#1352) (@bullmoose20)76bcd33: [80] Eslint warning cleanup 3 (#1351) (@bullmoose20)5e46722: [79] eslint_warning_cleanup_2 part 1 (#1350) (@bullmoose20)f07aa4e: [78] Eslint enablement (#1347) (@bullmoose20)1233390: Bump ruff from 0.15.19 to 0.15.20 (#1343) (@dependabot[bot])1d3b2bc: Bump actions/setup-node from 4 to 6 (#1342) (@dependabot[bot])64b4c37: Bump actions/cache from 4 to 6 (#1341) (@dependabot[bot])049b486: Bump docker/build-push-action from 6 to 7 (#1137) (@dependabot[bot])2e65fc1: Add ESLint for frontend globals (#1344) (@bullmoose20)2f6f5a5: Bump actions/checkout from 6 to 7 (#1287) (@dependabot[bot])e25a1ba: [77] enforce linter in github actions (#1340) (@bullmoose20)c312a3e: [76] ratings overides v1 (#1339) (@bullmoose20)8b082d6: [75] language and language subtitles overides (#1338) (@bullmoose20)2117445: [74] 5 overlays with text overlays (#1337) (@bullmoose20)21503ee: [73] Content rating overides (#1336) (@bullmoose20)2ee7c3d: [72] Fix two bugs found during test-matrix expansion (#1331) (@chaz Larson)58a84c6: Expand test matrix: +143 tests across 4 new test files (#1330) (@chaz Larson)7a7a54c: [71] Extract download routes + bundle/overlay-image helpers (PR G) (#1329) (@chaz Larson)5272021: [70] [69] Extract TMDb lookup helpers into modules/tmdb_lookup.py (PR H of quickstart.py refactor) (#1328) (@chaz Larson)87f592d: Extract ImageMaid runtime routes into blueprints/imagemaid_routes.py (PR F) (#1325) (@chaz Larson)8715c8c: [68] Direct play versions mediastinger ribbon and language count overides (#1327) (@bullmoose20)77d4450: [67] Extract /import-config/* routes into blueprints/import_config_routes.py (PR E of quickstart.py refactor) (#1324) (@chaz Larson)a5402ad: [66] Extract library-file-entry primitives into modules/library_file_entries.py (PR D of quickstart.py refactor) (#1323) (@chaz Larson)9b5b14a: [65] Extract library-page routes into blueprints/library_routes.py (PR C of quickstart.py refactor) (#1322) (@chaz Larson)54a76b5: [64] Extract workspace-status + dependency-reasons into modules (PR A of quickstart.py refactor) (#1321) (@chaz Larson)43fbfce: [63] Extract people-poster scanning into modules/logscan_people.py (6/6) (#1320) (@chaz Larson)f93ca80: [62] Extract Plex/header/run-command parsing into modules/logscan_command.py (5/6) (#1319) (@chaz Larson)c76c5b5: [61] Extract logscan progress/incomplete-run analysis into modules/logscan_progress.py (4/6) (#1318) (@chaz Larson)b45ed26: Streaming overlay advanced (#1317) (@bullmoose20)cf0739e: Bump ruff from 0.15.18 to 0.15.19 (#1316) (@dependabot[bot])822a499: [60] Resolution overlays override validations (#1315) (@bullmoose20)1418ade: [59] Extract ImageMaid log-content analysis into modules/logscan_imagemaid_analysis.py (3/6) (#1314) (@chaz Larson)2cbd8b6: [58] Extract logscan CLI/resume utilities into modules/logscan_resume.py (2/6) (#1313) (@chaz Larson)7aed08b: [57] Extract logscan cache/path primitives into modules/logscan_cache.py (1/6) (#1312) (@chaz Larson)947e20a: [56] Extract config management and test-libraries cloning into their own modules (#1311) (@chaz Larson)8b6579f: Fix platform-specific path separator bug in gap-analyzer test (#1310) (@chaz Larson)efa184b: [55] Extract process-control coordination into modules/process_control.py (#1309) (@chaz Larson)1169416: [54] Enhance gap analyzer (#1308) (@bullmoose20)0264ab7: [53] Extract ImageMaid settings/install management into modules/imagemaid.py (#1307) (@chaz Larson)f4e5a6f: [52] Extract Kometa root/install management into modules/kometa_install.py (#1306) (@chaz Larson)e5e43b5: [51] Extract asset management routes into blueprints/asset_routes.py (#1305) (@chaz Larson)00fcb8c: [50] Extract third-party service validation routes into blueprints/validation_routes.py (#1304) (@chaz Larson)b26af86: Serialize increment-build.yml runs to stop them racing on shared state (#1303) (@chaz Larson)ae5d1e7: [49] Extract background-jobs CRUD into modules/background_jobs.py (#1302) (@chaz Larson)e3f65e8: [48] Add ruff to pre-commit and fix existing lint violations (#1301) (@chaz Larson)0cd6170: [47] Run pytest in CI and fix tests broken on a fresh checkout (#1300) (@chaz Larson)801d9a1: Bump rojopolis/spellcheck-github-actions from 0.60.0 to 0.62.0 (#1298) (@dependabot[bot])4bfad8a: [46] Next additions (#1299) (@bullmoose20)a9b0dcd: [45] Fixes (#1297) (@bullmoose20)9860e70: [44] Next missing feature (#1295) (@bullmoose20)814df9a: [43] auto_sort_hubs library level (#1294) (@bullmoose20)45a80fb: [42] More features (#1293) (@bullmoose20)c84047b: [41] Template variables (#1292) (@bullmoose20)c63bc9f: [40] tmdb_birthday and title_format added (#1291) (@bullmoose20)cfe8cbb: [39] Next vars (#1290) (@bullmoose20)7376359: Update pytest requirement from >=9.1.0 to >=9.1.1 (#1288) (@dependabot[bot])3399fc0: [38] More vars (#1289) (@bullmoose20)2a5e11f: [37] More vars (#1286) (@bullmoose20)cf36c43: [36] Collection arr/automation shared keys (#1285) (@bullmoose20)44f37f7: update some tests (#1284) (@bullmoose20)0405551: [35] added additional files to sync (#1283) (@bullmoose20)fe29ec7: [34] add reset to collections (#1281) (@bullmoose20)0521f02: [33] Fix test results (#1280) (@bullmoose20)6a73a77: [32] Fix ignore ids (#1279) (@bullmoose20)5ffa219: [31] revert workaround (#1278) (@bullmoose20)761b2af: [30] fix for js regression (#1277) (@bullmoose20)c57f0ac: [29] Next vars (#1276) (@bullmoose20)261db7f: More template vars (#1275) (@bullmoose20)bf6e35b: Update pytest requirement from >=9.0.3 to >=9.1.0 (#1273) (@dependabot[bot])7322cca: [28] added overlay variables limit, list_days, list_size (#1274) (@bullmoose20)85eafdd: [27] added overlay variables (#1271) (@bullmoose20)fa0e9f7: [26] More library variabkes (#1270) (@bullmoose20)89976d3: [25] Fix tsts (#1268) (@bullmoose20)777fdce: [24] Fix order of use key (#1267) (@bullmoose20)c2c6e21: [23] more vars (#1266) (@bullmoose20)42eda40: [22] improved ui guidance (#1265) (@bullmoose20)0f1e505: [21] Another variable (#1263) (@bullmoose20)8c30298: [20] fix modals on settings page (#1262) (@bullmoose20)9dc0caf: [19] Update analyzer (#1261) (@bullmoose20)91756b3: [18] Add conffig analyser (#1260) (@bullmoose20)43f2ac9: [17] add include to collections v1 (#1259) (@bullmoose20)94cc50d: [16] fix menu (#1258) (@bullmoose20)7b9009b: [15] Reduce run confusion (#1257) (@bullmoose20)276d6dd: [14] fix for json error on fresh import (#1256) (@bullmoose20)f03e427: [13] Add languages template variable (#1255) (@bullmoose20)87b743f: [12] Add languages template variable (#1254) (@bullmoose20)ed69ebe: test fixed (#1253) (@bullmoose20)1eb9b17: [11] Fix regression on output (#1252) (@bullmoose20)cf5bce0: [10] Extend exclude feature (#1250) (@bullmoose20)092c653: [9] bundles refactor v3 (#1249) (@bullmoose20)079753c: [8] Order of accordions fix (#1248) (@bullmoose20)6e9a115: [7] the fix (#1247) (@bullmoose20)5b35c3f: [6] enhanced bundle v1 (#1246) (@bullmoose20)f939f9b: [5] add overlay_files: v1 (#1245) (@bullmoose20)bd763c8: [4] Scheduke overlays (#1244) (@bullmoose20)ae942c6: [3] fix-overlay-bootstrap-race (#1243) (@bullmoose20)287181b: [2] Per library arr settings (#1241) (@bullmoose20)41ef98f: [1] update kometa update flow v1 (#1240) (@bullmoose20)