= 2.59.09.32 =
* Remove the Secret constants, detailed Media Library Replacement lifecycle, source/build-process, and Varnish disclosure sections from `readme.txt` and `README.md`, while keeping the concise feature and setup documentation.
* Move the complete Installation and must-do post-install block in the WordPress.org `readme.txt` to immediately before Screenshots. Documentation-only release; dashboard Help, FAQ, cache, media, and optimization runtime behavior are unchanged.

= 2.59.09.31 =
* Remove the complete 80-question FAQ from `readme.txt` and `README.md`, keeping the concise installation and must-do post-install workflow in both repository documents.
* Move the same FAQ into the version-specific dashboard Help modal, organized into eight collapsed topic groups with individually expandable questions, counts, keyboard-native details controls, and matching UltraCache/Native theme styles. Dashboard documentation only; cache and optimization runtime behavior is unchanged.

= 2.59.09.30 =
* Add a concise must-do post-install JavaScript compatibility check to `readme.txt` and `README.md`: test the public site in a private browser window, copy Console errors, analyze them in JS Defer / Delay Safeguards & Diagnostics, append the proposed safeguards, save both lists, flush cache, and warm the front page until the Console is clear.
* Expand the version Help modal with the detailed browser-testing workflow, correct private-window shortcuts for Chrome/Edge and Firefox, guidance for Defer Instead versus Do Not Defer or Delay, and the exact cache flush/front-page warm-up loop. Documentation and dashboard-help release; cache and optimization runtime behavior is unchanged.

= 2.59.09.29 =
* Expand `readme.txt` and `README.md` with a practical, user-facing FAQ covering public page cache, wp-admin and logged-in Object Cache behavior, WooCommerce exclusions, query strings, warm-up, CSS/JavaScript/fonts, automatic and manual LCP learning, AVIF/WebP conversion, media queues, Media Library Replacement, object-cache backends/drop-ins, integrations, diagnostics, storage, cleanup, and support.
* Clarify that `/wp-admin/` is never page-cached while enabled Object Cache still accelerates dynamic administration requests by reusing cached queries, options, and WordPress objects. Documentation-only release; runtime cache and optimization behavior is unchanged.

= 2.59.09.28 =
* Add a fixed top-right `Rate us!` dashboard link that opens the UltraCache WordPress.org review form in a new tab. Keep the existing version-specific Help control fixed at the lower-right corner and apply matching Native/UltraCache theme styling and keyboard focus treatment to both controls.
* Add a final `Still having questions?` support callout inside the version Help modal with a direct `Ask on forums` link to the UltraCache WordPress.org support forum. Both external links use `noopener noreferrer`; cache, media, and optimization runtime behavior is unchanged.

= 2.59.09.27 =
* Remove the final generated selector `IN (...)` and `NOT IN (...)` SQL fragments from persistent LCP storage. Manual-selector page lookup now uses one fixed prepared page query followed by validated hash matching in PHP, preserving database ordering and exact selector selection without dynamic placeholders.
* Synchronize configured LCP selectors with fixed prepared statements: confirmed automatic mappings are staled in one bounded update when manual mode is active, while distinct manual/legacy-browser hashes are compared against the configured set and only removed hashes are updated. This clears the four remaining Plugin Check prepared-SQL findings without suppressions or raw SQL fragments.

= 2.59.09.26 =
* Refactor LCP Diagnostics counts, filters, search, refresh-status handling, and updated_at/id cursor pagination so every database sink receives a fixed SQL template prepared directly with allowlisted values. Remove the generic `$attention_sql`, `$count_sql`, `$row_sql`, and `$queue_query` execution paths that triggered the remaining Plugin Check prepared-SQL findings.
* Join the one matching `lcp_refresh` queue row into each bounded diagnostics page instead of issuing a generated `IN (...)` status query, and cache the cron-warm queue table-existence check through the shared UltraCache object-cache key. Preserve Attention/Confirmed/Pending/Stale/All tabs, 20/50/100 limits, exact aggregate counters, queue-state filters, row actions, and last-successful-refresh fallback.

= 2.59.09.25 =
* Refactor the browser-observed LCP storage and lifecycle database paths so `wpdb::prepare()` is applied directly at each `get_row()`, `get_results()`, and `query()` sink. Exact-row lookup, manual-selector lookup, automatic mapping lookup, viewport winner lookup, atomic observation upsert, competing-mapping staling, and selector synchronization no longer pass generic prepared SQL variables into database methods.
* Keep dynamic selector `IN` / `NOT IN` clauses limited to generated placeholder lists while every table identifier and runtime value remains bound through `%i`, `%s`, or `%d`. Preserve the existing self-healing table retry, automatic/manual precedence, pending-to-confirmed behavior, winner replacement, relearn/forget lifecycle, and targeted LCP refresh flow without changing the observations schema.

= 2.59.09.24 =
* Remove the unused runtime atomic-file writer that could create temporary sibling files for arbitrary targets. Runtime configuration no longer contains a dormant generic PHP-file replacement path; the existing guarded WordPress drop-in writer remains limited to `advanced-cache.php` and `object-cache.php`.
* Harden the shared guarded write helpers so generic file writes may create only the inert `index.php` directory marker with the exact `Silence is golden` payload, while generic renames reject every `.php` target. Managed cache drop-ins continue through the dedicated allowlisted drop-in writer.

= 2.59.09.23 =
* Move the Media Library Replacement schema-upgrade lock from direct `add_option()` calls to the shared `{prefix}ultracache_locks` table. Acquisition is atomic, expired locks can be taken over, release is token-guarded, the existing 60-second lifetime is preserved, and a still-active legacy option lock is respected while an expired legacy row is removed.
* Restore the plugin-wide invariant of zero direct `add_option()` calls and keep Media Library Replacement table creation serialized through the existing central lock subsystem.

= 2.59.09.22 =
* Remove conflicting `advanced-cache.php` and `object-cache.php` files immediately after the administrator confirms the existing Remove action. UltraCache no longer creates, returns, or references PHP backups for foreign cache drop-ins; removal remains restricted to those two exact WordPress content-directory paths through the existing capability-protected REST action and canonical WP_Filesystem drop-in helpers.
* Delete the obsolete `uploads/ultracache/cache/backups/dropins/` directory through the guarded UltraCache filesystem cleanup path and remove the empty parent backup directory when possible. Dashboard conflict text and confirmation now describe permanent removal instead of backup-and-remove behavior.

= 2.59.09.21 =
* Replace the fixed lower-right version label with a keyboard-operable `Help for [installed version]` button that opens a responsive, theme-aware setup modal. The modal contains the practical Aggressive-profile setup guide for compression, warm-up scope, image conversion, font optimization, WooCommerce, MailerLite, object cache, Varnish, scheduling, and the first cache/media preparation run; it closes by button, overlay, or Escape and restores focus to the trigger.
* Expand the WordPress.org `Installation` instructions and repository README with the same concise quick-setup workflow and direct users to the version-specific dashboard help modal.

= 2.59.09.20 =
* Enable `Warm affected pages after save` and `Apache Static HTML Delivery (.htaccess)` in the Aggressive performance profile. Applying Aggressive now turns on targeted post-save warming and direct Apache delivery of eligible prebuilt anonymous HTML cache files, while the individual controls remain available for manual adjustment.

= 2.59.09.19 =
* Move the complete browser-observed LCP diagnostics interface out of Advanced Diagnostics into its own full-width `LCP Diagnostics` accordion placed immediately above Advanced Diagnostics. The existing counters, server-side tabs, filters, pagination, mapping details, refresh/relearn/forget actions, and themed confirmation dialog remain unchanged; Advanced Diagnostics now contains only the remaining server, cache, storage, security, and runtime inspection panels.

= 2.59.09.18 =
* Scale LCP Diagnostics for large sites with server-side tabs, URL/selector/resource search, viewport/source/resource/refresh filters, 20/50/100-row limits, indexed updated/status/source/viewport ordering, and stable updated_at/id cursor pagination. Advanced Diagnostics now opens on Attention, loads only one bounded result page, reports exact aggregate counts including failed refreshes, keeps row actions within the active filters/page, and avoids rendering or transferring the full observations table even when thousands of URLs have learned mappings.

= 2.59.09.17 =
* Add automatic browser-observed LCP learning when no manual LCP selector is configured. The generic PerformanceObserver now records the actual text, image, background-image, or video-poster candidate per page and viewport; automatic candidates require two matching anonymous visits before confirmation, manual selectors continue to take immediate precedence, a confirmed browser winner suppresses further speculative LCP selection for that response, exact observed `<img>` resources receive eager/high-priority markup, image-backed candidates reuse the existing targeted purge and `lcp_refresh` warm queue, text candidates do not create image preloads, and diagnostics identify automatic versus manual sources while explicitly explaining that logged-in refreshes are ignored.

= 2.59.09.16 =
* Fix creation and use of the dedicated LCP observations table by adding `ultracache_lcp_observations` to the central validated UltraCache custom-table allowlist. The table name now reaches schema creation, existence checks, diagnostics, browser-observation writes, and lifecycle cleanup instead of being rejected as an invalid custom identifier.

= 2.59.09.15 =
* Add browser-observed LCP diagnostics to Advanced Diagnostics with persistent summary counts, recent mapping details, viewport/selector/element/resource metadata, observation history, current warm-refresh state, and the last successful page-specific LCP refresh. Add themed confirmation actions to forget a mapping, retain it as stale and relearn, refresh only the affected page cache, or open the public page; all mutations use a capability-protected REST endpoint, the existing targeted purge and LCP warm queue, and no full-site or CSS-bundle rebuild.

= 2.59.09.14 =
* Harden browser-observed LCP lifecycle handling: confirmed mappings no longer expire after seven days; removed or older competing selectors are retained as stale diagnostics while only one confirmed winner per page and viewport can emit a preload; observation, storage, and refresh queue entry share the page-cache eligibility decision; resource validation accepts trusted WordPress public content/uploads/theme/plugin hosts including CDN-rewritten base URLs; the observations table verifies its real existence and repairs/retries after an unexpected removal; and LCP refresh jobs received during a manual warm-up remain deferred in the existing queue and resume automatically when the manual session ends.

= 2.59.09.13 =
* Make the Image conversion test dialog and the Plugins-screen deactivation dialog follow the per-user UltraCache admin theme selection instead of hard-coded dark colors or the operating-system color scheme. The dashboard modal now consumes the existing theme tokens and updates with an open-theme change; the deactivation dialog receives the stored admin theme through its localized configuration and applies matching native/UltraCache surfaces, text, borders, controls, focus states, and responsive actions.

= 2.59.09.12 =
* Store browser-observed LCP mappings in the dedicated `{prefix}ultracache_lcp_observations` table instead of one expiring transient map. The table keeps one confirmed mapping per normalized page URL, exact manual selector, and viewport; uses atomic observation-count updates, indexed page/resource lookups, bounded retention cleanup, lazy schema creation for active-plugin updates, activation-time creation, and complete uninstall/Delete All cleanup. No transient-data migration is included.

= 2.59.09.11 =
* Connect browser-observed LCP learning to the existing database-backed cron warm queue: changed page/selector/viewport mappings now purge only the affected page-cache variants while preserving generated CSS bundles, enqueue a priority lcp_refresh job, force-refresh all active page-cache buckets without rebuilding CSS bundles, avoid full-site crawl expansion for standalone LCP refreshes, de-duplicate pending URL refreshes, and apply a bounded retry cooldown to prevent repeated slider-driven purge/warm loops.

= 2.59.09.10 =
* Extend Delay icon fonts to matching same-origin stylesheets inserted dynamically after the initial HTML. UltraCache now holds the stylesheet on print media, patches its @font-face rules with font-display: swap before activation, restores the original media value, preserves the stylesheet's existing load callback, honors the visible include/exclude patterns, and exposes measured matching/patching cost through window.ultracacheIconFontDelayTiming and a DevTools User Timing entry.

= 2.59.09.09 =
* Keep SVG uploads unchanged when upload conversion is enabled: image/svg+xml files now bypass raster resize and AVIF/WebP encoding without producing or deleting the uploaded file.
* Improve Delay icon fonts discovery and matching: front-page HTML icon-family class tokens such as material-icons are included in scanner results, and visible include/exclude patterns match font-family and font-file names across spaces, hyphens, and underscores (for example material-icons, Material Icons, and MaterialIcons-Regular).

= 2.59.09.08 =
* Separated manual LCP element targeting from resource priority: selectors are preserved exactly, direct text targets act only as LCP boundaries, direct image/background/poster resources receive priority without descendant guessing, and dynamic targets learn their actual browser-observed resource per page and viewport for the next cached response. Added a generic PerformanceObserver helper, page-scoped HMAC/rate-limited observation storage with targeted cache purge, verified-resource preload injection including SVG, and restored the missing generic tag-processor candidate extractor.
* Kept Priority Preloads, request-chain delay entries, and CSS async exclusion lists editable while their runtime switches are off; stopped adding implicit ID/class prefixes to manual LCP selectors, accepted SVG throughout LCP discovery/preload/runtime matching, removed the SR7-specific module-background shortcut, and stopped anonymous inline scripts from being delayed by third-party content-pattern matching.
* Made the JS Defer / Delay and CSS Bundle safeguard diagnostics full-width dashboard sections, and moved update-triggered frontend purge execution into its own operation-focused engine trait without changing behavior.
* Added separate, profile-enabled purge controls for successful WordPress core, active plugin, and active parent/child theme updates; update purges invalidate page HTML and frontend asset maps once per operation, optionally flush configured external page caches and start the existing warm queue, while leaving object cache and optimized media untouched.
* Reorganized the dashboard so Query-string Args Caching sits directly below Cache Engine and Warm Cache, while JS and CSS safeguard diagnostics sit directly beneath their related frontend optimization panels; setting IDs and runtime behavior are unchanged.
* Documented the trusted internal media-replacement dependency exception for Plugin Check without changing runtime behavior.
* Added Media Library Replacement to promote verified AVIF/WebP rewrite variants into WordPress attachment originals and generated sizes, with attachment metadata, database-reference, and Theme CSS updates.
* Added a resumable, server-authoritative Check / Prepare / Do / Verify / Delete Originals workflow with persisted progress, pause/resume/retry, cross-browser recovery, concurrency leases, time budgets, and explicit destructive confirmations.
* Added readiness and pre-write validation that blocks mutation when generated destinations, attachment candidates, output policy, registry plans, database scans, or Theme CSS baselines are incomplete or have changed.
* Added guarded, idempotent verification and original cleanup, plus recovery foundations for metadata, database references, Theme CSS, and interrupted replacement stages.
* Added database-wide media-reference indexing and matching for the current WordPress table prefix, including serialized/JSON validation, deduplication, verification, bounded keyset cursors, and WP-CLI access through the same replacement engine.
* Added separate Image Output Format and Fallback Format controls plus a shared Image compression level for AVIF/WebP optimization, upload generation, regeneration, conversion tests, and Media Library Replacement.
* Added sample image conversion comparisons, registered intermediate-size coverage, exact reuse of matching existing variants, and opt-in regeneration of already optimized images with current quality settings.
* Improved the media dashboard workflow, long-job progress UI, queue repair/recount controls, status reporting, and reliable handling of interrupted or concurrently opened operations.
* Added and strengthened SQLite object caching, then refactored Redis, APCu, SQLite, Disk, and runtime-only behavior into explicit backend classes while preserving the WordPress object-cache API.
* Refactored large plugin components into smaller operation-focused files for media, settings, diagnostics, JavaScript, LCP, fonts, CSS bundles, warm-up, REST/profiling, lifecycle, server rules, and shared core helpers.
* Added targeted class loading and lazy component loading to reduce initial PHP parsing while preserving WordPress-compatible bootstrap order, hooks, REST, WP-CLI, and public APIs.
* Added deactivation and uninstall cleanup policies to the standard Plugins screen, with controlled retention or removal of settings, custom tables, runtime/cache files, and plugin-owned data.
* Fixed Apache Static HTML Delivery rule synchronization and aligned dashboard, Help, Diagnostics, and translation text with the existing query-string allowlist behavior.
* Hardened filesystem/path containment, table scope, confirmation tokens, capabilities, nonces, serialized-data handling, generated-file validation, permissions, and destructive cleanup guards.
* Updated WordPress.org metadata, translations, diagnostics, REST/WP-CLI parity, compliance-sensitive code paths, and release packaging.

= 2.59.07.61 =
- Route real upload conversion through the existing UltraCache AVIF/WebP encoder chain instead of using WordPress image-editor AVIF saves for final output. WordPress image-editor use is now limited to resizing the intermediate source when the configured maximum upload side requires it.
- Add a specific Convert new uploads help tooltip without fallback language; this control converts the uploaded attachment itself and reports encoder failures visibly.

= 2.59.07.60 =
- Move Maximum upload image side to Advanced settings and keep Convert new uploads at the end of the AVIF / WebP Batch Conversion box.
- Rename Generate on Upload to Rewrite on upload in the media settings UI.
- Make upload conversion failures self-diagnostic: the visible WordPress upload error now includes source file, detected/target MIME, editor class, destination filename, save return data and candidate output-file validation state.
- Validate the actual file written by the WordPress image editor from multiple WordPress save-result candidates before reporting a missing output file.

= 2.59.07.59 =
- Fix upload conversion output validation so successful WebP/AVIF saves are measured through the UltraCache filesystem helper before falling back to WordPress filesize helpers.
- Add debug context when upload conversion save validation fails after the image editor reports success.

= 2.59.07.58 =
* Adds real new-upload image conversion controlled from the AVIF / WebP Batch Conversion panel. When enabled, WordPress uploads are converted to the selected Image Output Format during the normal upload flow.
* Adds Maximum upload image side with a default of 1920. Larger uploaded images are resized proportionally before WebP/AVIF save; smaller images keep their dimensions and are only converted.
* Uses WordPress upload and image editor APIs for the new upload conversion path. Conversion failure returns a visible upload error instead of silently keeping the original file or switching format.

= 2.59.07.57 =
- Fixed manual warm-up handling so frontend loopback `write-failed` headers no longer stop a cacheable 200 HTML page from being written by the controlled manual warm-up flow.
- Fixed skipped manual warm-up URLs so REST 200 `skipped` payloads are shown as skipped instead of raw `/crawl-page` failures in the admin progress log.
- Simplified manual warm-up progress messages to report user-facing outcomes such as Cached, Cached + CSS, Skipped, or Failed instead of cache-file counts or internal CSS/HTML ordering details.

= 2.59.07.56 =
- Kept the six manual warm-up actions distinct by scope and mode while tightening the manual warm-up completion contract: HTML-only actions do not trigger automatic CSS bundle preparation, and HTML + CSS actions keep CSS bundle work inside the manual session.
- Changed manual crawl-page handling so non-200, empty, non-HTML, or cache-rejected URLs are marked as skipped without REST 500 retries, preventing repeated self-requests for the same failing URL.
- Moved per-page CSS bundle preparation until after the URL proves it returns cacheable HTML, preventing CSS scans for 404/feed/non-HTML URLs, and added in-session canonical URL de-duplication for manual warm-up runs.

= 2.59.07.55 =
- Added explicit Cache Engine wording for post-save warming as “Warm affected pages after save” and kept it disabled by default.
- Changed post-save warming so it warms only scoped affected URLs instead of using site-front/feed seed URLs from the broader purge helper.
- Skipped autosaves, revisions and auto-drafts for post-save warming, added a per-post cooldown, filtered feed URLs from that path, and prevented post-save warm requests from auto-starting CSS bundle scans or media-variant bucket loops.

= 2.59.07.54 =
* Add a General Inclusions accordion below General Exclusions and move Manual LCP selector, Priority Preloads, and Delay Non-Critical Request Chains into it.
* Rename the delayed font pattern list to Delay These Fonts / Icon Font and clarify that it can match any chosen font, while commonly being used for icon fonts.

= 2.59.07.53 =
* Split matching delayed icon-font @font-face blocks out of the generated font-mix CSS bundle so text/font-mix CSS can remain blocking while icon-font CSS is emitted through the delayed icon-font stylesheet path.
* Reuse the existing Delay icon fonts pattern list during font-mix bundle consolidation and keep the bundle replacement atomic when the delayed companion stylesheet is written.

= 2.59.07.52 =
* Add first-party and third-party parallel execution controls for frontend deferred and delayed JavaScript.
* Apply the parallel execution flags to native defer/async conversion and to delayed JavaScript lane replay.
* Keep ordered execution as the default for both JavaScript paths.

= 2.59.07.51 =
* Reworked the delayed JavaScript loader so non-third-party delayed scripts run first in their own ordered lane before delayed analytics, consent, embeds, and other third-party scripts.
* Released the jQuery-ready hold after the first-party lane instead of waiting for delayed third-party scripts, preventing third-party consent/analytics code from leaving basic frontend interactions inactive.
* Added per-script timeout/fail-forward handling for delayed external scripts so missing load/error events cannot leave a delayed lane active indefinitely.

= 2.59.07.50 =
* Hardened TranslatePress page-cache compatibility so the translated-output buffer only runs for frontend HTML GET/HEAD requests.
* Skipped the TranslatePress compatibility buffer for admin, AJAX, REST, cron, CLI, JSON, feed, robots, sitemap, WooCommerce AJAX, and other non-HTML request contexts.
* Kept the existing translated-HTML storage timing and UltraCache internal query-argument cleanup unchanged, including internal revalidation requests that generate public cache HTML.

= 2.59.07.49 =
* Fixed TranslatePress compatibility so UltraCache internal revalidation query arguments are stripped from cached frontend URLs before HTML is stored, preventing public language-switcher links such as /en/... from retaining ultracache_revalidate or ultracache_rt parameters.

= 2.59.07.48 =
* Fixed TranslatePress page-cache storage so translated URLs are cached after TranslatePress finishes its frontend output-buffer translation, preventing alternate-language URLs from storing or serving the default Greek HTML.
* Kept the normal non-TranslatePress cache path unchanged; the compatibility buffer is only activated on frontend page-cache requests when TranslatePress is detected.

= 2.59.07.47 =
* Replaced the SQLite WAL-size selector with an automatically saved maximum SQLite database-size selector using 32, 64, 128, 256, 512, 1024, and 2048 MB choices; the default is 256 MB.
* Enforced the selected main SQLite database-file limit with `PRAGMA max_page_count` and added an automatic disposable-cache rebuild when a reduced limit is below the current file size.
* Added proactive SQLite capacity maintenance that removes expired entries first and then the oldest cache entries when used pages reach 90% of the selected limit, targeting 80% after cleanup.
* Separated WAL maintenance from the user database-size setting with a 16 MB post-checkpoint retention target, 1000-page automatic checkpoints, and a non-blocking cross-process maintenance lock.

= 2.59.07.46 =
* Added an automatically saved SQLite WAL target-size selector with 32, 64, 128, 256, 512, 1024, and 2048 MB choices; new and invalid configurations default to 256 MB.
* Applied the selected SQLite WAL target consistently to the generated object-cache drop-in, SQLite runtime configuration, and WAL checkpoint maintenance threshold.

= 2.59.07.45 =
* Fixed SQLite object-cache write lockout when the WAL file exceeded its maintenance target, while retaining a hard combined database and journal size cap.
* Preserved failed SQLite add attempts in request-local cache without falsely reporting persistent success, preventing repeated `alloptions` database reloads during backend write failures.
* Verified SQLite set operations changed persistent storage before reporting success.

= 2.59.07.44 =
* Added a user-controlled stale-worker circuit-breaker threshold under Queue Missing Media During Page Generation, validated as a positive integer and stored in the existing UltraCache settings option.
* Moved the Media Worker Safety status below the related missing-media queue controls.
* Reworked rolling stale-worker tracking to use bounded time buckets plus the latest 25 diagnostics, allowing large thresholds without storing one full option record per incident.
* Preserved the stale-worker count and latest quarantine diagnostics that opened a global pause until an administrator explicitly resumes media generation.
* Fixed PHP 8.4 nullable-parameter deprecation warnings in font CSS rewriting and the object-cache REST endpoint.

= 2.59.07.43 =
* Removed the top divider from the Media Worker Safety summary.

= 2.59.07.42 =
* Changed: Added an always-visible, compact five-line Media Worker Safety summary directly below the existing optimized-image, media-queue, and queue-health statistics. No separate dashboard card was added.
* Changed: The summary reports the current safety status, recent stale-worker incidents against the rolling threshold/window, remaining cooldown, latest quarantined attachment and timestamp, and the automatic queue action.
* Changed: Removed duplicated incident counts and cooldown timing from the background-control helper text; detailed state now has one stable location in the media summary.

= 2.59.07.41 =
* Replaces the one-strike global media pause with a per-item quarantine: a stale `processing` row becomes `failed`, remains excluded from automatic retries, and can be returned explicitly through Retry Failed.
* Adds a three-minute quiet-period cooldown after each stale worker so the previous PHP process has time to terminate before another media worker may start.
* Tracks stale-worker incidents in a rolling 30-minute window. The global media circuit opens only after three incidents in that window; the threshold, window, and cooldown remain filterable through `ultracache_media_stale_worker_threshold`, `ultracache_media_stale_worker_window_seconds`, and `ultracache_media_stale_worker_cooldown_seconds`.
* Rejects signed loopback workers, cron workers, automatic dispatch, and dashboard conversion while the cooldown is active, while preserving a single delayed cron continuation for automatic recovery.
* Clears rolling incident history only on an explicit administrator resume, preventing an accidental request from silently resetting the global safety threshold.
* Exposes cooldown time, recent incident count, threshold, and quarantined-item diagnostics in media queue state; the dashboard disables manual conversion during cooldown and shows the remaining quiet period.
* Adds uninstall cleanup for the new bounded stale-worker state option.

= 2.59.07.40 =
* Prevents a stalled media encoder from exhausting PHP-FPM by failing closed when a media queue claim exceeds its processing lease instead of automatically recycling the row to `pending`.
* Opens the persistent media background circuit breaker, clears the watchdog cron event, preserves bounded stale-item diagnostics, and requires an explicit administrator resume before any further automatic media work can start.
* Blocks immediate, cron, on-demand, and dashboard dispatch while another media queue row is still `processing`, so an expired dispatcher lock cannot create a replacement worker beside a potentially live PHP process.
* Stops self-chaining HTTP workers after each successful unit; the next bounded unit is scheduled through one delayed cron event instead.
* Makes queue completion claim-safe by requiring the original status, attempt number, and start timestamp before a worker may persist its result, preventing a delayed worker from overwriting a circuit-breaker or newer claim state.
* Treats an expired media processor lock as lost ownership and prevents the expired owner from finalizing queue state.
* Replaces the on-demand affected-page select-then-insert sequence with an atomic upsert, removing the confirmed duplicate-key race under concurrent frontend discovery.

= 2.59.07.39 =
* Prevents authenticated dashboard requests from causing false `DONOTCACHEPAGE` failures during manual warm-up.
* Honors each frontend loopback response so a URL that genuinely bypasses page cache fails independently while the remaining warm-up queue continues.

= 2.59.07.38 =
* Manual dashboard warm-up now bypasses the existing UltraCache page cache and atomically replaces each cache entry after successful generation.
* Authenticates internal force-refresh requests and bypasses Apache static delivery for those requests.

= 2.59.07.37 =
* Gives manual full-site and menu warm-up priority by stopping and clearing the cron warm queue before the dashboard crawler starts.
* Blocks cron warm starts, ticks, and scheduled cache cleanup while a manual warm-up is active or paused, and releases the block after completion or cache-generation reset.
* Persists authenticated manual warm-up ownership across pause and resume so scheduled cleanup cannot start a competing cron crawler.

= 2.59.07.36 =
* Fixes false Brotli detection in the HTML compression capability probe and restores Gzip selection when the server does not provide compression.

= 2.59.07.35 =
* Makes the HTML compression probe use an HTML response and forces the selector to Server managed when server-level Gzip or Brotli is detected.
* Hardens the SQLite object-cache backend with atomic add/replace/counter operations, persistent write-result handling, restrictive storage permissions, storage limits, secure deletion, and public-access verification.
* Restricts Apache static HTML delivery to trusted site hosts and applies quality-aware `Accept-Encoding` negotiation to the advanced-cache delivery path.
* Resolves the reported Plugin Check findings in the AVIF self-test and SQLite object-cache manager.

= 2.59.07.34 =
* Removes environment-specific deployment references from public release documentation.
* Keeps release history exclusively in `changelog.txt`; `readme.txt` now contains only plugin information and usage documentation.

= 2.59.07.33 =
* Fixes the WordPress early-hit page-cache path so it serves available Brotli or Gzip variants according to the request `Accept-Encoding` values.
* Sends matching `Content-Encoding` and `X-UltraCache-Encoding` headers for compressed early cache hits.

= 2.59.07.32 =
* Probes server-managed compression and PHP Gzip/Brotli support before opening the HTML Compression selector, then enables only the supported choices.
* Adds compressed Apache static HTML aliases with matching `Content-Encoding`, `Vary`, and UltraCache source headers.
* Clears the existing HTML page cache when compression or Apache static delivery mode changes so new aliases are rebuilt consistently.

= 2.59.07.31 =
* Shows Redis, APCu, SQLite, and Disk in one row on desktop, two columns on tablet, and one column on mobile.
* Expands the SQLite backend test with explicit Write, Read, Delete, and Expiration results in the Object Cache status panel.

= 2.59.07.30 =
* Adds SQLite as a fourth selectable WordPress object-cache backend for single-server sites with the PHP SQLite3 extension.
* Implements persistent signed-payload storage with WAL mode, expiration, global groups, multisite isolation, group flush, full flush, and bounded cleanup of expired entries.
* Adds SQLite availability, version, journal mode, entry count, storage size, read/write testing, fallback selection, profile auto-detection, and dashboard flush controls.
* Stores the database in the protected UltraCache object-cache directory and keeps SQLite database, WAL, and shared-memory files intact when the Disk backend is flushed.

= 2.59.07.29 =
* Removes six unreachable functions from `includes/admin/js/app.js`: the unused Cache Analytics card, committed-settings reset helper, asynchronous action-state helper, duplicate CSS bundle scope accessor, obsolete Safe Defer toggle helper, and the unrendered latest-profile JS safety loader.
* Removes the matching unreachable debug-profile handler, state, and prop plumbing from `includes/admin/js/diagnostics.js`. Browser Scanner, Runtime Scan, Console Error Handler, DB-backed diagnostic queues, and their visible controls remain unchanged.
* Removes 22 unused module imports from `includes/admin/js/app.js`, including obsolete profile/list helpers, unused UI primitives, diagnostic utilities, and cache-format helpers. This reduces accidental cross-module coupling and makes missing dependencies easier to detect during future changes.
* Narrows the internal `window.UltraCacheAdmin` export surfaces by removing 32 helpers/constants/components that have no consumer outside their defining module. Internally used helpers remain private and keep the same implementation; consumed exports and module names are unchanged.
* Keeps `includes/admin-dashboard.js` as the same 12-line bootstrap and retains the deterministic WordPress script/style dependency order established by the refactor.

= 2.59.07.28 =
* Stabilizes the per-user dashboard theme system introduced in 2.59.07.27 without changing frontend optimization, cache behavior, media conversion, warm-up, REST payloads, performance settings, or the saved theme values.
* Adds semantic `uc-dashboard-header` and `uc-dashboard-header-actions` classes to the existing header composition so responsive theme controls can be styled without relying on broad utility-class selectors. The title, description, toggle, and Flush All Cache action remain in the same order and use the same callbacks.
* Improves the `UltraCache Theme` control accessibility: the visible text is now a real label bound to the checkbox, the checkbox exposes switch semantics through `role="switch"` and `aria-checked`, the saving state is exposed through `aria-busy`, and the decorative slider is hidden from assistive technology.
* Guards the theme toggle callback before invoking it, preserving the current optimistic save/rollback behavior while preventing an avoidable runtime failure if the component is ever rendered without an `onChange` callback.
* Completes the native and UltraCache admin canvas backgrounds across `#wpcontent`, `#wpbody`, and `#wpbody-content`, avoiding uncovered strips around the dashboard when switching themes or using narrower wp-admin layouts.
* Adds explicit `color-scheme` values for native and UltraCache modes so browser-rendered controls and scrollbars follow the active light/dark dashboard appearance consistently.
* Stabilizes the header action layout: controls stay aligned on desktop, occupy the available width on WordPress mobile breakpoints, and preserve the existing full-width mobile button behavior without changing the rest of the dashboard flex/grid rules.
* Adds keyboard-visible focus styling specifically for the theme switch and adds a scoped `prefers-reduced-motion` rule for dashboard transitions and animations. Mouse interaction and the existing visual themes remain unchanged.

= 2.59.07.27 =
* Adds the per-user UltraCache dashboard theme system after the JavaScript and CSS refactor, without changing frontend optimization, cache, media, warm-up, object-cache, Varnish, or external-cache behavior.
* Makes the WordPress-native dashboard appearance the default for users who have not selected a theme. The existing dark UltraCache appearance remains available unchanged through the new `UltraCache Theme` toggle beside `Flush All Cache`.
* Stores the preference per administrator in the `ultracache_admin_theme` user-meta key (`native` or `ultracache`). The preference is not stored in the shared performance settings and does not trigger a settings save, cache purge, warm-up, or frontend change.
* Adds the authenticated `POST /ultracache/v1/admin-theme` REST route. It accepts only `native` or `ultracache`, uses the existing `manage_options` permission check and REST nonce, and returns the persisted theme.
* Removes the per-user theme meta during full settings/data uninstall cleanup while preserving it when the selected uninstall policy explicitly keeps settings.
* Adds `includes/admin/js/theme.js` for theme normalization, immediate root/body theme application, optimistic per-user saving with rollback on REST failure, and the compact header toggle component.
* Adds `includes/admin/css/themes.css` as the final style layer after tokens, foundation, components, and sections. Native mode uses WordPress admin surfaces, borders, form controls, buttons, admin color variables, notices, menus, modals, and scrollbars while UltraCache mode retains the current design.
* Renders the saved `data-uc-theme` value and matching admin body class server-side before React mounts, preventing a dark-to-light flash on native mode. JavaScript keeps the root attribute and body class synchronized when the toggle changes.
* Adds the explicit `ultracache-admin-theme` script handle and `ultracache-admin-css-sections` style handle while preserving the final public `ultracache-admin-css` handle.

= 2.59.07.26 =
* Splits the former 1,711-line `includes/admin-dashboard.css` into four ordered stylesheets under `includes/admin/css/`: `tokens.css`, `foundation.css`, `components.css`, and `sections.css`.
* Keeps the complete CSS rule stream byte-for-byte identical when the four files are concatenated in dependency order. No selector, declaration, media query, specificity, or cascade order is changed in this release.
* Preserves the public WordPress style handle `ultracache-admin-css`. It now points to `sections.css` and depends on `ultracache-admin-css-components`, which depends on `ultracache-admin-css-foundation`, which depends on `ultracache-admin-css-tokens`.
* Leaves `includes/admin-dashboard.css` as a compatibility notice only; it is no longer enqueued. Adds `includes/admin/css/index.php` to prevent directory browsing.
* Establishes the CSS layer boundaries needed for the future WordPress-native/default and UltraCache dashboard theme switch without introducing that switch yet.

= 2.59.07.25 =
* Adds `includes/admin/js/app.js` as the dedicated application-composition module. It owns the remaining dashboard helpers, App component, action orchestration, section composition, and complete React element tree that previously remained in `includes/admin-dashboard.js`.
* Moves the existing application body structurally rather than rewriting it: the module imports the same core/API/settings/help/UI/diagnostics/jobs/warm-up/media/cache/lifecycle modules, configures them in the same order, creates the same state/actions, and mounts the same App component through the existing lifecycle mount helper.
* Adds the explicit `ultracache-admin-app` WordPress script handle after all feature/lifecycle dependencies and before the final bootstrap. The final `ultracache-admin-js` handle now depends only on `ultracache-admin-app`.
* Keeps `window.ultracacheData` localized immediately before the final bootstrap handle. The app module performs no runtime initialization until `bootstrap()` is called, so the existing localized configuration remains available before any dashboard settings, stats, diagnostics, paths, or REST configuration are read.
* Registers translations for the new app handle and preserves the existing translation registration for the final bootstrap.

= 2.59.07.24 =
* Adds `includes/admin/js/lifecycle.js` as the dedicated React state and dashboard-lifecycle module, loaded through the explicit WordPress script dependency manifest before the final dashboard bootstrap.
* Moves the complete App-level React state/ref initialization out of `includes/admin-dashboard.js`, including settings, stats, diagnostics, media counts/support/queue state, forms, job/process state, action queues, modal/accordion state, scanner state, persistence refs, cancellation refs, and manual media-session ownership refs.
* Moves toast insertion/dismissal callbacks into the lifecycle module while preserving IDs, replacement behavior, the 50-toast cap, persistence flags, and the existing default timeout.
* Moves all 12 App-level effects into the lifecycle module: Redis activation verification, settings-ref synchronization, before-unload protection, toast expiration timers, reverse-proxy notices, cache-plugin conflict notices, responsive/mobile handling, passive cache-stat polling with visibility pause/resume, and advanced/Varnish/Redis form synchronization.
* Preserves passive dashboard behavior: no frontend compression probe or browser scan is started automatically, cache-stat polling remains disabled when the setting is off, only one stats refresh can be in flight, and polling still pauses while the document is hidden.
* Moves process ETA calculation, dashboard-root lookup, and React 18/legacy ReactDOM mounting into the lifecycle module without changing displayed ETA wording or root-element compatibility.
* Keeps form-default evaluation lazy where it was previously conditional, so the scheduled warm-up and Varnish server default providers are not called when explicit saved values already exist.
* Adds the `ultracache-admin-lifecycle` script handle with `wp-element`, `wp-i18n`, and core dependencies, registers its translations, and makes the final dashboard script depend explicitly on it.

= 2.59.07.23 =
* Fixes the cache-module extraction regression introduced in 2.59.07.22 where `VarnishCard` called the shared `formatLooseTime()` helper without importing it from `includes/admin/js/core.js`, causing `ReferenceError: formatLooseTime is not defined` and preventing the UltraCache dashboard from rendering.
* Adds `formatLooseTime` to the explicit core-helper destructuring in `includes/admin/js/cache.js`; no Varnish settings, REST calls, cache behavior, dashboard markup, or CSS are changed.
* Adds a focused Varnish-card render smoke check with a populated `last.time` value so extracted components cannot pass validation while missing a runtime helper used only by a conditional render path.

= 2.59.07.22 =
* Adds `includes/admin/js/cache.js` as the dedicated cache-backend and cache-layer dashboard module.
* Moves the Redis/object-cache card, APCu card, OPcache card, Varnish card, external-cache cards, conflicting cache-helper notice, and their formatting/default helpers out of `includes/admin-dashboard.js`.
* Moves object-cache backend/fallback selection, Redis settings save/test/flush, full object-cache count, conflicting drop-in recheck/removal, Varnish settings/test/flush, OPcache/APCu flush, LiteSpeed/Nginx flush, external-cache redetection, and Flush All Cache orchestration into the cache module.
* Preserves the existing queued-action path for `purge_all`, `object_cache_flush`, `object_cache_full_count`, `apcu_flush`, and `varnish_flush_all`; no queue action name, polling interval, status handling, toast text, or refresh behavior is changed.
* Preserves Redis password handling, backend validation, APCu auto-inclusion in Flush All Cache, Varnish HTTP/admin mode defaults, detailed Varnish REST error propagation, and existing conflicting-drop-in confirmation behavior.
* Adds the explicit WordPress script handle `ultracache-admin-cache`, loaded after core/API/UI and before the final dashboard bootstrap, and registers its translations.

= 2.59.07.21 =
* Adds `includes/admin/js/warmup.js` as the dedicated warm-up feature module. It owns warm HTML/CSS job classification, CSS bundle scope normalization, first-visit CSS bundle setting helpers, warm job labels/scopes, crawl-page item retries, crawl batch retrieval, front-page warm actions, full-site/menu warm start/resume/restart flows, and CSS-bundle preparation orchestration.
* Adds `includes/admin/js/media.js` as the dedicated media feature module. It owns WebP/AVIF conversion-unit processing, HTTP 422 bounded retry and terminal failure reporting, retryable processor-lock handling, media batch retrieval, exclusive manual-session start/stop, conversion preflight, queue repair/rebuild orchestration, failed/completed queue actions, background-work pause/resume, and optimized-file recount handling.
* Preserves the 2.59.07.09 media behavior where a conversion failure is retried up to its server-provided limit, counted once only when terminal, logged with attachment/source/format/stage/code/detail evidence, and does not stop the remaining dashboard conversion queue.
* Preserves the 2.59.07.12 exclusive dashboard media-session behavior: dashboard conversion acquires ownership before preflight, visitor/upload/cron workers cannot launch competing conversions, ownership is carried through resumable jobs, and it is released on completion, pause, or failure.
* Keeps the generic persisted job runner in `includes/admin/js/jobs.js`; `admin-dashboard.js` now supplies only shared React state callbacks and dispatches each job item/batch to the warm-up or media module.
* Adds explicit WordPress script handles `ultracache-admin-warmup` and `ultracache-admin-media`, loads them after their core/API dependencies and before the final dashboard bootstrap, and registers script translations for both handles.

= 2.59.07.20 =
* Resumes the staged admin-dashboard refactor after the 2.59.07.19 wp-admin isolation hotfix, using 2.59.07.19 as the exact functional baseline and retaining all request-context isolation and scoped drop-in reconciliation changes.
* Adds the ordered internal module `includes/admin/js/jobs.js` for generic persisted dashboard-job orchestration; the module is loaded after diagnostics and before the final `admin-dashboard.js` bootstrap through the explicit WordPress script dependency manifest.
* Moves dashboard job localStorage persistence (`loadSavedJob`, `saveJob`, and `clearSavedJob`) into the jobs module while preserving the existing `ultracache-dashboard-job-state-v3` storage key and invalid/corrupt-storage fallback behavior.
* Moves saved-job resume/restart eligibility, pending-item detection, media-rebuild generation recognition, and warm-up generation stale-after-flush protection into a pure `getJobControls()` helper.
* Moves generic job-state initialization and restart normalization into the jobs module, preserving cursor/next-cursor handling, the 100-item persisted pending batch cap, log trimming, counters, queue-building state, start time, batch size, ETA samples/checkpoints, and warm-up generation persistence.
* Moves process-panel state normalization into the jobs module without changing current/total clamping, media visibility while inactive, cancellation state, logs, counters, or ETA fields.
* Moves generic batch fetching orchestration, pending-item continuation, cursor progression, pause/cancel persistence, per-item counter aggregation, media ETA sampling, completion cleanup, resumable failure persistence, and exclusive-session release handling into `createJobRunner()`.
* Keeps feature policy outside the generic engine through callbacks: REST batch selection, media conversion units, warm-up URL processing/retries, manual media-session ownership, media queue progress merging, completion messages, stats refresh, and media queue refresh remain controlled by the existing dashboard code.

= 2.59.07.19 =
* Adds strict request-context isolation for the frontend engine: frontend output buffering, JavaScript/CSS tag filters, frontend enqueue callbacks, resource-hint mutation, WooCommerce frontend script-data filtering, and store-profile shutdown handlers are no longer registered during wp-admin, REST, AJAX, or cron requests.
* Keeps cache invalidation hooks active in admin contexts, including post, product, term, menu, theme, widget, front-page, and permalink changes, so admin isolation does not disable cache purging after content changes.
* Stops automatic page-cache and object-cache drop-in reconciliation on every unrelated wp-admin, REST, AJAX, and plugin-management request. Drop-ins continue to synchronize during activation, settings persistence/rollback, explicit dashboard access, and WP-CLI operations.
* Removes the complete temporary 2.59.07.18 Elementor/admin asset diagnostic implementation as scheduled: property, hooks, registry snapshots, payload attachment, dashboard script registration, and `includes/admin/js/temporary-admin-asset-diagnostics.js`.

= 2.59.07.18 =
* Adds a temporary, read-only admin asset diagnostic for the UltraCache dashboard to investigate delayed Elementor 4.x failures such as `React is not defined`, `elementorModules is not defined`, and `Angie is not available` without changing any third-party script registration, enqueue, dequeue, dependency, or execution behavior.
* Captures WordPress script-registry snapshots immediately before and after the existing UltraCache Elementor Notes suppression at `admin_enqueue_scripts`, `admin_print_scripts-toplevel_page_ultracache`, and `admin_print_footer_scripts-toplevel_page_ultracache`.
* Records relevant Elementor, Angie, Notes, editor-MCP, `wp-element`, React, ReactDOM, and `wp-components` handles together with their source URL, declared dependencies, version, script group, registration/enqueue status, pending `to_do` state, completed `done` state, and the surrounding WordPress script queues.
* Adds `includes/admin/js/temporary-admin-asset-diagnostics.js`, loaded only on the UltraCache dashboard. It records browser runtime snapshots at 0 ms, 1.2 seconds, and 5 seconds for `React`, `ReactDOM`, `wp.element`, `elementorModules`, and `Angie`, plus the actually rendered relevant script tags and their `type`, `async`, `defer`, and `data-wp-strategy` attributes.
* Exposes the collected evidence as `window.UltraCacheTemporaryAdminAssetDiagnostics` and writes collapsed console groups prefixed with `[UltraCache temporary admin asset diagnostic]` for quick copying from the live WordPress test environment.

= 2.59.07.17 =
* Extracts the JavaScript defer/delay diagnostics interface from `includes/admin-dashboard.js` into the new ordered module `includes/admin/js/diagnostics.js` without changing its rendered markup, CSS classes, labels, list-editing behavior, REST routes, or save flow.
* Moves Browser Scanner result grouping, Runtime Scan result rendering, captured runtime/resource error presentation, Console Error Handler parsing workflow, DB-backed JS Diagnostic Queue status/actions, append-to-Defer and append-to-exclusion controls, and suggestion deduplication/presence checks into the diagnostics module.
* Moves the CSS Bundle Exclusions diagnostics field and its profile result metrics, exclusion coverage checks, copy/append controls, JSON download trigger integration, clear action, and result rendering into the same module.
* Moves the Speed Diagnostics / Performance Profiler card, its CSS bundle and critical-chain summaries, UltraCache overhead probe, frontend rewrite breakdown, duplicate/mixed-status CSS link diagnostics, top callback/origin tables, slow checkpoints, download/clear controls, and CSS-exclusion copy actions into the diagnostics module.
* Moves shared diagnostic helpers `getJsDelaySafetySuggestions()`, `getJsDelayReviewSuggestions()`, `isSuggestionPresentInDraft()`, `getNextMediaEtaCheckpoint()`, and `formatEtaDuration()` out of the monolith.
* Moves the pure Browser Runtime Scan URL/snapshot helpers out of the `App` component: display-URL sanitization, runtime scan URL construction, scan-ID verification, runtime result normalization, popup script inventory collection, direct popup snapshot reading, and navigation-loss snapshot creation.
* Adds an explicit diagnostics runtime configuration boundary for the localized `ultracacheData` object and detected plugins public path. The extracted UI continues to use the same frontend probe URL, Runtime Scan nonce, and console-error path examples as before.
* Extends the deterministic WordPress script manifest with `ultracache-admin-diagnostics`. Load order is now `namespace.js` -> `core.js` / `api.js` -> `settings.js` / `help.js` / `ui.js` -> `diagnostics.js` -> `admin-dashboard.js`; the diagnostics script is registered for WordPress translations.
* Updates `includes/admin-dashboard.js` to require and consume the diagnostics module through `window.UltraCacheAdmin`, then configures it after the localized runtime data and public paths are available.

= 2.59.07.16 =
* Extracts performance-profile definitions and profile patch logic from `includes/admin-dashboard.js` into the new ordered module `includes/admin/js/settings.js`, including profile detection, preserved-setting stripping, object-cache patch splitting, and the Safe/Balanced/Aggressive/All Off presets.
* Moves JavaScript strategy, WooCommerce frontend/cart-fragment strategy, HTML compression delivery, line-list normalization, append-only merging, and active-profile recognition into the settings module without changing existing option values or profile behavior.
* Moves settings import/export filtering, payload creation, import validation, JSON download handling, visible exclusion-list deduplication, broad WooCommerce-path coverage, overlap detection, and targeted line removal into the same settings module.
* Adds an explicit settings runtime configuration boundary for plugin version, site origin, and the detected WooCommerce public path; export metadata and broad WooCommerce-list matching continue to use the same live dashboard values as before.
* Extracts the complete option-specific help registry, generic help generation, and label-with-help renderer into the new ordered module `includes/admin/js/help.js`.
* Extends the deterministic WordPress script manifest with `ultracache-admin-settings` and `ultracache-admin-help`; final load order is `namespace.js` -> `core.js` / `api.js` -> `settings.js` / `help.js` / `ui.js` -> `admin-dashboard.js`. The settings module is registered for WordPress script translations.

= 2.59.07.15 =
* Extracts reusable dashboard presentation primitives from `includes/admin-dashboard.js` into the new ordered module `includes/admin/js/ui.js` without changing their HTML structure, existing class names, CSS, labels, control behavior, REST calls, settings, queues, or dashboard layout.
* Moves the toast viewport; support action links, inline support card, and support modal; generic cards and accordions; statistic cards; buttons; toggle controls; text, number, select, custom-select, textarea, saveable-textarea, and multiselect fields; detail rows; status pills; and the shared progress panel.
* Keeps dashboard-specific help lookup, help-label rendering, visible-list merging, and warm-source parsing in the monolith for now, and supplies them to the UI module through an explicit runtime configuration boundary so the extracted components retain their previous behavior.
* Adds `ultracache-admin-ui` to the deterministic WordPress script manifest with load order `namespace.js` -> `core.js` / `api.js` -> `ui.js` -> `admin-dashboard.js`, and registers the UI module for WordPress script translations.
* Updates `includes/admin-dashboard.js` to require and consume the UI module through `window.UltraCacheAdmin`; the extracted component declarations and support-link constant no longer remain duplicated in the monolith.

= 2.59.07.14 =
* Extracts the first stable dashboard modules from the 11,000-line `includes/admin-dashboard.js` monolith without changing the rendered interface, settings, REST routes, request payloads, queue behavior, or feature logic.
* Adds `includes/admin/js/core.js` for the shared WordPress element/i18n references, React hooks, public-path normalization and joining, class-name composition, safe localStorage access, viewport detection, content-encoding helpers, common number/count/file/byte/duration/time formatters, and the generic sleep helper.
* Adds `includes/admin/js/api.js` for the complete REST route map, REST client configuration, nonce/header handling, GET query construction, action-specific payload normalization, noisy JSON recovery, structured REST error metadata, HTTP status preservation, empty/invalid response handling, and generic batch-response normalization.
* Updates `includes/admin-dashboard.js` to consume the `core` and `api` modules through `window.UltraCacheAdmin` while preserving the previous function names at the dashboard call sites; no feature code receives its own fetch wrapper.
* Extends the deterministic WordPress script manifest so loading order is `namespace.js` -> `core.js` / `api.js` -> `admin-dashboard.js`, with `wp-element` and `wp-i18n` loaded before the core module.
* Aligns the packaged POT project-version header with the plugin release metadata.

= 2.59.07.13 =
* Adds the internal `window.UltraCacheAdmin` module namespace and duplicate-module guard as the foundation for the staged dashboard split.
* Registers local dashboard scripts through a deterministic WordPress dependency manifest while keeping the existing dashboard monolith, UI, settings, REST requests, and runtime behavior unchanged.
* Keeps `admin-dashboard.js` as the final module entry point and loads the namespace first through the explicit `ultracache-admin-namespace` dependency.

= 2.59.07.12 =
* Gives a dashboard Media Conversion run exclusive queue ownership before its preflight scan, preventing visitor, upload, cron, maintenance, and loopback background workers from starting competing conversion units.
* Allows a background unit already inside an encoder to finish, while the dashboard waits for the shared processor lock instead of stopping the manual job.
* Renews and persists the dashboard session token across conversion requests and resumable jobs, then releases ownership on completion, pause, or failure so pending background work can resume.
* Adds an expiring recovery watchdog so an abandoned or closed dashboard tab cannot leave background media generation disabled indefinitely.

= 2.59.07.11 =
* Keeps Async Remaining CSS disabled when the Aggressive performance profile is applied.

= 2.59.07.10 =
* Resolves arbitrary explicit missing globals from exact provider filenames, script handles, and scanned definitions instead of limiting provider matching to a small hardcoded set of WordPress/core globals.
* Resolves `PerfectScrollbar is not defined` to the exact `perfect-scrollbar` provider and the direct `theme-addons.js` consumer.
* Runs provider resolution before fallback stack-source evidence, removing repeated basename and path variants for the same script.
* Canonicalizes and deduplicates suggestions by effective owner-relative exclusion target.
* Reduces missing jQuery plugin method results to the exact provider and direct consumer, excluding indirect callers from appendable fixes.

= 2.59.07.09 =
* Gives captured browser runtime errors priority over static delay/defer classifications and always retains exact non-core stack-source evidence, including sources already present in a safeguard list.
* Connects the existing jQuery plugin provider resolver to the Runtime Scan execution path, allowing errors such as `counter.appear is not a function` to resolve the script that registers `jQuery.fn.appear` before generic missing-global handling.
* Adds structured per-unit media conversion diagnostics for source, storage, WordPress image editor, Imagick, GD, and final output-validation failures.
* Reports the effective attempted media format instead of the internal `best` queue policy; WebP-only mode now reports `webp` and automatic fallback failures report `avif+webp`.
* Returns retry attempt/limit metadata for failed media queue units and lets the dashboard complete the bounded retries for one attachment without aborting the whole optimization job.
* Records one terminal failed attachment after the retry limit, shows its attachment ID, source file, format, stage, code, and detail, then continues with the next queued attachment.

= 2.59.07.08 =
* Removes plugin-owned trait/class declaration conflict guards while retaining the WP-CLI environment condition.
* Repairs the gettext template header and removes local development paths from source references.
* Rewrites and aligns the packaged readmes, keeps `readme.txt` below 10 KB, and documents every distributed JavaScript helper.
* Separates the optimized AVIF/WebP file counter completely from Cache Statistics, dashboard-stat snapshots, cache-stat polling, and the generic JavaScript `stats` state.
* Stores only the dedicated AVIF, WebP, and total file counts in the non-autoloaded WordPress option `ultracache_media_file_counts`; no JSON file, sidecar, or other filesystem storage is added.
* Loads the file counter independently during dashboard bootstrap and returns it independently as `mediaFileCounts` from the existing media queue REST response, preventing cache-stat refreshes from resetting it to zero.
* Updates the dedicated counter when UltraCache creates or deletes optimized files and keeps the previous database values during the one-time option rename from `ultracache_media_storage_stats_v2`.
* Removes the Optimized Images card from the Cache Statistics panel and removes media-file values from engine/cache-stat payloads.
* Renames Refresh Storage Stats to Recount Optimized Image Files; the action scans `uploads/ultracache/images` and corrects only the AVIF/WebP file counter.

= 2.59.07.07 =
* Fixes optimized-image counters resetting to `0 AVIF · 0 WebP` after a dashboard refresh by including the persistent media-storage option in the initial passive dashboard payload.
* Merges the current persistent media counters into cached dashboard-stat snapshots before returning them, preventing a stale snapshot from overwriting live totals.
* Synchronizes legacy `imagesOptimized`, `avifImagesOptimized`, and `webpImagesOptimized` aliases with the persistent counters so older cached payload fields cannot take precedence with stale zero values.
* Keeps persistent media totals visible even when general cache-stat polling is disabled; reading these counters is a lightweight option lookup and does not scan the filesystem.

= 2.59.07.06 =
* Moves Stop All Media Background Work / Resume All Media Background Work to the final position in the media queue action list so the emergency control appears after normal processing, maintenance, retry, and cleanup actions.

= 2.59.07.05 =
* Adds a persistent Stop All Media Background Work / Resume All Media Background Work control that invalidates outstanding dispatcher tokens, clears media cron watchdogs, cancels deferred dispatch, returns claimed queue rows to pending, and blocks upload, page-generation, cron, immediate-worker, REST, dashboard, and direct AVIF/WebP conversion entry points after the current physical encode finishes.
* Keeps the media queue and existing optimized files intact while generation is stopped; refreshing the dashboard cannot resume processing automatically, and resuming can continue from the preserved pending queue.
* Merges Rebuild Media Queue and Verify / Repair Queue into one Rebuild / Repair Media Queue action. The scan now checks every attachment's required physical derivatives, marks current outputs complete, requeues missing or stale outputs, and shares the conversion lock so queue repair cannot race an active encoder.
* Treats an optimized derivative as current only when it exists and is at least as new as its source file, allowing changed originals or thumbnails to be repaired without deleting valid outputs first.
* Removes the redundant cache warm-up explanatory note and simplifies the media conversion panel description.

= 2.59.07.04 =
* Renames "Queue Missing Media on Demand" to "Queue Missing Media During Page Generation" so the option name matches the actual discovery trigger.
* Rewrites the setting description to state only when discovery occurs: uncached page generation, warm-up, cron warm, and stale regeneration, with conversion handled separately in the background.
* Simplifies the related help text without listing unrelated actions that do not trigger media generation.

= 2.59.07.03 =
* Makes missing-media on-demand processing immediate without converting inside the visitor request: the request queues the attachment and sends one signed, non-blocking same-site REST worker request after WordPress finishes the response and page-cache write.
* Defers the initial dispatch through a PHP shutdown callback so a fast conversion cannot purge the affected page before the originating request finishes storing that page in cache.
* Adds a dedicated database dispatcher lock held across the worker chain, so concurrent frontend visits, uploads, warm-up requests, and cron recovery can produce only one active background media dispatcher.
* Chains one physical image unit at a time through the existing shared conversion lock and timeout-safe processor; successful units dispatch the next worker while pending work remains.
* Keeps WP-Cron as a watchdog and fallback only. Failed loopback dispatch, conversion-lock contention, and conversion failures use bounded fallback/backoff schedules instead of launching workers from every visitor.
* Protects the public worker route with a short-lived HMAC bound to the dispatcher token, site URL, and WordPress authentication salt; stale, expired, or non-owner requests are rejected.
* Resets stale processing rows before watchdog recovery, allowing abandoned conversions to return to the bounded retry flow.
* Updates the Queue Missing Media on Demand description to distinguish immediate background dispatch from conversion inside the visitor request.

= 2.59.07.02 =
* Adds a dedicated database lock for Media Queue Rebuild chunks so refresh, resume, another browser tab, WP-CLI, and automatic queue building cannot scan/update the rebuild cursor concurrently.
* Adds a persistent rebuild generation token. Restart publishes a new generation before waiting for the lock, causing any older in-flight chunk or delayed browser request to stop as stale instead of updating the new run.
* Makes rebuild requests idempotent per generation, so retrying the same initial request does not delete and restart the queue a second time when the first response was lost.
* Persists the rebuild generation in the dashboard job state, silently waits for an active chunk lock during refresh/resume, and rejects saved state belonging to an older rebuild.

= 2.59.07.01 =
* Keeps the existing long-job progress bar and simplifies only the Media Queue Rebuild status area to Total units, Finished, and Time left.
* Removes the rebuild-only Overall Progress text and chunk scan/queue log lines that could present stale or misleading information while a new rebuild starts.
* Uses the fixed eligible Media Library attachment total (`libraryTotal`) as the rebuild denominator instead of the mutable queue-row total, preventing on-demand queue additions from producing results such as 28,675 / 28,677.
* Resets a fresh rebuild display to zero/Calculating until the first authoritative chunk response arrives, preserves exact progress across pause/resume, and prevents a non-complete job from showing 0s remaining.

= 2.59.06.100 =
* Bounds media conversion failures with a dedicated `consecutive_failures` queue column. A row becomes `failed` after three consecutive failed or abandoned claims instead of remaining pending forever; any successful physical-image unit resets the counter, and Retry Failed resets it for an explicit new attempt.
* Separates `skippedThisRun` from `alreadyOptimizedThisRun`, eliminating the WP-CLI skipped-total double count.
* Returns non-2xx REST responses for media queue lock conflicts and conversion/retry-limit failures: 409 for lock contention, 422 for conversion failures, and 500 for other processing errors.
* Wraps the GD opaque-JPEG source decode and generated-AVIF decode in scoped warning handlers so codec warnings are captured in diagnostics instead of leaking into output.
* Replaces the three remaining focused WPCS `json_encode()` fallbacks with WordPress `wp_json_encode()` calls.

= 2.59.06.99 =
* Replaces transient-only optimized-media storage totals with persistent aggregate counters stored in `ultracache_media_storage_stats_v2`.
* Updates AVIF/WebP file counts and byte totals immediately when UltraCache creates, replaces, or deletes generated derivatives, so dashboard values survive transient expiry, Redis eviction, and process restarts.
* Seeds the persistent counters from the latest legacy storage scan when available and keeps the last known values visible when reconciliation is incomplete instead of reporting an incorrect zero.
* Makes Refresh Storage Stats reconcile the persistent counters against the filesystem; complete scans become authoritative while capped/incomplete scans preserve the last known totals and mark reconciliation as needed.
* Adds dashboard status text distinguishing reconciled persistent counters from last-known counters that still need filesystem reconciliation.
* Removes the new persistent storage statistics option through the existing UltraCache runtime-data uninstall policy while leaving generated media files untouched.

= 2.59.06.98 =
* Clarifies the Media Conversion capability summary so Imagick installation, AVIF encoder verification, and WebP availability are reported as distinct states.
* Updates media runtime diagnostics to label AVIF results as self-test Passed/Failed and WebP results as Available/Unavailable instead of ambiguous Yes/No values.
* Keeps the automatic AVIF safety test and runtime behavior unchanged; this release only corrects capability reporting terminology.

= 2.59.06.97 =
* Removes the complete AVIF encoder self-test status panel from the Media Conversion dashboard, including the explanatory text and Imagick/GD result lines.
* Retains the automatic environment-fingerprinted AVIF safety test exclusively as an internal runtime capability gate for generation and frontend delivery.

= 2.59.06.96 =
* Removes the manual AVIF self-test button and its authenticated REST trigger from the dashboard after completing the encoder regression diagnosis.
* Retains the automatic, environment-fingerprinted opaque-JPEG and transparent-RGBA AVIF safety tests as runtime capability gates for generation and frontend delivery.

= 2.59.06.95 =
* Fixes content-dependent Imagick AVIF corruption by preserving the source image's native channel layout instead of activating an alpha channel on opaque JPEG files.
* Keeps native transparency for PNG/WebP sources without manufacturing alpha for JPEG sources; the GD conversion path now requests alpha preservation only for source formats that can carry it.
* Extends the AVIF self-test with a bundled opaque 300x169 odd-height JPEG regression fixture in addition to the transparent 16x16 RGBA PNG, and requires both tests to pass for each encoder.
* Increments the AVIF self-test algorithm version so previously cached results are invalidated and the expanded test runs automatically after upgrade.
* Does not delete existing generated AVIF files automatically; previously generated AVIF derivatives must be regenerated after installing this release.

= 2.59.06.94 =
* Bundles a deterministic 16x16 RGBA PNG for AVIF encoder validation instead of trusting codec presence or container metadata alone.
* Adds persistent, environment-fingerprinted AVIF self-tests for Imagick and GD that encode the bundled image, fully decode the generated AVIF, and validate known red, green, blue, white, transparent, and semi-transparent pixels.
* Uses the self-test result as runtime capability truth: failed AVIF engines are excluded from generation, existing AVIF files are no longer selected for frontend HTML/CSS rewrites, and `best` media work requires WebP when no AVIF engine passes.
* Adds an authenticated REST diagnostic endpoint and a Media Conversion dashboard button showing separate Imagick and GD pass/fail reasons.
* Makes WebP the recommended default for fresh/default settings and performance profiles while preserving existing saved output selections.
* Stores the AVIF result in `ultracache_avif_encoder_self_test_v1`, invalidates it when the PHP/image-library fingerprint or bundled test asset changes, and removes it through UltraCache data cleanup/uninstall.

= 2.59.06.93 =
* Adds a staged media-optimization ETA that measures the first 10 completed attachments, recalibrates after 100 attachments, and recalibrates again at every 500-attachment checkpoint.
* Keeps the current ETA between checkpoints while reducing the remaining time after every completed attachment, and preserves measured timing data across pause/resume without counting paused time.
* Propagates the exact eligible Media Library attachment total from the queue discovery query, replacing the provisional queue-row denominator and allowing progress and ETA to remain meaningful while the queue is still building.
* Shows the ETA sample size in the dashboard and displays a clear estimation countdown until the initial 10-attachment sample is available.

= 2.59.06.92 =
* Fixes the dashboard media optimizer regression where the shared `processJobItem()` helper referenced the React component-local `cancelRequestedRef` directly and raised `ReferenceError: cancelRequestedRef is not defined`.
* Passes a cancellation callback explicitly from the dashboard job runner into the media item processor, preserving pause/resume checks between physical-file conversion requests without leaking component-local state into module scope.

= 2.59.06.91 =
* Changes manual, REST, and background media conversion from whole-attachment processing to one physical source-file conversion unit per request.
* Keeps attachment progress resumable by detecting existing AVIF/WebP derivatives and returning the remaining unit count after every request.
* Adds secondary time- and memory-budget checks between physical files for full-attachment CLI and maintenance callers.
* Preserves explicit WP-CLI full-attachment regeneration while keeping web and cron workers on resumable single-file units.
* Replaces transient media processor coordination with the shared token-owned UltraCache lock table so dashboard, cron, REST, and CLI queue workers cannot overlap.
* Atomically claims pending media queue rows and prevents completed queue rows from re-running conversion after a lost or repeated response.
* Removes automatic browser retries for media failures, returns interrupted units to pending for explicit Resume, pauses the job on the first HTTP/server error, and adds a 250 ms delay between successful conversion units.
* Limits web queue processing to one conversion unit with an 8-second requested budget and a 15-second hard cap, while background processing uses delayed success, lock, and failure backoff schedules.
* Reduces stale media-processing recovery from 10 minutes to 2 minutes.
* Adds repository-level Composer, PHPCS, EditorConfig, and WordPress Coding Standards configuration for repeatable plugin linting.
* Refreshes the translation template metadata and adds the new media queue status/error strings.

= 2.59.06.90 =
* Adds local PHPCS tooling under `tools/phpcs` with PHPCS, WordPress Coding Standards, and PHPCompatibilityWP for WordPress.org audit checks.
* Documents the local PHPCS/PHPCBF commands and ignores the generated Composer `vendor/` directory.

= 2.59.06.89 =
* Improves same-URL reload-loop diagnostics by scanning printed plugin/theme scripts for upstream startup `.change()` / `trigger("change")` event triggers when the final redirect/listener script is already covered.
* Adds exclusion-first upstream trigger suggestions for delayed local WooCommerce/orderby scripts that can wake another plugin's redirect listener.
* Falls back to fetching the looped page's script inventory from the stored scan detail when the runtime report does not include scripts.

= 2.59.06.88 =
* Makes interrupted Browser Runtime Scan matching less brittle by ranking local delayed WooCommerce/filter startup scripts from the printed page even when the scan cannot read their JavaScript contents before navigation.
* Prioritizes delayed theme WooCommerce startup scripts, including product/order scripts that are likely to fire synthetic change events before another plugin redirects.
* Keeps interrupted-navigation findings manual and exclusion-first under "Do Not Defer or Delay" candidates.

= 2.59.06.87 =
* Teaches Browser Runtime Scan to detect when the diagnostic popup navigates away before the in-page collector can report, covering reload/redirect loops that happen before console errors are captured.
* Sends same-origin popup script inventory with direct Browser Runtime Scan harvests so REST diagnostics can analyze the actual scripts printed on the interrupted page.
* Adds exclusion-first suggestions for startup navigation/change triggers, including WooCommerce/orderby synthetic change patterns that can activate another plugin's redirect listener after JavaScript delay.

= 2.59.06.86 =
* Adds a deterministic plugin ZIP builder that writes internal archive paths with forward slashes, so WordPress recognizes the single `ultracache/` root folder during manual uploads.
* Verifies release ZIPs reject backslash entries, git artifacts, missing `ultracache/ultracache.php`, and files outside the `ultracache/` root.

= 2.59.06.85 =
* Adds Runtime Scan same-URL reload-loop detection that persists scan navigation evidence across reloads and records the last synthetic startup event before unload.
* Marks reload-loop fixes as exclusion-first so they appear as "Do Not Defer or Delay" candidates instead of Defer Instead fixes.
* Updates dashboard grouping for exclusion-first scan findings so they are counted and shown in the correct Browser Scanner section.

= 2.59.06.84 =
* Renames scan-result exclusion action buttons from the internal "Do Not Defer or Delay" target name to "Add to exclusions".
* Quotes "Do Not Defer or Delay" in append buttons and nearby scan-result status text so users understand it is the visible exclusion list name.

= 2.59.06.83 =
* Removes Advanced Runtime Font CSS Rewrite from the Balanced and Aggressive profile patches so no performance profile enables that advanced font rewrite automatically.
* Improves Runtime Scan and Console Error Handler suggestions for order-sensitive local plugin/theme dependencies by adding the shared owner JavaScript directory when the crashed consumer and matched provider live under the same owner path.

= 2.59.06.82 =
* Corrects the Varnish admin CLI response reader to match Varnish's own protocol: a fixed 13-byte status/length header followed by the declared body length plus the terminating newline.
* Fixes the admin-auth follow-up read so Varnish response bodies cannot leave a newline behind and desynchronize the next CLI response.

= 2.59.06.81 =
* Fixes the manual object-cache backend test so newly typed Redis passwords and clear-password requests are included in the REST probe payload before settings are saved.

= 2.59.06.80 =
* Fixes Varnish admin-secret mode by parsing the Varnish CLI response status line dynamically instead of assuming one fixed header width.
* Updates the Varnish admin auth hash builder to try the exact secret-file byte forms Varnish accepts, covering secrets copied with or without the trailing newline from `/etc/varnish/secret`.

= 2.59.06.79 =
* Makes the Varnish test REST endpoint return its diagnostic payload for normal connection-test failures instead of hiding endpoint details behind a generic HTTP 500 dashboard error.
* Updates the dashboard Varnish test action to merge failed diagnostic payloads and show each endpoint's exact `server: FAIL - reason` line in the error toast and Varnish card.

= 2.59.06.78 =
* Rewords the historical 2.59.06.60 changelog note about removed third-party matcher fragments so automated remote-file scans do not mistake archived domain examples for active plugin behavior.

= 2.59.06.77 =
* Rewrites the dashboard info-icon help into plain-language, code-derived explanations that describe what each control changes, why it can improve speed, and what to test before trusting it.
* Adds specific help coverage for cache delivery, media, JavaScript timing, CSS delivery, font optimization, WooCommerce controls, query/cookie safety lists, object cache, Redis, Varnish, external cache flushing, and warm-up/scheduling controls.
* Updates the bespoke JS safeguard, Browser Scanner, Console Error Handler, CSS diagnostics, Delayed JS auto-start, Font-Mix CSS, WooCommerce strategy, Apache Static HTML Delivery, and Object Cache Fallback tooltips to match the same explanation style.
* Regenerates `languages/ultracache.pot` so the new explicit tooltip strings and 2.59.06.77 metadata are reflected in the translation catalog.

= 2.59.06.76 =
* Moves "Bundle Generated Font-Mix CSS" from CSS Delivery into Fonts Optimization so the control lives beside the font pipeline it affects.
* Adds a new opt-in "Async Generated Font-Mix CSS Bundle" control that async-loads only the consolidated `bundle-font-mix-*.css` file while leaving individual `css-font-mix-*` source files untouched.
* Runs Font-Mix CSS consolidation before the async CSS pass when the new async Font-Mix option is enabled so the consolidated bundle can be classified and rewritten.
* Adds richer info-icon help for WooCommerce frontend strategy presets, including Off, Safe, Balanced, Aggressive, and Custom behavior.
* Adds missing info-icon help to the bespoke JS safeguard, Browser Scanner, Console Error Handler, CSS Bundle Exclusions, page URL diagnostic, and Delayed JS auto-start controls.

= 2.59.06.75 =
* Adds expanded info-icon help across dashboard option controls while keeping the short descriptions visible below each title.
* Adds a visible Apache Static HTML Delivery (.htaccess) option that serves conservative queryless anonymous HTML cache aliases before PHP on Apache-compatible hosts.
* Writes stable `index-orig.html`, `index-webp.html`, and `index-avif.html` aliases beside hashed page-cache files, with source markers so purges do not delete unrelated aliases.
* Expands Browser Cache Headers .htaccess coverage for web manifests, AVIFS, WASM, EOT, audio/video files, and revalidation-oriented HTML/JSON/XML handling.
* Keeps Apache Static HTML Delivery separate from Browser Cache Headers and removes its managed rules on deactivation, plugin data cleanup, and uninstall.
* Removes UltraCache-managed Browser Cache Headers and Apache Static HTML .htaccess blocks during uninstall without touching rules outside those markers.

= 2.59.06.74 =
* Adds an opt-in "Bundle Generated Font-Mix CSS" control in CSS Delivery that consolidates UltraCache-generated `optimized-css/css-font-mix-*.css` stylesheet links into one ordered blocking CSS bundle.
* Keeps the generated font-mix bundle classified as layout-risk CSS so Async CSS diagnostics do not treat it as an async candidate.
* Adds WooCommerce-box info-icon help as a UI test, moving the individual WooCommerce option descriptions into native hover/focus titles while leaving the rest of the dashboard copy unchanged.

= 2.59.06.73 =
* Adds a visible WooCommerce cart-fragments behavior dropdown with Off, Delay request, and Suppress empty-cart execution modes.
* Adds an empty-cart cart-fragments suppression mode that prevents `wc-cart-fragments` execution on anonymous cacheable pages without WooCommerce cart/session cookies, while keeping cart, checkout, account, logged-in, and active cart/session-cookie contexts on normal WooCommerce behavior.
* Keeps cart-fragments Delay and Suppress empty-cart execution mutually exclusive during dashboard saves/imports.

= 2.59.06.72 =
* Reworks the WooCommerce dashboard card into "WooCommerce Controls" and moves WooCommerce Safe Mode into that section so WooCommerce cache safety, request timing, and cleanup controls live together.
* Adds a visible WooCommerce frontend strategy dropdown with Off, Safe, Balanced, Aggressive, and Custom presets that write the existing cart-fragments delay and WooCommerce asset-cleanup toggles instead of adding a hidden runtime switch.
* Renames the cart-fragments timing control to "WooCommerce release timer" to mirror the general Delayed JS timing model.

= 2.59.06.71 =
* Renames the "Safe Asset Cleanup" dashboard card to "WooCommerce Asset Timing" so the section matches its WooCommerce-specific controls.
* Adds visible WooCommerce cart-fragments delay controls that can queue `get_refreshed_fragments` AJAX on anonymous cacheable pages and release it with the Delayed JS timing model or a WooCommerce-specific timer, while skipping logged-in, cart, checkout, account, and active cart/session-cookie contexts.
* Adds `assets/js/woocommerce-cart-fragments-delay.js` as the frontend helper for the new WooCommerce cart-fragments delay feature and keeps it protected as an UltraCache-owned helper script.

= 2.59.06.70 =
* Removes hidden runtime JavaScript safeguards for WordPress inline dependency blocks, GTM bootstrap snippets, and third-party dependency-library delay bypasses so Browser Scanner and Console Error Handler can propose visible "Defer Instead of Delay" or "Do Not Defer or Delay" safeguards from actual detected breakage.
* Moves inline analytics delay markers such as `gtag(`, `dataLayer`, and `gtm.start` into the visible Safe Third-Party Delay Patterns defaults instead of matching them through a private inline-script list.
* Removes hidden CSS and asset cleanup safeguards from CSS bundle exclusions, aggressive async CSS admin-asset blocking, frontend authoring asset stripping, and broad icon-font auto-detection; visible lists and scanner output are now authoritative, while UltraCache-owned helper JavaScript remains internally protected.
* Updates Delay icon fonts UI copy to clarify that only entries in the visible font pattern list are delayed.

= 2.59.06.69 =
* Makes the "Defer Instead of Delay" and "Do Not Defer or Delay" JavaScript safeguard lists mutually exclusive: appending to one removes overlapping entries from the other, paired saves send both final lists together, and settings sanitization removes remaining overlaps.

= 2.59.06.68 =
* Renames JavaScript safeguard action labels and scan status text so findings are described as appending to "Defer Instead of Delay" or "Do Not Defer or Delay" instead of the ambiguous "fallback exclusion" wording.

= 2.59.06.67 =
* Forces the Frontend JavaScript Manipulation safeguard editors for "Defer Instead of Delay" and "Do Not Defer or Delay" into a true two-column, one-row layout instead of relying on utility classes that could stack them vertically.

= 2.59.06.66 =
* Changes the Balanced and Aggressive profile default CSS bundle mode from Safe to Aggressive while keeping CSS bundling enabled and user-maintained CSS exclusions preserved.
* Keeps the Aggressive profile on native Defer as the base JavaScript strategy instead of broad Delay all JS, with targeted delay modules still enabled for speed.
* Makes the force-defer list act as "Defer Instead of Delay" across Delay all JS, targeted third-party delay, non-critical/local delay, LCP Boundary Delay, and delayed-placeholder restoration.
* Improves runtime JS diagnostics so missing WordPress/core globals suggest both the provider and the crashing consumer, filters UltraCache helper stack frames, detects duplicate-execution redeclare errors, and recognizes jQuery Migrate shorthand failures.
* Fixes pasted console parsing for jQuery Migrate shorthand failures where Chrome prefixes the TypeError with `jquery.min.js?...` and appends the `JQMIGRATE: Migrate is installed` notice, so the real error still produces a `jquery-migrate.min.js` suggestion.
* Lets Browser Scanner and Console Error Handler escalate persistent findings from "Defer Instead of Delay" to the stronger "Do Not Defer or Delay" fallback instead of hiding already-deferred suggestions.
* Updates the JavaScript safeguard UI to pair "Defer Instead of Delay" with the stronger "Do Not Defer or Delay" fallback and shared save/append controls.

= 2.59.06.64 =
* Fixes ordered delayed-JavaScript replay when another runtime removes, replaces, or independently restores an UltraCache placeholder while the loader is processing its original DOM snapshot.
* Replaces delayed placeholders atomically instead of inserting the executable script while the inert placeholder is still present.
* Skips detached placeholders and suppresses duplicate execution by preserved script ID or exact source URL plus execution mode; records skipped duplicate/detached counts on the document element for diagnostics.
* Makes the force-defer list act as "Defer Instead of Delay" across Delay all JS, targeted third-party delay, non-critical/local delay, LCP Boundary Delay, and delayed-placeholder restoration.
* Improves runtime JS diagnostics so missing WordPress/core globals suggest both the provider and the crashing consumer, filters UltraCache helper stack frames, detects duplicate-execution redeclare errors, and recognizes jQuery Migrate shorthand failures.
* Lets Browser Scanner and Console Error Handler escalate persistent findings from "Defer Instead of Delay" to the stronger "Do Not Defer or Delay" fallback instead of hiding already-deferred suggestions.
* Updates the JavaScript safeguard UI to pair "Defer Instead of Delay" with the stronger "Do Not Defer or Delay" fallback, and changes the Aggressive profile to use native Defer instead of broad Delay all JS.

= 2.59.06.63 =
* Prevents the CSS bundle source scan and final page warm loopbacks from receiving mod_pagespeed/ngx_pagespeed-rewritten HTML by sending the supported `PageSpeed: off` and backward-compatible `ModPagespeed: off` request headers.
* Requests unrewritten origin HTML for those internal operations so PageSpeed wrapper URLs such as `A.*.css.pagespeed.cf.*.css` are not passed to UltraCache cache-write validation when the server honors the supported per-request override.

= 2.59.06.62 =
* Fixes managed `wp-config.php` block replacement and uninstall removal so only the delimited block is removed while the surrounding line breaks are preserved; `<?php` can no longer be joined to the following `define()` statement.
* Strengthens candidate `wp-config.php` validation by requiring a normal full PHP opening tag, preventing malformed `<?phpdefine(...)` content from passing as a short opening tag plus an unknown `phpdefine()` call.
* Applies the same boundary-preserving removal and full-opening-tag validation to WordPress uninstall cleanup.

= 2.59.06.61 =
* Removes the standalone Redis manual-test control and its dedicated REST/action-queue surface so unsaved form values are no longer mixed with the already-bootstrapped object-cache runtime.
* Makes Save Redis Settings perform Redis connection, authentication, and read/write validation before changing wp-config.php, stored settings, or the generated object-cache drop-in; failed validation leaves the previous configuration untouched.
* Reloads after a verified Redis save, performs a one-time payload probe against the actually active backend, and labels the result with the tested backend.
* Replaces duplicate object-cache status rows with a concise runtime status, configured backend, Redis connection, PHP extension availability, backend-specific payload probe, and Redis prefix.

= 2.59.06.60 =
* Removes redundant Google-hosted Maps tile/static-host and reCAPTCHA static-host matcher fragments while retaining the existing Google Maps and reCAPTCHA entry-point patterns.
* Replaces the Google Fonts, dashboard heavy-action, and cron warm-up option-based locks with a shared token-guarded `ultracache_locks` table supporting atomic acquisition, expired-lock takeover, renewal, and owner-only release.
* Replaces the two remaining create-or-update `add_option()` branches with direct non-autoloaded `update_option()` calls, leaving no direct `add_option()` calls in UltraCache.
* Adds the lock table to activation, validated table handling, bounded expired-row cleanup, Delete All cleanup, and WordPress uninstall cleanup.

= 2.59.06.59 =
* Documents the two intentional `var_export( ..., true )` calls used to generate valid PHP string literals for UltraCache-managed `wp-config.php` password constants.
* Adds narrowly scoped PHPCS exceptions for `WordPress.PHP.DevelopmentFunctions.error_log_var_export`; the calls return strings and do not emit debug output.

= 2.59.06.58 =
* Completes the final reviewer validation across declared URLs, WordPress-native asset enqueueing, remote dependency checks, path resolution, guarded storage, late escaping, prefixes/dynamic names, generated drop-ins, and full uninstall cleanup.
* Regenerates `languages/ultracache.pot` from the current PHP and JavaScript sources, updates source references/header metadata, adds previously missing translatable strings, and removes obsolete catalog entries.
* Revalidates the AVIF Imagick/GD/WebP fallback policy and Safe CLS responsive-dimension safeguards without changing their runtime behavior.

= 2.59.06.57 =
* Removes 221 `function_exists()` declaration wrappers and six `class_exists()` declaration wrappers from UltraCache-owned functions/classes, leaving guards only for the standard `WP_Object_Cache` and `wp_cache_*` drop-in symbols.
* Gives advanced-cache and object-cache internal helpers separate `ultracache_advanced_cache_*` and `ultracache_object_cache_*` names so both drop-ins can load without shared helper declarations or load-order fallbacks.
* Prefixes the remaining plugin-owned object-cache keys for action-job schema/rows, cron-warm schema, runtime JS diagnostic jobs, CSS rewrite-map rows, and payload diagnostics with `ultracache_`.
* Removes the unused case-only REST class alias and the duplicate admin `ultracache-root` element/lookup.

= 2.59.06.56 =
* Preserves every existing image `width` and `height` attribute instead of replacing percentage, `auto`, empty, zero, boolean, or otherwise non-numeric values with intrinsic pixel dimensions.
* Skips Safe CLS processing for an image when either existing dimension attribute is non-numeric, and skips inline `max-width: none` images without injecting plugin CSS or changing responsive styles.
* When exactly one positive numeric dimension exists, calculates only the missing dimension from the resolved intrinsic aspect ratio instead of copying the source image's full opposite dimension.
* Adds both intrinsic dimensions only when both attributes are absent, while leaving `srcset`, `sizes`, inline styles, classes, and responsive theme behavior unchanged.
* Extends the Safe CLS raster-image exclusion to SVGZ as well as SVG and bumps release metadata from 2.59.06.55 to 2.59.06.56. No files or directories were added or deleted.

= 2.59.06.55 =
* Makes AVIF conversion prefer Imagick first and use GD only when a real transparent/semi-transparent AVIF encode-and-decode probe verifies alpha preservation.
* Adds an equivalent real Imagick AVIF alpha probe instead of trusting format advertisement alone, so unusable AVIF codecs are not treated as supported.
* Falls back to WebP as the effective media output when neither Imagick nor GD can produce a verified alpha-safe AVIF file, and keeps WebP available as the per-image fallback when an AVIF file is missing.
* Detects the source image by its real MIME type as well as its extension, handles renamed PNG/JPEG files correctly, and rejects SVG/SVGZ from all raster conversion paths.
* Preserves alpha in the direct GD and Imagick conversion paths and updates media support/reset probe cache keys.

= 2.59.06.54.01 =
* Prevents the Delete Everything/deactivation and WordPress uninstall requests from recreating UltraCache-owned database state after cleanup by defining an explicit uninstall-in-progress guard before teardown.
* Skips deactivation-hook work, cache-asset/CSS-rewrite table creation, and object-cache flush-report persistence while the uninstall guard is active.
* Refactors uninstall table removal through a validated UltraCache-only helper, verifies each requested table is absent, and repeats the two affected table drops as the final full-cleanup operation.
* Deletes and re-verifies the final `ultracache_object_cache_last_flush_report`, `ultracache_cache_asset_refs_db_version`, and `ultracache_css_rewrite_map_db_version` options after drop-in/file cleanup.

= 2.59.06.54 =
* Removes the uniquely delimited UltraCache managed-constants block from the exact active `wp-config.php` during plugin uninstall, regardless of the selected data-retention policy.
* Resolves only the configuration file loaded by WordPress or authoritatively located by WP-CLI; no WordPress-root or parent-directory path guessing is added.
* Writes only through `WP_Filesystem::put_contents()`, validates the resulting PHP, verifies the update by SHA-256 read-back, and retains the original contents only in memory for immediate verified rollback.

= 2.59.06.53 =
* Replaces every internal short-form plugin identifier with the full ultracache/ULTRACACHE prefix across PHP, JavaScript, generated drop-in templates, persistent keys, hooks, nonces, REST/AJAX integration, HTML identifiers, diagnostics, uninstall cleanup, translations, and documentation.
* Removes the unused action-queue option helper and obsolete action_jobs_rows_v1 cache cleanup.
* Bounds runtime JavaScript scan transient names with a fixed MD5 suffix.
* Corrects Delete All and uninstall cleanup for the active action-queue heavy lock, cron warm transient, and dynamic Google Fonts database locks while removing obsolete option cleanup entries.

= 2.59.06.52 =
* Encodes all frontend helper configuration passed through `wp_add_inline_script()` with `JSON_HEX_TAG`, `JSON_HEX_AMP`, `JSON_HEX_APOS`, and `JSON_HEX_QUOT` to prevent inline-script context breakout across all five helper-data callers.
* Restricts the WordPress-engine full-page cache output path to canonical files inside `ULTRACACHE_CACHE_DIR` whose basename matches `index-(orig|avif|webp)-<32-character MD5>.html` before raw HTML output.
* Restricts the early `advanced-cache.php` drop-in output path to canonical files inside `ULTRACACHE_CACHE_DIR` using the same UltraCache filename format, allowing only the generated `.html`, `.html.gz`, and `.html.br` payloads.
* Documents the two intentional raw full-page cache output paths with narrow PHPCS exceptions; HTML escaping is not applied because it would corrupt the complete cached WordPress response.

= 2.59.06.51 =
* Removes the remaining native filesystem fallback branches from guarded reads, file metadata, directory listing/deletion, media optimized-file checks, runtime cleanup, diagnostics, font cleanup, profiling, warm-crawl cleanup, and uninstall cleanup. These paths now fail closed when WP_Filesystem is unavailable.
* Replaces `tempnam()` with WordPress `wp_tempnam()` and verifies that the returned temporary path remains inside the requested guarded directory.
* Removes confirmed unused helpers: `ultracache_safe_chmod()`, `ultracache_safe_stream_set_blocking()`, `ultracache_uninstall_home_path()`, `ultracache_json_encode_for_inline_script()`, `ultracache_content_cache_reference_matches()`, `ultracache_request_profile_hook_priority_details()`, `ultracache_font_css_file_diagnostics()`, and the obsolete native recursive-delete helper.
* Keeps all existing storage locations and runtime behavior otherwise unchanged. No files or directories were added or deleted.

= 2.59.06.50 =
* Removes the unused `ultracache_safe_copy()` helper and its native `copy()` fallback.
* Removes the native `file_put_contents()` fallback from `ultracache_safe_file_put_contents()`; generated UltraCache files now write only through `WP_Filesystem::put_contents()`.
* Removes the native `rename()` path from `ultracache_safe_rename()`; generated cache and drop-in temporary files now move into place only through `WP_Filesystem::move()`.
* Replaces the temporary `.htaccess` file and rename workflow with a direct `WP_Filesystem::put_contents()` write. UltraCache retains the original `.htaccess` content only in memory, verifies the new content by SHA-256 read-back, restores or removes the file if verification fails, and removes the obsolete temporary `.htaccess` writable-path allowance.

= 2.59.06.49 =
* Restores the Redis and Varnish password fields as explicit administrator controls. Saving a non-empty Redis password writes `WP_REDIS_PASSWORD`; saving a non-empty Varnish password writes `ULTRACACHE_VARNISH_PASSWORD`. Empty fields preserve existing managed values, and dedicated remove actions delete only UltraCache-managed values.
* Adds a uniquely delimited UltraCache managed-constants block to the active `wp-config.php`. Existing `WP_CACHE`, `WP_REDIS_PASSWORD`, or `ULTRACACHE_VARNISH_PASSWORD` definitions outside that block are never moved, replaced, or removed; externally managed password constants are reported as configured and remain read-only in the dashboard.
* Replaces the previous custom wp-config.php backup, temporary-file, native copy, native file-write, and native rename workflow. The new writer uses `WP_Filesystem::get_contents()` and `WP_Filesystem::put_contents()`, validates the generated PHP, verifies the written content by SHA-256 read-back, and retains the original content only in memory for immediate verified rollback.
* Adds combined settings/wp-config transaction handling. If page-cache, browser-cache, or object-cache synchronization fails after a constants update, UltraCache restores the previous settings and original wp-config.php content; an unverified rollback is surfaced as a dedicated error instead of being hidden by the original save failure.
* Generates constant values with safe PHP literals and validates managed-block parsing for quotes, backslashes, line breaks, duplicate definitions, external definitions, and the active `WP_CACHE` state.
* Password values remain excluded from WordPress options, dashboard responses, REST responses, WP-CLI output, diagnostics, logs, embedded runtime configuration, and generated cache drop-ins. Responses expose only configured/managed/external status flags.
* Updates REST permissions so password writes require both `manage_options` and `activate_plugins` plus the existing REST nonce. The dashboard never displays the stored value; a blank field means keep, while removal requires a separate explicit action.
* Removes the obsolete wp-config backup-registry cleanup entry rather than adding previous-version cleanup. No migration, legacy lookup, backward-compatibility layer, old-file cleanup, or old-option cleanup was added.

= 2.59.06.48 =
* Removes the generated executable runtime-secret PHP sidecar and all related path discovery, rendering, synchronization, protection, diagnostics, object-cache loading, and uninstall code. No replacement secret file is created.
* Redis authentication now uses only the standard `WP_REDIS_PASSWORD` constant from the active `wp-config.php`. Scalar passwords and Redis ACL arrays containing username/password are supported; `WP_REDIS_USERNAME` remains an optional scalar username source.
* Varnish authentication now uses only the uniquely prefixed `ULTRACACHE_VARNISH_PASSWORD` constant from the active `wp-config.php`.
* Derives the early-runtime revalidation/control secret deterministically from the existing WordPress authentication keys and salts, so no additional secret needs to be persisted in the database or filesystem.
* Updates `advanced-cache.php` and `object-cache.php` generation so early Redis authentication and runtime-control validation read constants/salts directly, without requiring a generated secret include.
* Removes Redis and Varnish password inputs from REST update/test schemas and WP-CLI mutation paths. Dashboard fields are read-only status indicators, and client/API/CLI responses expose only configured yes/no flags.
* Forces any transient dashboard password keys to remain blank before option persistence. Runtime consumers hydrate credentials from constants only; diagnostics and logs expose no secret values.
* Updates readme documentation with the required `WP_REDIS_PASSWORD` and `ULTRACACHE_VARNISH_PASSWORD` definitions.

= 2.59.06.47 =
* Removes the generated executable `runtime-config.php` sidecar and its JSON predecessor. UltraCache no longer writes, loads, protects, reconciles, or cleans a standalone runtime configuration file.
* Embeds the normalized secret-free early page-cache configuration directly into the standard WordPress `advanced-cache.php` drop-in as a JSON-decoded array generated at drop-in build time.
* Adds an SHA-256 embedded-configuration marker to `advanced-cache.php`; drop-in status and diagnostics now verify that the embedded configuration matches the current dashboard settings.
* Removes the dedicated runtime-config bootstrap hook, file synchronization cycle, protection-file generation, warm-up sync call, path helper, diagnostics path card, and uninstall cleanup associated with the deleted sidecar architecture.
* Preserves the current runtime secret file architecture unchanged for the following dedicated secret-constants stage. Redis/Varnish password storage and wp-config.php writing are outside this patch.
* Updates dashboard diagnostics to report `embedded_in_advanced_cache` configuration instead of a runtime-config.php file.

= 2.59.06.46.02 =
* Corrective validation patch for the final path-refactor test. `ultracache_wordpress_admin_include_path()` now rejects any value containing `/` or `\` before basename normalization and allowlist matching, so values such as `../file.php` cannot be reduced to an approved filename.
* includes/core/functions.php: extends `ultracache_loaded_wp_config_path()` for WP-CLI. Normal web requests continue to use PHP's loaded-file list; WP-CLI requests use `WP_CLI\Utils\locate_wp_config()` because WP-CLI evaluates wp-config.php instead of including it. UltraCache adds no ABSPATH/root/parent search fallback.
* The existing wp-config read/write, backup, temporary-file, atomic-replace, capability, and guard behavior remains unchanged. The exact path returned by either authoritative runtime source continues to be the only primary config accepted by UltraCache's companion-path guard.

= 2.59.06.46.01 =
* Corrective public-path compliance patch after the 2.59.06.46 scan. Functional plugin, theme, uploads, wp-includes, and wp-admin URL matching no longer assumes default directory names such as `/plugins/`, `/themes/`, `/uploads/`, `/wp-includes/`, or `/wp-admin/`.
* includes/core/functions.php: adds `ultracache_wordpress_includes_public_path()` and `ultracache_wordpress_admin_public_path()`, resolving root-relative WordPress core/admin public paths through `includes_url()` and `admin_url()` while preserving file-versus-directory references.
* JavaScript optimization, LCP protection, runtime scanning, cache bypass, diagnostics, and default dependency exclusions now consume dynamic WordPress public-path resolvers. Plugin-specific CDN heuristics retain only owner/slug fragments such as `/woocommerce/assets/`; they no longer assume the configured plugins root name.
* includes/admin/class-admin-trait.php and includes/admin-dashboard.js: expose resolved public paths through the existing `wp_add_inline_script()` configuration and use them for WooCommerce matching and path examples. Dead profile copies of preserved path settings were removed.
* Product-filter, Slider Revolution, Elementor, Divi, WooCommerce, WordPress core JS, generated-assets, uploads, plugin, and theme references now derive from WordPress APIs. No remote request, asset load, storage location, cache key, setting key, migration, or compatibility fallback was added.

= 2.59.06.46 =
* Final path-compliance scan: verifies that active PHP code contains no `WP_CONTENT_DIR` or `WP_PLUGIN_DIR` references, no hardcoded plugin/uploads filesystem roots, and no `ABSPATH`-based wp-config.php assumptions. Direct-access guards remain unchanged; the unavoidable WordPress core-root `ABSPATH` and `WPINC` uses remain isolated in their documented canonical resolvers.
* includes/core/functions.php: adds `ultracache_mu_plugins_root_dir()` and `ultracache_mu_plugins_root_url()` as the only access points for WordPress's configurable must-use plugin path/URL constants, because WordPress exposes no public helpers for those roots. Font scanning, path-to-URL conversion, profiler ownership, and readable-root guards now consume the centralized resolvers instead of reading `WPMU_PLUGIN_DIR` / `WPMU_PLUGIN_URL` directly.
* readme.txt and README.md: replaces default-layout examples such as `wp-content/uploads/...` and `/wp-content/plugins/` with wording based on the active WordPress uploads/plugins directories, so the documentation remains correct for custom content, uploads, and plugin locations.
* ultracache.php: replaces the object-cache failure message's literal `wp-content/object-cache.php` reference with the WordPress content-directory location, preserving the same error condition and action.

= 2.59.06.45 =
* includes/core/functions.php: adds `ultracache_loaded_wp_config_path()` to resolve the exact `wp-config.php` file already loaded by the current WordPress request through PHP's authoritative `get_included_files()` list. The plugin no longer assumes that wp-config.php is under the WordPress core root or one directory above it. No root/parent fallback search is retained.
* includes/core/functions.php: adds `ultracache_is_loaded_wp_config_companion_path()` and updates readable, writable, and destructive path guards so wp-config access is limited to the actually loaded config file and UltraCache's existing temporary/backup filename patterns in that exact directory. The write, backup, temporary-file, and atomic-replace behavior itself is intentionally unchanged for the separate reviewer finding.
* ultracache.php: changes `get_wp_config_path()` to consume the loaded-config resolver while preserving the existing readability check, error handling, WP_CACHE parser, and enable/disable workflow.
* Removes the final wp-config root/parent path assumptions from the active runtime. Existing WordPress core-root helpers remain only for genuine core paths and includes.
* This patch changes wp-config.php path discovery only. It does not alter wp-config.php contents, backup retention, temporary files, atomic writes, runtime secrets, cache storage, drop-ins, settings, or uninstall policy. No migration, legacy lookup, compatibility fallback, file move, or directory move was added.

= 2.59.06.44 =
* includes/core/functions.php: adds `ultracache_wordpress_admin_include_path()` and `ultracache_require_wordpress_admin_include()` as the single approved resolver/loader for the WordPress core admin files used by UltraCache (`file.php`, `image.php`, `plugin.php`, and `upgrade.php`). The unavoidable WordPress core-root `ABSPATH` dependency is isolated in `ultracache_wordpress_core_root_dir()`; callers no longer concatenate `ABSPATH . 'wp-admin/includes/...'` themselves.
* UltraCache table installers, image-editor diagnostics, plugin inventory/deactivation, home-path discovery, and WP_Filesystem initialization now load their required WordPress core APIs through the centralized helper. Existing functions, timing, database schemas, and failure returns remain unchanged.
* includes/core/functions.php and ultracache.php: replaces remaining non-guard WordPress-root uses for cron-command generation, runtime path identity, and existing wp-config.php candidate construction with `ultracache_wordpress_core_root_dir()`. This changes path discovery only; wp-config.php read/write behavior is intentionally unchanged for its later dedicated reviewer-compliance design.
* uninstall.php: adds uninstall-local WordPress core/admin include resolvers and removes repeated direct `ABSPATH . 'wp-admin/includes/file.php'` construction. The single unavoidable uninstall `ABSPATH` read is isolated and documented.
* Direct-access guards and generated runtime-file guards using `defined('ABSPATH')` remain unchanged because they are access-control checks, not file/directory location logic. `WPINC` remains isolated in the existing canonical wp-includes resolver.

= 2.59.06.43 =
* includes/core/functions.php: changes `ultracache_runtime_config_storage_dir()` from direct `WP_CONTENT_DIR` concatenation to the existing `ultracache_wordpress_content_dir()` resolver backed by `WP_Filesystem_Base::wp_content_dir()`. `runtime-config.php` and `runtime-config.json` remain at the same WordPress content-directory `cache/ultracache/` location; this patch changes path discovery only.
* includes/core/functions.php: removes the remaining direct `WP_CONTENT_DIR` candidate from runtime-secret path discovery and uses the centralized WordPress content-directory resolver instead. Runtime-secret location, file format, protection, and read/write behavior remain unchanged for their later dedicated reviewer-remediation stage.
* readme.txt and README.md: describe required cache drop-ins as residing in the WordPress content directory without presenting the internal `WP_CONTENT_DIR` constant as the integration path.
* Removes all active PHP references to `WP_CONTENT_DIR` while retaining required WordPress-core `ABSPATH`/`WPINC` use, wp-config.php discovery, and the current runtime configuration architecture for their separate roadmap stages.

= 2.59.06.42 =
* uninstall.php: replaces direct `WP_CONTENT_DIR` use for `advanced-cache.php` and `object-cache.php` with `ultracache_uninstall_wordpress_content_dir()`, which resolves the active WordPress content directory through `WP_Filesystem_Base::wp_content_dir()` before constructing the required drop-in paths.
* uninstall.php: centralizes the current runtime-config cleanup path through `ultracache_uninstall_runtime_config_storage_dir()` instead of directly concatenating `WP_CONTENT_DIR . '/cache/ultracache/'`. The runtime-config files remain in their existing location until the later dedicated runtime-configuration storage stage.
* uninstall.php: routes generated CSS/font/deferred-JS cleanup through the existing WordPress uploads resolver, so uninstall uses the same `uploads/ultracache/...` roots as runtime writers and does not carry legacy cache-directory lookup or migration logic.
* uninstall.php: removes redundant `ABSPATH` and `WP_CONTENT_DIR` candidates from runtime-secret path identity and uses the WordPress home/content resolvers instead. WordPress core include paths that officially require `ABSPATH` remain unchanged.
* This patch changes uninstall path resolution only. Runtime storage, wp-config.php modification behavior, runtime-secret architecture, cache operation, generated-asset generation, and plugin settings are unchanged. No migration, legacy path lookup, compatibility fallback, file move, or directory move was added.

= 2.59.06.41 =
* includes/core/functions.php: replaces UltraCache's direct `WP_CONTENT_DIR` cache-drop-in resolver with `ultracache_wordpress_content_dir()`, which obtains the active WordPress content-directory path from `WP_Filesystem_Base::wp_content_dir()`. `advanced-cache.php` and `object-cache.php` remain in the WordPress-required content-directory root.
* includes/core/functions.php: adds dedicated WordPress Filesystem helpers for cache-drop-in existence, reads, atomic replacement, deletion, backup copying, size, and modification time. Drop-in operations no longer use UltraCache's generic filesystem wrappers or native PHP fallback operations.
* includes/engine/class-engine-dropin-lifecycle-trait.php: routes advanced-cache.php status, comparison, installation, replacement, and removal through the dedicated WP_Filesystem drop-in API. The generated drop-in contents and runtime behavior are unchanged.
* includes/class-object-cache-manager.php: routes object-cache.php status, ownership verification, installation, replacement, and removal through the same dedicated WP_Filesystem drop-in API. Object-cache backend selection and runtime configuration are unchanged.
* includes/settings/class-settings-trait.php: resolves drop-in conflicts through the canonical Filesystem API path, reads metadata through WP_Filesystem, and performs optional backup/copy/delete operations through the same filesystem transport. Removes the direct `WP_CONTENT_DIR` availability checks from active drop-in management.
* includes/diagnostics/class-diagnostics-trait.php and includes/cli/class-wp-cli-settings-stats-trait.php: use the canonical drop-in existence helper instead of native filesystem checks.
* This patch changes only cache-drop-in path resolution and lifecycle I/O. Page-cache/object-cache data storage, generated assets, runtime-config.php, runtime secrets, wp-config.php handling, and uninstall cleanup remain assigned to their separate roadmap stages. No migration, legacy path lookup, or compatibility fallback was added.

= 2.59.06.40 =
* includes/core/functions.php: changes the canonical page-cache root from `wp-content/cache/ultracache/` to the WordPress-resolved `uploads/ultracache/cache/` path and changes disk object-cache storage from `wp-content/cache/ultracache-objects/` to `uploads/ultracache/object-cache/`.
* templates/advanced-cache.php.tpl and includes/engine/class-engine-dropin-lifecycle-trait.php: replace hardcoded `WP_CONTENT_DIR` cache paths with build-time injected, WordPress-resolved cache and runtime-config paths. The advanced-cache drop-in location itself remains unchanged under the WordPress content directory.
* Page-cache HTML, compressed variants, locks, temporary media files, drop-in backups, diagnostics profiles, and the legacy file analytics buffer now resolve below `uploads/ultracache/cache/`. Existing files are not moved or read from legacy paths.
* ultracache.php: keeps `runtime-config.php` and its protection files at their current dedicated path until the later runtime-configuration storage stage, so executable runtime configuration is not moved into uploads.
* uninstall.php: updates clean-install cleanup roots to the new uploads page-cache and disk-object-cache directories, with no migration or legacy cache cleanup logic.
* readme.txt and README.md: document the new WordPress uploads-based cache and object-cache layout.

= 2.59.06.39 =
* includes/diagnostics/class-diagnostics-trait.php: replaces stale font-pipeline, CSS-bundle storage, and CSS-bundle summary readers that still looked under the internal page-cache directory with `ultracache_generated_asset_dir()` calls. Diagnostics now inspect the same WordPress uploads locations used by the writers for css-bundles, font-css, optimized-css, google-fonts, and the CSS bundle manifest.
* includes/cli/class-wp-cli-settings-stats-trait.php: changes the WP-CLI CSS bundle self-test from `wp-content/cache/ultracache/css-bundles/manifest.json` to the canonical `uploads/ultracache/css-bundles/manifest.json` path resolved through `ultracache_generated_asset_dir()`.
* ultracache.php, uninstall.php: adds the `deferred-inline-js` bucket to Delete All and uninstall generated-runtime cleanup so every ephemeral browser-loaded generated asset directory is covered. Persistent optimized AVIF/WebP files under `uploads/ultracache/images` remain intentionally excluded.
* Confirms that all active generated-asset writers already use the centralized WordPress uploads helpers introduced before this patch: CSS bundles, optimized CSS, font CSS, localized Google Fonts, deferred inline JavaScript, and optimized images remain under `uploads/ultracache/...`. This patch removes the remaining stale cache-root readers; it does not move files and adds no legacy lookup, migration, or fallback path.
* Page-cache, disk-object-cache, logs/analytics, drop-ins, wp-config.php, and runtime-secret storage remain unchanged for their dedicated roadmap stages.

= 2.59.06.38 =
* includes/core/functions.php: adds `ultracache_plugin_dir()` and `ultracache_plugin_url()` as the single WordPress-native resolver pair for UltraCache-owned files and URLs. Both are derived from `ULTRACACHE_FILE` through `plugin_dir_path()` / `plugin_dir_url()` and sanitize all optional relative paths.
* ultracache.php, includes/class-media-converter.php, includes/class-object-cache-manager.php, includes/admin/class-admin-trait.php, includes/diagnostics/class-diagnostics-trait.php, includes/engine/class-engine-dropin-lifecycle-trait.php, includes/engine/class-engine-frontend-assets-trait.php: replaces runtime concatenation of `ULTRACACHE_PATH`, `ULTRACACHE_URL`, and direct `plugins_url()` calls with the centralized plugin path/URL helpers. The initial bootstrap include remains based on the main-file constants because the helper file must load first.
* includes/core/functions.php: adds `ultracache_uploads_storage_dir()` and `ultracache_uploads_storage_url()` as the single filesystem/URL joiners for WordPress uploads. They consume the existing `ultracache_uploads_base_info()` result and preserve custom uploads directories, custom uploads URLs, multisite paths, and URL-encoded relative segments.
* includes/core/functions.php: routes generated CSS/JS/font assets, optimized image paths, uploads public-path markers, and their URLs through the centralized uploads helpers without changing their current `uploads/ultracache/...` locations.
* includes/engine/class-engine-media-image-trait.php, includes/media/class-media-html-rewrite-trait.php, includes/media/class-media-path-url-trait.php, includes/media/class-media-queue-trait.php: replaces seven direct `wp_get_upload_dir()` reads with `ultracache_uploads_base_info()` so media resolution, HTML rewriting, on-demand queue discovery, and attachment lookup share the same normalized uploads identity.
* This patch only centralizes path resolution. Page-cache, disk-object-cache, logs, analytics, drop-in, wp-config.php, and runtime-secret storage locations remain unchanged for their dedicated roadmap stages. No migration, legacy lookup, compatibility fallback, file move, or directory move is added.

= 2.59.06.37 =
* includes/core/functions.php: adds centralized WordPress-aware resolvers for the standard plugins root, WordPress core root, and wp-includes directory. The plugins root is now derived from the main plugin file through plugin_dir_path(), while the unavoidable core-root ABSPATH/WPINC use is isolated and documented in one place.
* includes/core/functions.php: replaces every active WP_PLUGIN_DIR use in installed-plugin resolution, font scanning, public URL/path mapping, readable-root allowlists, and callback profiling with the centralized plugins-root resolver. Callback profiling now classifies uploads through wp_upload_dir() data instead of a generic WP_CONTENT_DIR path.
* includes/core/functions.php, includes/diagnostics/class-diagnostics-trait.php: changes diagnostic path classification/redaction from direct WP_CONTENT_DIR/ABSPATH comparisons to known plugin, theme, uploads, WordPress-core, and document-root resolvers. No absolute server paths are exposed.
* includes/core/functions.php, includes/class-object-cache-manager.php, includes/engine/class-engine-analytics-trait.php: replaces filesystem-path-based Redis, APCu, and analytics namespace seeds with one installation-stable identity based on database identity, table prefix, and multisite network constants.
* templates/object-cache.php.tpl, templates/advanced-cache.php.tpl, includes/engine/class-engine-dropin-lifecycle-trait.php: injects the same non-filesystem namespace seed into generated drop-ins so dashboard/runtime diagnostics and drop-in cache operations use identical Redis/APCu/analytics prefixes.
* Namespace keys intentionally change in this clean-install pre-public build. No legacy-prefix lookup, cache-key migration, or backward-compatibility fallback is added.
* Existing page-cache, disk-object-cache, generated-asset, drop-in, wp-config.php, and runtime-secret storage locations remain unchanged for their later dedicated roadmap stages.

= 2.59.06.36 =
* includes/admin-dashboard.js, PERFORMANCE_PROFILES: removes the three dead Safe, Balanced, and Aggressive copies of `delayFunctionalThirdPartyJsPatterns`. Profile application already preserves this user-editable setting through `PERFORMANCE_PROFILE_PRESERVED_SETTING_KEYS`, so these copied values were never applied.
* Keeps the canonical PHP default matching-fragment list unchanged for installation defaults, reset/default restoration, and the dashboard Populate action. The listed third-party domains are detection patterns for scripts already present on the site; UltraCache does not request or load files from those providers.

= 2.59.06.35 =
* includes/engine/class-engine-js-optimization-trait.php, build_deferred_external_inline_script_tag(): replaces the manually compiled `<script src="..." defer>` markup for generated deferred inline-JS assets with `wp_get_script_tag()`, while preserving the generated asset URL, defer state, original attributes, and UltraCache metadata.
* includes/engine/class-engine-js-optimization-trait.php, restore_delayed_script_record_tag(): replaces manual opening/closing script reconstruction with `wp_get_script_tag()` for external scripts and `wp_get_inline_script_tag()` for inline scripts, while preserving the restored source, body, nonce, integrity, crossorigin, referrer policy, ID, and other valid original attributes.
* includes/engine/class-engine-js-optimization-trait.php, build_delayed_script_tag(): replaces manually concatenated delayed external-script placeholder markup with `wp_get_script_tag()` and passes unescaped attribute values to WordPress so core performs final attribute serialization and escaping.
* includes/engine/class-engine-js-optimization-trait.php, build_delayed_inline_script_tag(): replaces manually concatenated delayed inline-script placeholder markup with `wp_get_inline_script_tag()` and lets WordPress serialize both the placeholder attributes and inline body.
* includes/engine/class-engine-js-optimization-trait.php, apply_delayed_script_replacements_with_processor(): removes the unreachable `'<script>'` default value from the required record opening tag, eliminating the reviewer-detected raw script literal without adding a fallback path.
* includes/engine/class-engine-js-optimization-trait.php, collect_js_inline_dependency_defer_recommendations(): stops rebuilding a temporary `<script>` opening tag only to inspect its ID and reads the ID from the complete regex-matched tag instead.
* Removes the related NonEnqueuedScript PHPCS suppressions because the affected final-HTML transformations now use the WordPress 5.7+ script-tag APIs. Existing plugin-owned admin and frontend files continue to load through `wp_register_script()`, `wp_enqueue_script()`, and `wp_add_inline_script()`.

= 2.59.06.34 =
* Corrects the PayPal Terms and Privacy URLs in readme.txt and README.md to the working US Legal Hub URLs.

= 2.59.06.33 =
* ultracache.php lines 6 and 21: bumps the plugin header and ULTRACACHE_VERSION constant from 2.59.06.32 to 2.59.06.33.
* ultracache.php lines 1015-1023: replaces duplicated ABSPATH-based runtime-secret token/path construction with the shared ultracache_get_runtime_secret_site_token() and ultracache_get_runtime_secret_path() helpers.
* ultracache.php lines 3915-3918: resolves the browser-cache .htaccess from get_home_path() through ultracache_get_wordpress_home_path(), so WordPress subdirectory installations update the public home root instead of ABSPATH.
* includes/core/functions.php lines 608-704: adds shared WordPress-home, effective document-root, stable runtime-secret token, and canonical outside-document-root runtime-secret path helpers.
* includes/core/functions.php lines 706-775: resolves installed plugin roots from get_plugins() real main-file entries, then uses plugin_dir_path() and plugin_dir_url() instead of concatenating a slug directly onto WP_PLUGIN_DIR/plugins_url().
* includes/core/functions.php lines 2596-2599 and 2906-2909: replaces dirname(dirname(__DIR__)) own-plugin root discovery with the existing ULTRACACHE_PATH constant.
* includes/core/functions.php lines 2993-2997: validates readable root server configuration files against the WordPress home path instead of ABSPATH.
* includes/core/functions.php lines 3013-3018: makes the runtime-secret filesystem guard consume the shared canonical runtime-secret path helper.
* includes/core/functions.php lines 3175-3179: validates browser-cache .htaccess writes against the WordPress home path instead of ABSPATH.
* includes/class-object-cache-manager.php lines 252-258: makes object-cache Redis secret loading use the same shared runtime-secret token/path helpers as the main plugin.
* includes/settings/class-settings-trait.php lines 1204-1209: detects installed W3 Total Cache-related plugins through the WordPress get_plugins() inventory helper instead of file_exists(WP_PLUGIN_DIR . slug).
* includes/rest/class-rest-profiler-trait.php lines 3623-3627, 3647-3656, and 3962-3973: removes direct WP_PLUGIN_DIR + slug fallbacks from runtime JS discovery and resolves plugin roots only through the installed-plugin main-file helper.
* includes/diagnostics/class-diagnostics-trait.php lines 1332, 1360, 1392, 1409, and 1418: reports secret-file document-root placement against the effective server document root instead of ABSPATH string-prefix checks.
* includes/diagnostics/class-diagnostics-trait.php lines 2273-2275 and 2300: reports the shared effective server document root in server diagnostics.
* uninstall.php lines 33-83 and 451-457: computes uninstall-time runtime-secret cleanup from get_home_path()/DOCUMENT_ROOT using the same canonical outside-document-root location rules.
* readme.txt line 8 and README.md line 3: updates release metadata to 2.59.06.33.

= 2.59.06.32 =
* Removes the generic diagnostic database query wrappers that passed prepared SQL through an opaque `$query` parameter.
* Executes the analytics table and MySQL variable diagnostics through direct, scoped `$wpdb` calls with placeholders where values or identifiers are dynamic.
* Keeps database error suppression and unavailable-value behavior unchanged; no cache, analytics collection, or frontend runtime behavior changes.

= 2.59.06.31 =
* Corrects the first two Console Error Suggestion actions so they append to the unsaved JS Delay / Defer Exclusions draft instead of Defer those scripts.
* Renames those actions to Add This Script Exclusions and Add Full Dependency Chain to Exclusions.

= 2.59.06.30 =
* Replaces the two per-result JS scanner append buttons with four choices: defer this script, defer the full discovered owner chain, delay this script, or delay the full discovered owner chain.
* Appends the selected pattern only to the corresponding unsaved textarea draft; the other three buttons disappear only for that finding, while other findings remain unchanged.
* Removes the provider-contact disclaimer text from Safe Third-Party Delay Patterns and Known Functional Third-Party Delay Patterns.

= 2.59.06.29 =
* Removes same-request manual CSS bundle tag generation when a page bundle is built too late for WordPress enqueue.
* Applies page CSS bundle replacement only when the WordPress-enqueued bundle markup is present in the rendered HTML.
* Preserves the original stylesheet links unchanged when the enqueued bundle markup is missing; the generated bundle is used on a later request through normal enqueue.

= 2.59.06.25 =
* Renames per-result scanner Append buttons to Append to exclusions.
* Adds per-result Append to Safe Third-Party Delay Patterns buttons for Browser Runtime Error scans and Console Error Suggestions.
* Uses 5px button margins and appends to the existing delaySafeThirdPartyJsPatterns setting without changing scanner logic.

= 2.59.06.24 =
* Hardens DB diagnostics so optional database probes suppress visible WordPress database errors and return Unavailable when unsupported.
* Removes the unsafe SELECT @@query_cache_size fallback for MySQL 8 compatibility.
* Keeps the change limited to DB diagnostics; no cache/runtime behavior changes.

= 2.59.06.23 =
* Renames the UI setting from Delay icon font-face blocks to Delay icon fonts.
* Merges Auto-detect likely icon fonts into Delay icon fonts so the single visible switch enables both the delayed icon-font feature and its broad icon-font detection.
* Keeps the existing internal settings synchronized for profiles and saves: enabling Delay icon fonts also enables delayIconFontsAutoDetectEnabled; disabling it turns both off.

= 2.59.06.22 =
* Removes the Populate Defaults and Download CSS JSON buttons from CSS Bundle Exclusions & Diagnostics.
* Keeps Run CSS Diagnostics, Clear CSS Result, and Save Exclusions available; no runtime behavior changes.

= 2.59.06.21 =
* Replaces the separate Gzip and Brotli cache compression switches with a single HTML Compression dropdown while keeping the same internal settings.
* Runs server-compression detection only when an admin selects UltraCache gzip or Brotli compression, and keeps compression off when server-side gzip or Brotli is already active.

= 2.59.06.20 =
* Updates changelog.txt with the reviewer-hardening changes from the 2.59.06.15 through 2.59.06.20 cycle.
* Keeps readme.txt and README.md free of changelog sections; changelog history remains in changelog.txt only.

= 2.59.06.19 =
* Fixes fresh-install drop-in conflict detection so current UltraCache advanced-cache.php and object-cache.php markers are recognized as UltraCache-managed.
* Limits guarded drop-in owner reads to the exact WordPress drop-in paths instead of broad wp-content access.
* Adds the current object-cache drop-in marker used by the owner detector; no legacy marker compatibility was added.

= 2.59.06.18 =
* Adds reviewer-facing comments for unavoidable final rendered HTML rewrites where wp_enqueue_style() or wp_enqueue_script() cannot apply after resources have already been printed.
* Clarifies that late admin print hooks only dequeue conflicting third-party admin assets and do not print scripts.

= 2.59.06.17 =
* Replaces hardcoded generated upload URL/path checks with helpers based on WordPress upload directory data and UltraCache generated-asset helpers.
* Replaces broad wp-content readable-root logic with explicit plugin, mu-plugin, theme, uploads, cache, and core include roots.
* Replaces direct ABSPATH-relative URL-to-file mapping with the central local URL resolver.

= 2.59.06.16 =
* Adds Async external CSS for stylesheet links whose host is different from the current site host.
* Places the Async external CSS switch in CSS Delivery above Aggressive Async CSS and adds a visible exclusion field in CSS Bundle Exclusions & Diagnostics.
* Ensures async external CSS wins over CSS bundling so external stylesheets are not bundled when converted to async CSS.

= 2.59.06.15 =
* Adds a diagnostic-only fallback output buffer for valid store-profile requests when the WordPress template enhancement output-buffer callback does not run.
* Saves a skipped diagnostic profile with output-buffer-callback-not-run when neither the normal callback nor the fallback can produce a profile.
* Improves diagnostic profile headers and dashboard messaging for missing STORE profile JSON cases.

= 2.59.06.14 =
* Plugin Check: write the CSS rewrite-map atomic upsert with inline `$wpdb->prepare()` inside `$wpdb->query()` so the prepared-SQL sniff can verify it directly.

= 2.59.06.13 =
- Defers the automatic Local Google Fonts rebuild triggered by the toggle so settings save can finish first and the rebuild starts as a background dashboard queue job without blocking the UI flow.

= 2.59.06.11 =
- Cleans UltraCache-owned runtime options and transient prefixes during uninstall/Delete all data, including ultracache_* and ultracache_* transient rows.
- Removes generated runtime CSS/font directories under uploads/ultracache during full cleanup: css-bundles, font-css, google-fonts, and optimized-css.
- Keeps persistent optimized image derivatives under uploads/ultracache/images by design.
- Keeps the Media Optimization Image Output Format dropdown from 2.59.06.09 and the exact-file warm verification from 2.59.06.10.

= 2.59.06.07 =
- Matches CSS bundle sources using canonical URL variants so source URLs with ?ver= can match css_rewrite_map rows stored without query args.
- Allows optimized-css/font-css generated links to be recognized as aliases of their original manifest sources during page CSS bundle replacement.
- Keeps the change limited to CSS bundle source matching; no generated path, profile, JS, or font-build behavior changes.

= 2.59.06.04 =
- Builds page CSS bundle markup from the existing manifest when the WordPress-enqueued bundle tag is absent from the final cache rewrite buffer.
- Fixes warm-up results where a CSS bundle was built but the cached HTML still had no css-bundles reference.
- Keeps the fix limited to page CSS bundle insertion/replacement; no CSS profile, generated path, or JS/font behavior changes.

= 2.59.06.02 =
- Writes runtime generated font-css/optimized-css assets to uploads/ultracache so generated URLs match generated files.
- Prunes runtime font CSS map entries whose generated target CSS file is missing before printing frontend config.
- Saves the cleaned runtime font CSS map after stale targets are removed so frontend JS does not request missing CSS files.

= 2.59.06.01 =
- Removes the hidden Google Fonts manual-rebuild backoff bypass added in 2.59.06.
- Changes the Google Fonts write-failure retry guard to a visible short 10-15 second window.
- Persists Google Fonts failure details so diagnostics can show the actual failure reason instead of only failed counts.

= 2.59.06 =
- Restores uploads/ultracache generated-asset write/delete permissions in the guarded filesystem layer.
- Fixes Google Fonts/local font CSS generation paths that were blocked after generated assets moved under uploads/ultracache.
- Changes Speed Diagnostics loopback requests from profile-bypass to internal revalidate/force-refresh so timing breakdowns can be saved.
- Adds Google Fonts rebuild failure details to the diagnostics status when a stylesheet still cannot be generated.

= 2.59.04 =
- Replaces remaining page-cache storage writable checks with the WordPress-native UltraCache filesystem wrapper.
- Removes root-only review helper markdown files from the production package while keeping required source/build notes in readme.txt.
- Updates CSS rewrite map SQL table identifiers to use WordPress database identifier placeholders and updates tested metadata.

= 2.58.90.04 =
- Moves the Delayed JS loader from raw wp_head inline output to assets/js/delayed-js-loader.js.
- Enqueues the loader through wp_enqueue_scripts with WordPress-native script APIs.
- Passes the unified delayed-JS auto-start configuration through wp_add_inline_script() before the helper.

= 2.58.90.03.04 =
- Fixes Runtime/Console Scanner explicit `_ is not defined` handling so underscore can be suggested from actual page inventory.
- Deduplicates scanner suggestions that point to the same script by preferring exact path fragments over duplicate WordPress handles.
- Keeps provider/source suggestions in the same pass for both Browser Runtime Scanner and Extract Console Error Suggestions.

= 2.58.90.03.01 =
- Fixed Runtime/Console JS suggestion resolver for explicit missing globals such as "jQuery is not defined".
- Uses error source + active plugin/theme source-file evidence + final page script inventory to suggest the matching provider script only.
- Does not infer unrelated WordPress core dependencies; already protected failing sources remain marked separately from missing provider additions.

= 2.58.90.03 =
- Moved the Runtime JS Scan collector into assets/js/runtime-js-scan-collector.js.
- Enqueues the collector only for verified runtime scan requests through wp_enqueue_scripts.
- Passes scan configuration with wp_add_inline_script() before the helper and removes the old raw inline/wp_head/output-buffer scanner paths.

= 2.58.90.02.02 =
- Replaced the MailerLite helper loading path with a clean wp_enqueue_scripts implementation.
- Removed the MailerLite HTML rewrite insertion path and wp_print_scripts() usage.
- Keeps admin_url('admin-ajax.php') configuration through wp_add_inline_script() before the helper.

= 2.58.90.02.01 =
- Broadened MailerLite lazy nonce helper detection to include official plugin assets and MailerLite Universal markers.
- Preserves WordPress script API loading and admin_url('admin-ajax.php') endpoint handling.

= 2.58.90.02 =
- Moved the MailerLite lazy nonce frontend helper into assets/js/mailerlite-lazy-nonce.js.
- Loads the helper through WordPress script registration/printing APIs with dynamic Ajax endpoint data.
- Kept the existing lazy nonce runtime behavior and admin_url('admin-ajax.php') endpoint handling.

= 2.58.90.01 =
- Added staged frontend JavaScript helper enqueue infrastructure and migration inventory.
- Added assets/js documentation placeholders for upcoming WordPress-registered helper files.

= 2.58.83 =
- Evidence-based JS error scanner: source/stack/code-search findings are appendable, review-only scanner output removed, and hardcoded resolver flow disabled.

* Synced performance profiles with the unified delayed JS auto-start model.
* Renamed Safe Defer JS to Defer JS and Frontend JS & Request Chains to Frontend Javascript manipulation.
* Safe profile keeps all Frontend Javascript manipulation switches off.
* Balanced enables only the selected delayed JS features: safe third-party, non-critical/local, known functional third-party, and all third-party delay.
* Aggressive adds Delay all JS with a 0.05s unified fallback.
* Moved Delayed JS auto-start triggers into one dropdown and set all event triggers off by default.

2.58.76 - JS diagnostic queue DB compliance fix
- Replaced interpolated JS diagnostic queue table SQL with prepared identifier placeholders.
- Added targeted object-cache reads and invalidation for JS diagnostic queue job/status lookups.

2.58.75 - JS diagnostics spacing and label polish
- Adds 12px gaps to JS diagnostics action button rows.
- Adds 10px top spacing to Runtime Scan context, runtime action buttons, console action buttons, and runtime status message.
- Sets Page URL to scan and Console errors to analyze labels to 12px and #6f7b8f.

2.58.74 - Fixed JS diagnostics Browser Scanner / Console Error Handler two-column layout and title style consistency.
2.58.73 - Fixed JS diagnostics layout regression where Clear Console Input referenced a missing React handler.
2.58.72 - Reordered JS Delay/Defer diagnostics UI into exclusions, browser scanner, console handler, and shared queue status sections with improved runtime progress visibility.
2.58.71 - Removed borders from Advanced Settings mini action/diagnostic boxes and populate-warning notices for a cleaner UI.
2.58.70 - Fixed Advanced Settings & Exclusions layout so the five sections render as separate accordion card boxes instead of one shared wrapper.
2.58.69 - Advanced Settings accordion split and JS diagnostic result UI polish
- Adds a DB-backed JS diagnostic queue for browser runtime and pasted-console diagnostics.
- Adds queue start, pause, resume, cancel, progress, latest status, and stored result buckets.
- Stores Confirmed Error Fixes, Suggestions, Review Only, Already Listed, and Ignored buckets without auto-appending exclusions.

2.58.66 - Theme scan stage
- Adds a diagnostics-only Theme Scan Stage for unresolved runtime JS errors.
- Scans the active child theme first, then the parent theme, using guarded UltraCache file reads.
- Emits review-only exact theme JS candidates; Safe Defer toggle behavior is unchanged.

2.58.65 - Runtime error group resolver
- Added a Runtime Error Group Resolver for Safe Defer/Delay diagnostics.
- Maps failing console/stack source URLs to known plugin groups where confirmed, including WooCommerce Products Filter.
- Keeps MailerLite validation-messages.js as an exact confirmed source fix instead of a generic messages/global suggestion.
- Unknown plugin/theme source owners are review-only and are not appendable confirmed fixes.

2.58.64 - HTML adjacency resolver
- Added a final-HTML external-script plus immediate-inline dependency resolver for runtime/console JS diagnostics.
- Missing globals such as MailerLite messages now resolve to the adjacent provider script instead of a raw/global token.

2.58.63 - Safe Defer diagnostic fixes
- Runtime/console diagnostics no longer append broad generic dependency fixes such as jquery, jquery-core, wp-i18n, wp-hooks, wp-api-fetch, react, react-dom, or wp-element.
- Runtime diagnostics now keep WordPress/React foundation errors as exact resolved review-only candidates unless a specific plugin/script group is detected.
- Added specific confirmed resolver entries for WOOF/WooCommerce Products Filter and direct MailerLite validation-messages.js errors.
- Removed the browser-side console parser fallback from Extract Console Error Suggestions.
- Replaced the remaining aggressive-profile broad JS exclusion seed with the curated tested dependency path list.

2.58.62 - Safe Defer defaults cleanup
- Safe Defer JS now appends only curated WordPress foundation script paths.
- Removed broad generic dependency defaults from Append Tested Dependency Defaults.
- Removed the legacy Safe Defer init-script scan from the Safe Defer toggle and profile apply flow.

2.58.61 - Final font-display store-stage rewrite
- Runs linked stylesheet font-display normalization at the absolute cache-store finalizer and inside the write path, after CSS/JS/LCP transformations.
- Handles root-relative local stylesheet URLs before resolving source paths, so Elementor/theme/plugin font CSS can be rewritten to patched UltraCache CSS copies.

2.58.60 - Final linked font-display normalization pass
- Restored a final source-level linked stylesheet font-display normalization pass after async CSS transforms so late/restored local font CSS links are rewritten to UltraCache patched copies.
- Keeps runtime CSSOM font-display patch as fallback only; primary fix is cached CSS href replacement.

= 2.58.60 =
* UI: align uc-field-label styling with switch title typography across Advanced Settings fields.

2.58.58 - Dropdown title style alignment
- Dropdown setting titles now use the same visual title styling as switch labels.

2.58.57 - JS strategy cleanup and APCu flush lock
- Removed Defer all eligible JS from the full-site strategy dropdown; full-site strategy is now Off or Delay all eligible JS.
- Renamed LCP Boundary Defer to LCP Boundary Delay in the dashboard UI.
- Replaced Delayed local JS auto-start mode/seconds fields with one dropdown: interaction only, 0.1, 0.5, and 1-9 seconds.
- Removed the Disabled auto-start option; use the full-site delay switch instead.
- Forced Also flush APCu ON when APCu is selected as the object cache backend, with updated UI text.

2.58.56 - Native defer inline externalization
- Defer all eligible JS now externalizes safe inline scripts into generated deferred cache files so inline companions keep DOM order with native deferred external scripts.
- Delay all eligible JS remains the separate delayed-loader strategy.

2.58.55 - JS full-site strategy dropdown and separated defer/delay all behavior
2.58.54 - Visible delayed local JS auto-start controls
- Added Advanced Settings & Exclusions controls for delayed local JS auto-start: interaction only, custom seconds, or disabled.
- Replaced the hardcoded 12s local delayed JS auto-start with saved visible settings.
- Kept uncapped parallel delayed JS loading, ordered execution, jQuery ready barrier, and Elementor lazy background helper.

2.58.53 - Uncapped parallel delayed JS load without preload
- Removed the hardcoded parallel group cap from the delayed JS loader.
- External delayed scripts now load in uncapped contiguous parallel groups when the delayed batch starts.
- Kept ordered DOM execution, jQuery ready barrier, Elementor lazy background helper, and no delayed-JS preload links.

2.58.52 - Parallel delayed JS load without preload
- Removed delayed JS preload-window link injection from 2.58.51.
- Added windowed parallel script insertion with ordered execution for delayed JS batches.
- Moved local delayed auto-start later so initial load is more interaction-first.

2.58.52 - Delayed JS preload window
- Added a bounded preload-ahead window for delayed local/all scripts to reduce one-by-one network waterfalls.
- Kept strict DOM-order execution and the jQuery ready barrier so dependency order remains protected.
- Kept the 2.58.50 Elementor lazy-background class helper and avoided the 2.58.49 faster-execute/preload regression.

2.58.50 - Elementor lazy background compatibility rollback
- Reverted the 2.58.49 faster-local-queue and Elementor background preload/reveal performance experiment.
- Kept the 2.58.48 jQuery ready barrier and JS diagnostics UI cleanup.
- Added a lightweight Elementor lazy-background class helper that reveals nearby containers without running Elementor JS earlier or preloading all backgrounds.

2.58.48 - Delayed JS ready barrier and diagnostics UI cleanup
- Added a delayed-JS jQuery ready barrier so local/all delayed batches hold jQuery ready callbacks until the delayed batch has finished in DOM order.
- Cleaned the JS Delay / Defer Exclusions controls: confusing append/scan/debug buttons were replaced with explicit Analyze, Runtime Scan, Append Confirmed Error Fixes, and Append Suggestions actions.
- Added visible explanations under each JS diagnostic/action button and removed the broad /wp-includes/js/ path from tested dependency defaults.

2.58.47 - Precise JS exclusion matching for Delay all JS
- Generic visible JS exclusions such as woocommerce no longer blind-match unrelated handles like googlesitekit-events-provider-woocommerce.
- WooCommerce exclusions are now path/exact-handle aware, so real WooCommerce assets remain protectable without blocking Site Kit providers.
- Auto init-scan output now rejects broad root tokens such as woocommerce, frontend, main, plugin, script, data, and params.

2.58.46 - Delay wins over native defer
- When Defer all JS is active, script_loader_tag no longer emits native defer for the remaining scripts.
- Force-defer rules are suppressed during the absolute delay-all final pass so delayed Site Kit dependencies cannot run after native-deferred dependents.
- The final ordered delayed queue remains the authoritative pass for all eligible external and inline scripts unless matched by visible JS exclusions.

2.58.45 - Absolute Delay All JS rule
- Defer all JS now converts every delayable external and inline script into the ordered delayed layer unless matched by unified JS exclusions.
- Existing delayed scripts are normalized into the same all-js delayed queue so local and third-party pieces do not split execution order.
- Unified exclusions remain authoritative for whole WordPress script groups.

2.58.42 - JS exclusion and script group regression fix
- Treat the unified JS Delay / Defer Exclusions list as the authoritative exclusion source across defer, delay, non-critical delay, and LCP boundary paths.
- Normalize WordPress script group handles so one base-handle exclusion protects related js-before, js, js-after, js-extra, and translations companions.
- Avoid splitting WordPress script groups at script_loader_tag time when inline companions are registered.

- CLI warm_frontpage_html_css now warms HTML-only with success when CSS Bundling is disabled instead of failing on missing bundle injection.
- APCu object-cache CLI flush message now clarifies PHP-process scope and PHP-FPM/web APCu limitations.
- Varnish purge coordination now records/warns when Varnish is enabled but Flush All Include Varnish is OFF, avoiding misleading full-purge feedback.

2.58.39 - Final WordPress.org package
- Verified no remote asset enqueue, no wp_localize_script usage, no global ob_start usage, and no unexpected direct wp_remote_* calls beyond guarded infrastructure wrappers.
- Removed one frontend console warning from a MailerLite nonce fallback failure path.

2.58.38 - Escaping / returned HTML audit
- Added a shared inline-script JSON encoder that applies JSON_HEX_* flags for script-safe JSON literals.
- Updated runtime font map, speculation rules, runtime JS scan collector, and SR7/LCP selector inline scripts to use script-safe JSON output.
- Escaped the fallback LCP image preload href before injecting the generated link tag.

2.58.37 - Final regex review pass
- Switched font/local stylesheet scanners to WP_HTML_Tag_Processor.
- Removed legacy async CSS link rewrite regex fallbacks and moved noscript fallback insertion to the HTML API path.

2.58.36 - Admin enqueue modernization
- Updated the UltraCache admin dashboard script enqueue to use the WordPress 6.3+ args array with in_footer => true.
- Kept admin script execution behavior unchanged and did not add a script loading strategy.

2.58.35 - CSS bundle scanner HTML API
- Switched CSS bundle stylesheet discovery to WP_HTML_Tag_Processor for head/link scanning.
- Removed the remaining CSS bundle link-scan regex path from the warm verification counter.

- Normalized the GPLv2 license URI between the plugin header and readme.

2.58.33 - HTTP wrapper URL normalization revert
- Reverted esc_url_raw() normalization in the general UltraCache safe HTTP wrapper after it correlated with bypassing frontend optimization output.
- Kept WordPress safe HTTP transport, reject_unsafe_urls, bounded timeout/redirection, and the infrastructure wrapper PHPCS rationale.

2.58.30 - Final technical dead-code cleanup
- Removed unused private helpers left behind by recent HTML API, font, CSS, JS, LCP, and media refactors.

2.58.29 - Font/Icon scan suspicious candidate cleanup
- Filter suspicious encoded/random-looking font-family candidates from Font/Icon scan results.
- Keep real icon/font family names such as Font Awesome, eicons, feather, swiper-icons, and theme icon fonts.

2.58.28 - Safe Defer / scan HTML API cleanup
- Switched Safe Defer front-page script scanner to WP_HTML_Tag_Processor.
- Switched runtime JS inventory scan to WP_HTML_Tag_Processor.
- Switched front-page font scan style/link discovery to WP_HTML_Tag_Processor.
- Removed legacy regex attribute extraction helpers from those scanner paths.

2.58.27 - Image/dimension HTML API cleanup
- Use WP_HTML_Tag_Processor by default for Safe CLS image dimension injection.
- Remove the regex fallback from Safe CLS image width/height injection.
- Remove the regex fallback from lazy-load/async image attribute mutation.

2.58.26 - Admin settings FIFO cleanup
- Removed stale pending settings/debounce refs from the old save model.
- Kept scoped settings save/apply behavior and the current UI FIFO flow.

2.58.25 - Delayed font noscript fallback cleanup
- Prevent Safe Async CSS processing from re-wrapping existing noscript fallback links.
- Keep delayed icon-font noscript fallbacks clean without nested noscript tags.

2.58.24 - Leftover CSS HTML API cleanup
- Converted leftover CSS stylesheet consolidation from offset/substr HTML rebuilding to WP_HTML_Tag_Processor attribute mutation.
- Kept source stylesheet consolidation scoped to the existing leftover CSS bundle path with no regex replacement fallback.

2.58.23 - Google Fonts live output cleanup
- Run Google Fonts HTML API cleanup through the WordPress template enhancement output buffer for bypass/uncached responses.
- Keep wp_resource_hints source filtering and avoid regex fallbacks.

2.58.22 - Google Fonts resource hints source filter
- Added wp_resource_hints filtering for Google Fonts dns-prefetch/preconnect hints when Local Google Fonts Optimization is enabled.
- Kept HTML API cleanup for manually injected Google Fonts hint links.

2.58.21 - Font stylesheet link HTML API cleanup
- Removed regex fallback mutation for Google Fonts stylesheet link href rewrites.
- Neutralized remote Google Fonts resource hints with WP_HTML_Tag_Processor attribute mutation instead of regex tag removal.
- Removed regex fallback mutation for self-hosted font CSS link and font-display normalized stylesheet link rewrites.

2.58.20 - LCP/preload/image HTML API cleanup
- Removed the regex fallback from the LCP image candidate optimization path.
- Existing LCP preload link normalization now uses WP_HTML_Tag_Processor only.
- UltraCache-managed ambiguous/duplicate LCP preloads are neutralized with HTML API attribute mutation instead of regex removal.

2.58.19 - Media filtered-content HTML API cleanup
- Removed the regex fallback from WordPress content/block image URL rewrite callbacks.
- Filtered content image URL rewriting now uses WP_HTML_Tag_Processor directly under the WordPress 6.9+ baseline.
- Left full-page media URL token discovery and CSS url() parsing unchanged for later focused cleanup.

2.58.18 - Script delay HTML API cleanup
- Switched the full HTML script delay/wrap application path to WP_HTML_Tag_Processor.
- Removed the offset/substr assembly path for applying already-decided delayed script replacements.

2.58.17 - JS script loading attribute HTML API cleanup
- Switched the Defer All JS script loading attribute mutation path to WP_HTML_Tag_Processor.
- Removed the regex fallback from protected script loading attribute normalization.
- Left full script tag replacement/delay wrapping paths unchanged for later focused cleanup.

2.58.16 - HTML attribute helper cleanup
- Removed regex fallback mutation from the shared HTML tag attribute helpers.
- Shared attribute add/remove operations now use the WordPress HTML API path and leave the tag unchanged if the processor cannot safely update it.

2.58.14 - Move CSS bundle cached-HTML stylesheet replacement to the WordPress HTML API without regex fallback.
2.58.13 - Hide recovered noisy REST output details from the admin UI while keeping resilient JSON recovery.
2.58.12 - Add resilient REST response parser for noisy admin REST responses

2.58.11 - Remove REST output buffer guard
- Removed the UltraCache REST bootstrap output buffer and the matching rest_pre_serve_request discard filter to avoid unclosed ob_start review risk.

2.58.10 - Profile toggle enforcement
- Fixed profile application so Pre-render on Save and Stale While Revalidate are no longer stripped from profile saves.
- Added Enable Debug to the profile-managed off state so All Off turns debug headers off.
- Kept Pre-render on Save and Stale While Revalidate enabled for Safe, Balanced, and Aggressive profiles.

2.58.09 - Safe loopback request for JS inventory scan
- Routed the runtime JS inventory scan through the shared UltraCache safe loopback request helper.
- Kept JS inventory scan requests on the same trusted same-site URL policy, SSL fallback reporting, and debug logging used by other internal scans.

2.58.08 - Admin runtime config inline script
- Replaced the admin dashboard ultracacheData runtime config use of wp_localize_script with wp_add_inline_script and wp_json_encode before the module script.
- Kept wp_set_script_translations dedicated to dashboard translation loading.

2.58.07 - REST output guard for dashboard batch jobs
- Protected UltraCache REST JSON responses from third-party PHP notices or warnings printed before the JSON payload.
- Made dashboard REST parsing fail with a clear invalid JSON or empty response error instead of returning null to warm-up and media queue jobs.
- Kept batch response normalization strict so invalid REST payloads no longer surface as unrelated processed-property crashes.
- Raised plugin metadata to PHP 8.1+ while keeping WordPress 6.9+ as the target.

2.58.06 - Settings save FIFO and scoped response apply
- Scoped dashboard settings responses to the keys saved by each switch, dropdown, or form so unrelated UI state is not rolled back by later saves.
- Routed profile follow-up saves for object-cache autodetect and Safe Defer JS scans through the same patch-scoped settings save path.
- Removed changelog content from the readme files so changelog entries live only in changelog.txt.

2.58.05 - WordPress.org escaping and external services documentation cleanup
- Routed WordPress content/block media rewrites through a context-aware callback with escaped rewritten attributes.
- Updated External services documentation for Google Fonts, third-party optimization patterns, Varnish/reverse proxy endpoints, and PayPal links.

2.58.04 - Translator comment cleanup for Plugin Check i18n placeholders
- Added missing translator comments for placeholder-based i18n strings reported by Plugin Check.

2.58.03 - Full i18n pass and localization template refresh
- Expanded PHP and admin dashboard JavaScript i18n coverage for user-facing text.
- Kept commands, paths, keys, statuses, handles, and executable snippets untranslated.
- Refreshed the POT template.

2.58.02 - Repository localization cleanup
- Replaced direct unsafe loopback SSL bypass requests with the UltraCache safe loopback helper.
- Added admin JavaScript i18n setup and generated the UltraCache POT template.
- Added a first PHP i18n pass for REST/admin-facing messages.

2.58.01 - Initial public release
- Initial public release build.
