= 2.59.13.15 =
* Make Strong lifecycle suggestions emitter-timing-aware: classify strong event emissions as immediate, DOM-ready, window-load, deferred callback, unknown, or mixed; suppress callback/unknown/mixed races, keep Delay-to-Defer recommendations for DOM-ready/window-load emitters, and escalate truly immediate blocking emissions to Do Not Defer or Delay.
* Persist emitter timing evidence in the per-file JavaScript analysis cache with a parser-version bump, and fix blank emitter labels to fall back to script id/source when the WordPress handle is empty.

= 2.59.13.14 =
* Remove the obsolete 80-file content-analysis ceiling from the resumable Analyze HTML JS Dependencies workflow so every prepared local JavaScript candidate is processed before dependency evidence is correlated.
* Keep each iteration bounded to at most 10 JavaScript files and the existing ~1.8 second runtime budget, preserving resumable execution without truncating larger page inventories.
* Keep Strong Suggestion heuristics, stable evidence identity, exact safeguard actions, persistent analysis cache, resume/integrity checks, progress popup, and Help guidance otherwise unchanged.

= 2.59.13.13 =
* Fix resumable Analyze HTML JS Dependencies evidence correlation to bind lifecycle findings to a stable per-script identity instead of persisted numeric inventory indexes, preventing stripped inline-script bodies from compacting the inventory and assigning listener/emitter evidence to the wrong script. Older in-flight evidence jobs are rejected and must be rescanned.
* Make exact Strong Suggestion actions write exactly the displayed suggested handle/path to Defer Instead or Do Not Defer or Delay; plugin/theme path expansion is now reserved for Defer Chain and Exclude Chain actions.
* Keep Strong Suggestion heuristics, batching, persistent analysis cache, progress popup, and the 2.59.13.12 Help guidance otherwise unchanged.

= 2.59.13.12 =
* Add a post-install Help subsection beneath the JavaScript console-check steps for cases where the Console is clear but page functionality still fails, directing administrators to Analyze HTML JS Dependencies and warning against blindly applying every suggested safeguard.
* Keep the JavaScript analyzer, Strong Suggestions heuristics, batching, cache, resume, progress popup, and safeguard behavior unchanged.

= 2.59.13.11 =
* Fix Analyze HTML JS Dependencies settings-integrity fingerprinting to read the canonical UltraCache runtime settings array instead of the REST settings response object, eliminating the array_key_exists() type error introduced in 2.59.13.09; also allow the saved scan URL to be restored during dashboard-refresh resume without reassigning a const.
* Surface the resumable HTML JS dependency scan through the shared Warm/Media progress popup, with phase, page-script, local-file, processed-file, persistent-cache-hit, and freshly parsed-file progress while retaining the existing inline diagnostic status.
* Keep the 2.59.13.10 Strong Suggestions heuristics, batching, persistent per-file evidence cache, resume behavior, and settings-change invalidation semantics unchanged.

= 2.59.13.10 =
* Harden Analyze HTML JS Dependencies Strong Suggestions so only deterministic execution-order contradictions are promoted: delayed listeners/providers must be provably later than blocking/deferred counterparts, while uncertain async races remain outside the focused Strong stream.
* Suppress lifecycle self-correlation for duplicate inventory representations of the same script, and merge multiple independent lifecycle/dependency signals for one target into a single ranked Strong Suggestion with an evidence count instead of duplicate findings.
* Prioritize unsafeguarded multi-signal findings, keep lifecycle evidence ahead of declared-dependency-only evidence, and cap the focused Strong result set at eight actionable scripts without changing the broader Runtime/Console diagnostic heuristics.

= 2.59.13.09 =
* Add phase-aware Analyze HTML JS Dependencies progress reporting with page-inventory, local-file, processed-file, persistent-cache-hit, and freshly parsed-file counters while preserving the bounded 2.59.13.08 evidence pipeline.
* Persist a browser-session resume hint for the active HTML dependency job and automatically continue the same server-authoritative job after an administrator dashboard refresh; the existing same-URL server deduplication remains the fallback when browser session state is unavailable.
* Bind every scan to a fingerprint of the JavaScript execution-order settings used to build its page profile and inventory, revalidate that fingerprint during batches and before publishing Strong Suggestions, and stop with an explicit fresh-scan requirement if the configuration changes mid-run.

= 2.59.13.08 =
* Consolidate the resumable Analyze HTML JS Dependencies path around one compact per-script evidence registry instead of persisting separate listener/emitter maps, so every readable local JavaScript file contributes one normalized evidence record from either the persistent cache or the bounded scanner.
* Build final lifecycle correlation and Strong Suggestions from that shared registry without reopening or reparsing JavaScript files, while retaining the existing declared WordPress dependency-edge analysis from the same page inventory.
* Keep 2.59.13.07 in-flight scan compatibility by translating the previous persisted listener/emitter maps at correlation time, and expose single-pass evidence counters in the completed diagnostic result without changing suggestion heuristics.

= 2.59.13.07 =
* Add persistent per-file lifecycle-analysis caching for Analyze HTML JS Dependencies using UltraCache revisioned state storage, keyed by normalized local file path and validated by file mtime, filesize, and parser version.
* Reuse only compact extracted listener/emitter evidence for unchanged local JavaScript files; never persist JavaScript bodies, and automatically reanalyze and replace a cache row when the source fingerprint changes.
* Track cache hits, misses, and writes in the resumable scan result, and clear the JS analysis cache at the canonical Flush All clean-slate boundary while retaining the 2.59.13.06 batching and 2.59.13.05 Strong Suggestions behavior.

= 2.59.13.06 =
* Make Analyze HTML JS Dependencies use a dedicated resumable action job so page preparation, bounded local-JavaScript analysis batches, and final evidence correlation no longer run as one monolithic Strong Suggestions request.
* Process at most 10 readable local JavaScript files per lifecycle-analysis iteration with a short runtime budget, persist the cursor plus compact listener/emitter evidence between requests, resume the same URL job after an interrupted dashboard session, and skip the legacy monolithic JS safety file pass during this dedicated scan.
* Keep the 2.59.13.05 Strong Suggestions heuristics and output contract unchanged, avoid the global heavy-action lock for the resumable analyzer, and keep inline script bodies out of persisted scan state.

= 2.59.13.05 =
* Add a focused Strong Suggestions stream to Analyze HTML JS Dependencies so high-confidence silent Delay/Defer execution-order conflicts are surfaced separately from broad compatibility heuristics.
* Extend local JavaScript lifecycle analysis to resolve generic event-dispatch wrapper methods that forward literal lifecycle names into dispatchEvent(new CustomEvent/Event(...)), allowing missed one-time initialization events to be detected without hardcoded plugin exceptions.
* Prefer the exact WordPress script handle for Strong Suggestions when available, deduplicate by script, prioritize lifecycle conflicts, and cap the focused result set so actionable findings are not buried under low-value matches.

= 2.59.13.04 =
* Update the WordPress.org Donate link to the UltraCache page at https://iniotakis.com/ultracache/.
* Update installation step 14 to enable Warm uncached URLs after first visit under Warm Cache.

= 2.59.13.03 =
* Extend Console Error Handler diagnostics with the actual WordPress script dependency graph from the selected page and compare each declared edge against the final Delay/Defer/blocking strategy applied by UltraCache.
* Inspect readable same-site JavaScript files for lifecycle listener/emitter relationships so one-time initialization order risks can be proposed even when the browser produces no console error.
* Keep an exact script visible when the same runtime error persists after it is already listed in Do Not Defer or Delay; distinguish a safeguard that is still optimized in final HTML from a fully blocking script whose dependency chain still needs investigation.
* Add dedicated dependency-risk and persistent-failure diagnostic buckets without adding hidden compatibility exceptions or changing either safeguard list automatically.

= 2.59.13.02 =
* Add per-page Elementor generated-CSS dependency reconciliation to the shared final cache-storage path. UltraCache dynamically discovers Elementor `post-{id}.css` references in each rendered page, regenerates only missing referenced files through Elementor's own `Post_CSS::create($post_id)->update()` contract, verifies the physical file, and refreshes the dependency version before page-cache storage.
* Apply the same dependency contract to normal frontend STORE requests and shared warm writes. Unresolved Elementor CSS dependencies prevent UltraCache from storing that broken HTML variant instead of publishing a cache entry that references missing generated CSS.
* Keep Elementor cache ownership with Elementor: no global Elementor CSS regeneration is introduced. Optional Elementor Flush All still uses Elementor's native clear; CSS is rebuilt per page as each URL is visited or warmed.
* Correct Elementor help/FAQ text so Element Cache expiration is described as element-output lifetime, not generated-CSS lifetime.
* Make the two atomic schema-install `add_option()` calls use the explicit prefixed `ultracache_locks_schema_install_lock` option name so WordPress.org static review can verify the namespace without changing lock semantics.

= 2.59.13.01 =
* Fix the first-visit background warm runtime setting lookup so the enabled dashboard switch is read through the canonical snake_case runtime settings contract after a successful frontend STORE.
* Preserve the existing post-response enqueue boundary, shared targeted warm pipeline, Background warm pages per minute rate, and configured Varnish/LiteSpeed warm stages; no options or queue semantics are changed.

= 2.59.12.99 =
* Detect active Elementor as a supported native cache layer and add an opt-in Also flush Elementor Cache switch under External Cache Flush.
* Clear Elementor through its native files manager before UltraCache removes page cache, suppress the resulting self-originated Elementor callback, and let existing warm-after-flush work start only after both cache layers are invalidated.
* Add FAQ guidance recommending a 1 Year Elementor Element Cache expiration for mostly static sites without changing Elementor settings automatically.

= 2.59.12.98 =
* Defer Elementor generated-file invalidation reconciliation until shutdown so multiple clears in one request coalesce after the final clear, then run one canonical UltraCache Flush All and the existing configured warm behavior.
* Add narrowly scoped PHPCS SchemaChange ignores, with explicit versioned custom-table index-repair justification, to the eight intentional legacy index migration statements.

= 2.59.12.97 =
* Flush the canonical UltraCache page-cache layers when active Elementor clears its generated public files, preventing cached HTML from retaining references to removed Elementor CSS files.
* Reuse the existing Flush All warm behavior after Elementor invalidation; no Elementor-specific warm queue or crawler is added.
* Remove the Elementor Element Cache FAQ recommendation because disabling that separate cache does not prevent Elementor generated-file invalidation.

= 2.59.12.96 =
* Replace dynamic media queue and Media Library Replacement blocker `IN (...)` SQL construction with bounded 20-row batches whose complete placeholder sets are declared directly in each prepared query.
* Pass every affected prepared statement directly to the matching `$wpdb` read/write method, eliminating ambiguous intermediate query variables and replacement-count reports without suppressing database checks.
* Preserve the existing bulk operation semantics, table-identifier validation, blocker decisions, queue resets, cleanup, and readiness diagnostics.

= 2.59.12.95 =
* Align the runtime `ULTRACACHE_VERSION` constant with the installed plugin version so administrator JavaScript and CSS assets use the current cache-busting query value.
* Ensure the corrected automatic warm-up popup guidance is loaded immediately after upgrading instead of reusing the cached 2.59.12.93 `ui.js` asset.

= 2.59.12.94 =
* Correct the setup help popup so automatic warm-up guidance points to Warm full site after Flush All Cache and/or Warm uncached URLs after first visit instead of the unrelated scheduled-cleanup option.

= 2.59.12.93 =
* Add an optional Warm uncached URLs after first visit switch that queues the first cold frontend URL into the shared background warm pipeline, coalesces with on-visit CSS bundle work, uses the configured Background warm pages per minute rate, and completes the same enabled external-cache stages as full-site warming.
* Restore a locked LCP mapping as an immutable terminal boundary: missing request-credentials metadata no longer reopens frontend observation for that viewport.
* Remove the credentials-only update path that could modify a locked LCP row and trigger a targeted purge or LCP refresh without an explicit Forget mapping or Relearn action.
* Keep runtime image request credentials observation inside the normal Learning cycle only; existing locked mappings with an unknown mode remain unchanged until the administrator explicitly starts a new learning cycle.

= 2.59.12.91 =
* Extend the existing frontend LCP discovery cycle, only when Fix sliders / hero sections and LCP Image Priority are active, to observe the actual runtime image request credentials mode used for the LCP image URL.
* Suppress speculative slider/hero image preloads while the credentials mode is unknown; after browser observation, persist `none`, `anonymous`, or `use-credentials` and refresh only the affected page through the existing targeted LCP refresh queue.
* Emit browser-observed image preloads with the exact persisted `crossorigin` contract, skip preloading when the runtime mode is unavailable or conflicting, and keep non-slider pages on their existing preload behavior.
* Reopen legacy locked LCP mappings only for their missing credentials field, without relearning the LCP resource or triggering a full-site flush/warm cycle.

= 2.59.12.90 =
* Add FAQ guidance to disable Elementor Element Cache when UltraCache Page Cache is active, while keeping Elementor CSS Print Method on External File and running one Clear Files & Data, Flush All, and Warm Cache cycle after the change.
* Add FAQ guidance for strict color fidelity: disable Ignore color profile preservation; images whose embedded profile cannot be verified or preserved may remain in their original JPG/PNG format instead of being converted to AVIF/WebP.
* Enable Ignore color profile preservation by default in the Aggressive performance profile to maximize AVIF/WebP conversion coverage; Safe, Balanced, and All Off retain strict profile preservation.

= 2.59.12.89 =
* Remove the canonical Media Library Replacement singleton workflow option during dashboard Delete All cleanup and normal WordPress uninstall.
* Repeat deletion of the singleton workflow option in the uninstall final cleanup pass so a loaded shutdown callback cannot leave completed replacement state behind after the custom tables are dropped.
* Prevent a clean reinstall from displaying stale Preparation Complete, Replacement Applied, Verify, or Delete state from a workflow that belonged to the removed installation.

= 2.59.12.86 =
* Record resumable Theme CSS checksum validation with the canonical `validated` status instead of the incompatible `seen` value.
* Keep post-apply Theme CSS inventory persistence on the same canonical validation status so the inventory has one status contract.
* Remove the false "Theme CSS files disappeared" failure caused by the validator writing a status that the final file-set parity query did not recognize.

= 2.59.12.85 =
* Count deferred blocker sibling rows as part of the same canonical registry inventory, keeping registry/readiness parity stable after an affected attachment moves from matched to blocked_dependency.
* Persist registry completion as a durable singleton workflow milestone with the validated registry and readiness variant counts.
* Prevent a later Prepare request from repeating the initial registry consistency phase after blocker deferral; resume directly from file-copy planning without jobs, generations, or alternate state sources.

= 2.59.12.84 =
* Preserve the completed singleton readiness inventory when Prepare initializes the replacement registry instead of replacing the canonical readiness section with an empty default array.
* Make the final Prepare consistency check compare registry variants against the same persisted readiness snapshot that authorized Prepare, fixing false registry/readiness results such as 6654/0 after a complete scan.
* Keep readiness and Prepare in one canonical workflow option without reintroducing jobs, generations, fallback state sources, or browser-side workflow selection.

= 2.59.12.83 =
* Make deletion of Prepare-created replacement destinations best-effort during Restart so an unlink failure cannot block the authoritative reset of the one Media Library Replacement workflow.
* Continue clearing all six replacement tables, blocker decisions, plans, cursors, confirmations, and canonical workflow state after best-effort destination cleanup; the next Prepare re-evaluates any remaining file through the normal filesystem plan.
* Preserve the hard Restart boundary after destructive Do work has started and keep overwrite-backup restoration fail-closed.

= 2.59.12.82 =
* Make Restart Replacement Plan an authoritative reset of the one Media Library Replacement workflow without publication-contract versions, destination-ownership proofs, job provenance, or legacy-plan compatibility gates.
* Restore overwrite backups and remove destinations recorded as created during the current Prepare directly from the singleton registry, then clear all replacement tables, blocker decisions, plans, cursors, confirmations, and persisted workflow state.
* Preserve the existing block after destructive Do work has started, where rollback evidence is still required before any reset.

= 2.59.12.81 =
* Replace the Media Library Replacement execution-instance model with one canonical persisted workflow state shared by Prepare, blocker decisions, Do, Verify, Delete Originals, recovery, and status polling.
* Remove functional job IDs and generations from replacement REST requests, responses, SQL selection, React state, pagination, previews, CLI operations, and destructive authorization; retain legacy schema columns only as blank compatibility fields until a later schema-only cleanup.
* Make Restart clear all current replacement rows, blocker decisions, database/file/metadata/Theme CSS plans, nested cursors, confirmations, and workflow state, while preserving rollback evidence by refusing an unsafe reset after destructive Do work has begun.
* Make the blocker badge and atomic modal consume the same singleton backend truth, and isolate database, cleanup, and Theme CSS previews from authoritative workflow status.
* Persist readiness, database indexing, intermediate expansion, Theme CSS scanning, streaming, validation, and resumable cursors inside the canonical state; bind just-in-time destructive confirmation to the current plan fingerprint so cross-session continuation does not depend on browser or token lifetime.
* Preserve the bounded database reference extractor and inline data-URI exclusion introduced in 2.59.12.77 without changing its implementation bytes.

= 2.59.12.80 =
* Replace the separate Decide Blockers payload and open flags with one atomic modal state so the verified blocker response and the visible modal are committed in the same React state transition.
* Let the blocker endpoint select the server-active replacement job on initial open, lock pagination to the returned job, validate the response contract, and refuse to render an open modal without a real payload.
* Stop database, Theme CSS, and cleanup preview responses from overwriting the authoritative Media Library Replacement workflow status, and make periodic status refresh resolve the active job on the server.
* Preserve loaded blocker decisions across pagination while replacing them cleanly on the first modal load, without changing blocker rows, decisions, Prepare, Do, or database contracts.

= 2.59.12.79 =
* Remove short-lived database and Theme CSS confirmation tokens from Prepare planning validation, the final pre-Do guard, and prepared-plan validity so a completed plan remains actionable hours or days later.
* Suppress destructive token issuance from internal Prepare and recovery previews while retaining fresh confirmation tokens for explicitly invoked standalone preview/apply endpoints.
* Issue and consume a fresh database or Theme CSS start token inside the first authenticated Do chunk for that phase, then persist durable job/generation authorization for every later resumable chunk.
* Allow paused Do recovery to resume after the token TTL or from a later authorized administrator session without weakening registry, destination-file, metadata, database, Theme CSS, generation, or fingerprint guards.

= 2.59.12.78 =
* Make the authoritative active workflow status job ID take precedence over stale mapping, database, blocker, or cleanup preview job IDs when dashboard actions resolve the current Media Library Replacement job.
* Clear blocker payloads, decisions, and every replacement preview/modal state after Restart Replacement Plan so a previous job cannot remain attached to a newly prepared job in React state.
* Replace blocker decisions on the initial modal load and merge them only during pagination, preventing React batching from restoring decisions retained by an earlier job.
* Reject blocker responses whose returned job ID differs from the requested active job instead of presenting an empty Decide Blockers modal against the wrong replacement plan.

= 2.59.12.77 =
* Replace whole-value global PCRE image-reference extraction with one deterministic bounded byte scan, preventing large inline data-image payloads from trapping Media Library Replacement Prepare in CPU-bound backtracking after nginx has returned 504.
* Ignore inline data URIs because they are embedded payloads rather than replaceable Media Library files, while retaining exact raw database fragments for Apply and Verify.
* Reuse the existing reference normalization, uploads-path resolution, prepared database index, matching, Apply, and verification contracts without changing SQL pagination, escaping, blocker decisions, or adding development-version migration code.
* Preserve existing reference coverage for HTML, CSS url(), absolute and protocol-relative URLs, JSON-escaped slashes, query strings, fragments, and srcset-style values without creating a second full unescaped copy of each database value.

= 2.59.12.76 =
* Replace unbounded leading-wildcard Media Library Replacement database candidate searches with adaptive, bounded primary-key windows; image predicates execute only inside the resolved row range, while unsupported table shapes retain bounded raw-row OFFSET traversal.
* Make reference-index replay idempotent with INSERT IGNORE, advance progress by physical rows scanned rather than matching references found, keep database-match work out of the denominator until indexing completes, and expose the current table, column, cursor, scanned rows, and query duration.
* Continue the complete non-destructive Prepare discovery and planning flow when blocker rows exist. Defer every sibling row of an affected attachment to prevent partial file or metadata plans, then open Decide Blockers only after database and Theme CSS planning completes.
* Finalize group and per-file blocker decisions without starting Apply: whole-attachment exclusions proceed directly to the final pre-Do guard, while verified-overwrite decisions reactivate only affected attachments and rebuild their file, database, and Theme CSS plans.

= 2.59.12.73 =
* Stop the Prepare dashboard runner immediately when the server enters decisions_required, close the active progress panel, release the Prepare lease, and expose Decide Blockers without repeatedly calling the same Prepare phase.
* Remove redundant per-chunk replacement status GET requests from Prepare and treat the final status refresh as non-fatal, preventing transient nginx/PHP-FPM 502 responses from turning persisted Prepare progress into a dashboard failure.
* Add per-file blocker decisions beneath each group policy. Group decisions provide the scalable default, while paginated individual rows can override that policy before one atomic save.
* Keep Save Decisions limited to decision persistence and Prepare completion. Apply remains disabled until Prepare finishes and always requires a separate explicit click.

= 2.59.12.72 =
* Add a Prepare → Decide Blockers → Apply Media Library Replacement workflow: Prepare freezes actionable conversion and destination blockers instead of treating them as technical Prepare failures, and Apply remains locked until every blocker group is resolved.
* Persist blocker code, detail, generation, group decision, administrator, and decision time on the prepared physical registry; support keeping affected attachments as originals and overwriting different existing destinations through the existing verified backup contract.
* Add a grouped blocker decision modal using the existing replacement-preview layout, summary cards, server-side pagination, group-level actions, and per-unit details so large libraries require one decision per blocker class instead of one decision per image.
* Remove the global Existing destination files policy from the main Media Library Replacement settings; identical verified destinations remain automatic, while actual collisions are discovered by Prepare and presented only when they exist.
* Exclude keep-original attachments from file copy, metadata planning, database and Theme CSS matching, verification, and original deletion while retaining them in the frozen decision audit trail.

= 2.59.12.71 =
* Make replacement readiness prefer an authoritative persisted semantic skip for an exact physical source/format over stale pending duplicates from compatible parent requests.
* Carry physical-unit skip reason and detail through readiness blocker signatures, responses, progress messages, and dashboard diagnostics so deterministic unsupported variants report their real conversion blocker.
* Prevent replacement readiness from requeueing an exact unit already resolved as a terminal semantic skip while continuing to block Prepare until the required target file can actually be generated.

= 2.59.12.70 =
* Persist deterministic physical-unit semantic skips with their exact reason, detail, source fingerprint, and conversion-context signature so missing targets do not reopen unchanged skipped work.
* Reattempt a persisted semantic skip only after the source descriptor/fingerprint changes, the conversion context changes, or an explicit regeneration resets the unit.
* Reconcile terminal attachment parents that still contain nonterminal child units and derive completion from the authoritative child aggregate instead of leaving skipped/done parents with pending units.
* Stop WP-CLI media processing after repeated identical persisted queue signatures, preventing parent/unit attempt counters from masking a no-progress state-machine loop.

= 2.59.12.69 =
* Restored the intermediate attachment metadata verification helper used by replacement Verify and cleanup inspection after the attachment-level metadata apply refactor.

= 2.59.12.68 =
* Apply Media Library Replacement attachment metadata through one authoritative old-to-final plan per attachment instead of separate main-image and intermediate-size writes to the same serialized metadata value.
* Add an additive per-attachment metadata-plan registry that preserves active version 13 jobs, materializes plans during Prepare, and lazily materializes plans when resuming jobs created by earlier builds.
* Fix false Do consistency failures where UltraCache interpreted its own already-applied thumbnail metadata changes as external attachment changes.
* Support deterministic recovery from persisted partial states created by older runs while continuing to reject unknown filename, MIME, metadata, or custom-field changes made after Prepare.
* Count metadata Do progress by attachments with a stable total while retaining per-file registry rows for file verification, reference replacement, diagnostics, and rollback evidence.

= 2.59.12.67 =
* Keep the failed Prepare Replacement button disabled while replacing its technical-only tooltip with the actionable recovery path: open Advanced / Manual Recovery, run “Restart Replacement Plan”, and then run “Prepare Replacement” again.
* Display the same Prepare failure recovery guidance persistently below the disabled button so the next action remains visible without mouse hover or on touch devices, while leaving all Manual Recovery logic and enablement unchanged.

= 2.59.12.66 =
* Make Media Library Replacement Prepare consistency authoritative to persisted registry rows and readiness unique variants instead of transient scan-level skipped counters, preventing attachments without intermediate metadata or ignored non-physical metadata slots from falsely failing Prepare.
* Treat absent intermediate sizes and invalid non-physical metadata slots as no-work inventory entries rather than replacement blockers; continue to persist and block on real missing/unreadable source files, invalid generated outputs, registry skipped rows, insertion failures, and registry/readiness mismatches.
* Report registry skipped/failed rows and scan insertion failures explicitly in Prepare consistency errors so a server-backed failure identifies the authoritative blocker class.
* Keep the readiness progress popup open after terminal conversion blockers and append the requested recovery action: run “Scan Media Library & Repair Status” and rerun “Start / Resume Conversion”.

= 2.59.12.65 =
* Reconcile attachment parent state immediately after cooperative interruption, administrator pause, Retry Failed, fatal-shutdown recovery, and stale-worker recovery so dashboard, WP-CLI, readiness, and background workers resume from the same persisted physical-unit aggregate.
* Make exact child-unit shutdown recovery authoritative for the parent recovery status and stale-recovery generation, preventing parent and main/thumbnail retry budgets from diverging after a terminated worker.
* Clear obsolete encoder-attempt evidence whenever a unit is returned by a worker-level pause, interruption, or stale recovery, preserving the exact worker failure reason instead of displaying encoder diagnostics from an earlier conversion attempt.
* Resume background dispatch after a dashboard manual session ends when attachment work, local assets, physical units, queue build, or lazy unit inventory still require progress; do not depend only on attachment-level pending rows.
* Harden cross-surface recovery contracts for UI-to-WP-CLI and WP-CLI-to-UI handoff, output-written-before-claim-loss reconciliation, terminal retry limits, legacy false-done repair, metadata superseding, and independent AVIF/WebP unit state without changing the parent or child schemas.

= 2.59.12.64 =
* Stop Prepare Replacement readiness deterministically when a complete pass still has queueable variants but produces no enqueue, physical-unit attempt, generated output, unit-state transition, or blocker-set change; complete with blockers instead of starting an unbounded verification pass.
* Persist a deterministic blocker signature across readiness chunks and passes, including attachment, physical file, status, attempts, failure code/stage/detail, so repeated unresolved state is observable and resumable without arbitrary pass limits.
* Read readiness state from exact physical AVIF/WebP child units across compatible exact, best, and both parent policies, preserving per-file failure details and preventing attachment-level success from hiding a failed main image or thumbnail.
* Report the first exact blocked attachment, main/intermediate source path, persisted failure code, and failure detail in the readiness response and dashboard while keeping Media Library replacement locked until every required output is valid and current.

= 2.59.12.63 =
* Add authoritative physical-unit status counters joined to attachment parent policies, including materialized-parent coverage, pending/processing/done/failed/skipped units, retry-pending units, required totals, outstanding work, and completion that remains false while lazy inventory coverage is incomplete.
* Separate legacy parent-row touches from completed attachments and physical-unit attempts in batch results; report attachment/local-asset terminal outcomes, resolved/generated units, retryable unit failures, and terminal unit failures without changing attachment-level queue semantics.
* Make WP-CLI process, rebuild, process-batch, and scoped-ID output use the exact aggregate counters, remove ambiguous attachment wording, and refuse completion while either parent rows or physical units remain failed.
* Count readiness generated units only from successfully generated AVIF/WebP outputs rather than attempted units, while retaining legacy response aliases for compatibility with existing REST/background consumers.
* Keep dashboard batches, maintenance dispatch, cron fallback, and WP-CLI active while lazy physical-unit inventory is incomplete even when no attachment parent is currently pending; expose exact coverage and wait-state diagnostics instead of reporting premature completion.
* Avoid duplicate reconciliation inside one process batch, exclude terminal skipped parents that require no physical inventory from coverage debt, and report migration failures as explicit incomplete work rather than silently advancing counters.

= 2.59.12.62 =
* Route dashboard, REST, WP-CLI, Media Library Replacement readiness, and background attachment processing through one authoritative physical-unit worker; remove the CLI whole-attachment shortcut and process one persisted main/thumbnail output unit per claim.
* Persist exact per-file success, semantic skip, retryable failure, terminal failure, encoder-attempt evidence, source fingerprint, attempt count, and stale-worker recovery state before any later unit can run.
* Derive each attachment parent status only from active child-unit rows, forbid done when any required main image or thumbnail remains pending/failed, and trigger affected-page processing only after the complete parent reaches a successful terminal state.
* Extend pause, retry, explicit regeneration, cooperative interruption, fatal-shutdown recovery, and stale-claim recovery to child units while retaining the attachment-level parent queue, local-asset execution, UI attachment counters, and existing schema versions.

= 2.59.12.61 =
* Lazily materialize physical conversion units for existing attachment queue rows during rebuild, execution, Media Library Replacement readiness, and bounded administrator/CLI maintenance while leaving local-asset rows atomic and unchanged.
* Reconcile every active unit against its exact source and target files: validate format headers and freshness, mark current outputs done, keep missing/stale/invalid outputs pending, classify unsupported mappings as skipped, and supersede obsolete metadata units.
* Recompute attachment parent state from reconciled child units so a legacy done/skipped row cannot remain complete while a required main image or thumbnail is missing; preserve terminal failed parents until explicit retry unless all required outputs are already valid.
* Keep child rows synchronized after the legacy attachment worker persists a result, remove child rows with parent rebuild/clear operations, and clean bounded orphan units plus persistent migration state without changing UI attachment counters or activating child-unit claims yet.

= 2.59.12.60 =
* Add a dedicated persistent physical media conversion unit table keyed to the existing attachment-level parent queue without changing current UI, REST, WP-CLI, background-worker, retry, local-asset, or replacement execution semantics.
* Build deterministic main and intermediate source inventories that expand best/both policies into concrete AVIF/WebP units, persist exact source and target paths plus fingerprints, and remain idempotent across repeated synchronization.
* Supersede obsolete physical units when attachment metadata changes, reactivate changed source fingerprints as pending work, and retain the parent queue as the stable aggregate/request contract for the later per-unit worker migration.
* Register the new operational table with UltraCache table validation, activation schema checks, plugin-data cleanup, uninstall cleanup, and Media Library Replacement operational-state exclusion.

= 2.59.12.59 =
* Release cooperative local-asset early-return claims immediately back to pending without consuming failure budgets, and recover fatal/terminated PHP shutdown claims automatically; quarantine only repeated real worker terminations after the persistent recovery budget is exhausted.
* Make Retry Failed recover abandoned processing rows as well as terminal failed rows under the exclusive media-process lease, expose recoverable interrupted work to the dashboard, and dispatch the queue immediately after administrator recovery.
* Order pending media work by the lowest attempt count before row identity so a retried AVIF or WebP unit cannot starve another pending format for the same source.
* Add the Images & Media Library FAQ guidance for theme/plugin images that remain JPEG or PNG, while preserving original local files and the existing rewrite, encoder, replacement, and schema contracts.

= 2.59.12.58 =
* Fix local theme, plugin, mu-plugin, and WordPress-includes media jobs remaining in processing before encoder execution when the guarded source-fingerprint UPDATE matched the active claim but changed no stored values.
* Treat MySQL/MariaDB zero changed rows as a valid no-op only after an exact id, status, attempts, and started-at claim verification; retain stale-claim rejection when that authoritative claim no longer exists.
* Preserve the existing local-source resolver, generated identity, shared media queue, AVIF/WebP encoders, affected-page fence, Media Library Replacement, and schema versions without adding a migration.

= 2.59.12.57 =
* Repair the media queue schema 4-to-5 upgrade by adding source-request uniqueness only after legacy attachment rows receive their canonical source identity and requested-format values.
* Replace MariaDB-incompatible SHOW INDEX WHERE ... LIMIT probes with full index metadata inspection, and rebuild the legacy unique attachment indexes as the required non-unique lookup indexes without duplicate-key attempts.
* Make media queue and affected-page reference upgrades idempotent across fresh, legacy, and partially applied schemas, deduplicating only identical canonical work identities before creating the final unique indexes.
* Advance the media queue schema to 6 and affected-page reference schema to 3 while preserving queued attachment/local-asset work, statuses, retries, source fingerprints, and page-purge requirements.

= 2.59.12.56 =
* Complete the integrated local-image rewrite and WordPress-aware wp_options replacement regression candidate across canonical WordPress-derived source resolution, collision-free local-asset variants, the shared media queue, HTML/CSS/LCP surfaces, option identity, cache synchronization, concurrency, recovery, and rollback.
* Match native WordPress option action sequencing around the byte-exact writer: publish the generic update_option action immediately before the atomic SQL mutation, then publish the option-specific update action and updated_option only after the database and runtime cache state are verified.
* Preserve the established Media Library uploads generated identity byte-for-byte, keep Media Library Replacement scoped away from theme/plugin originals, retain schema 13 without migration, and keep local-asset work isolated from attachment rebuild and repair operations.
* Add one integrated release gate covering executable identity/freshness/option-writer behavior, source-contract parity, complete PHP syntax, release metadata, package root, archive integrity, and exclusion of development tests from the installable ZIP.

= 2.59.12.55 =
* Keep every persisted WordPress option reference on the dedicated option-aware writer even when the active multisite blog context changes after Prepare Replacement; never fall through to the generic database-row writer.
* Bind Apply, verification repair, recovery, and rollback to the exact current $wpdb->options table and fail closed with a specific context-change result before any database mutation.
* Expand executable regression coverage for autoloaded and non-autoloaded raw, serialized, and JSON-like options, alloptions/notoptions synchronization, persistent cache invalidation, filter mutation, reused IDs, multisite context drift, concurrent compare-and-swap conflicts, and rollback parity.
* Preserve Media Library Replacement schema 13 and the 2.59.12.54 option-name identity contract without adding a migration or changing non-option database replacement behavior.

= 2.59.12.54 =
* Route Media Library Replacement writes to the current WordPress options table through a dedicated option-aware compare-and-swap adapter instead of the generic database-row writer.
* Persist the exact option name with each indexed and planned option reference, block legacy or reused option IDs without matching identity, and preserve byte-exact concurrent-writer protection.
* Synchronize per-option, alloptions, notoptions, and persistent object-cache state after apply, verification repair, recovery, and rollback; verify the exact cached value before completion.
* Run WordPress option sanitization and pre-update filters before the atomic write, reject transformed plans, and publish the standard option update actions only after the database and runtime cache state are verified.
* Upgrade Media Library Replacement schema 12 to 13 additively without discarding existing registry rows; option plans created before the identity contract require a fresh Prepare step.

= 2.59.12.53 =
* Route full-document and filtered-fragment image admission through the canonical WordPress-derived local-source roots, restoring theme, plugin, mu-plugin, and WordPress-includes rewrite parity without changing Media Library Replacement scope.
* Share one side-effect-free exact-source AVIF/WebP lookup across HTML attributes, srcset, inline and external CSS, Slider Revolution image attributes, LCP candidate preference, and LCP preload equivalence while preserving existing uploads and local-asset identities.
* Extend supported semantic image surfaces with lazy srcsets, Slider image data attributes, and video posters, keep foreign/non-image/metadata/download contexts unchanged, and retain lookup-only frontend behavior with the existing local-asset queue.

= 2.59.12.52 =
* Extend the existing persistent media queue with canonical local-asset work rows for theme, plugin, mu-plugin, and WordPress-includes image sources without creating a second queue or attachment record.
* Re-resolve each local public source through the existing WordPress-derived path contract before encoding, bind work to canonical source identity plus exact requested format and source fingerprint, and keep frontend requests lookup-only.
* Reuse the established AVIF/WebP encoder, admission, color-profile, orientation, animation, atomic output, retry, stale-worker, affected-page purge, and background dispatch contracts while preserving Media Library attachment queue behavior.

= 2.59.12.51 =
* Add a separate WordPress-derived local-asset AVIF/WebP storage namespace and collision-resistant source identity for theme, plugin, mu-plugin, and WordPress-includes images.
* Preserve the established uploads-relative generated paths byte-for-byte while deriving non-upload identity from canonical source scope, owner, relative path, and full source filename.
* Let runtime public-URL lookup serve fresh existing local-asset derivatives with the same exact-source mtime/size freshness contract, while leaving non-attachment queue generation for the next roadmap version.

= 2.59.12.50 =
* Add one canonical local public image source descriptor using the existing WordPress-derived uploads, plugin, mu-plugin, theme, and WordPress-includes path resolvers.
* Route frontend AVIF/WebP public-URL admission through the shared descriptor while preserving the established uploads-relative generated identity, freshness lookup, and attachment-backed on-demand queue behavior.
* Memoize exact local source descriptors, preserve query-insensitive source identity, support custom registered theme directories, and reject foreign URLs, unsupported extensions, traversal, and UltraCache-generated cache/image outputs.

= 2.59.12.49 =
* Exclude every UltraCache-owned table and UltraCache-owned option row from Media Library replacement database discovery, planning, preview, apply, verification, and rollback.
* Add an apply-time internal-state guard so a plan created by an earlier version cannot write UltraCache operational records; existing internal plan rows are classified as excluded instead of failed.
* Add Continue Replacement recovery for failed metadata, database, Theme CSS, and post-replacement Flush All phases while preserving every completed change.
* Add Restart Database Replacement for database-phase failures, rebuilding only unresolved database references from the current database while preserving switched attachment metadata and successful content replacements.
* Run Flush All after Media Library replacement completes and report the attachment, site-content, internal-exclusion, and clean-slate cache-reset result in the completion message.

= 2.59.12.48 =
* Show homepage HTML warm completion with the canonical warmed URL and the actual HTML, Varnish-variant, and LiteSpeed pipeline stages instead of a static success sentence.
* Show homepage HTML + CSS bundle warm completion through the same stage formatter used by menu and full-site warm-up, including CSS and the verified Varnish variant count.
* Reuse the same result-driven homepage summary when a shared/homepage CSS bundle is prepared before a broader manual warm job; no warm runtime behavior is changed.

= 2.59.12.47 =
* Make Flush All a clean warm/Varnish queue generation boundary by deleting every prior pending, retrying, processing, completed, skipped, and terminal row instead of preserving invalidation and refill work.
* Clear foreground and cron ownership, bump the warm generation, unschedule old ticks, and wait for the authoritative cron worker lease to finish before deleting the old queue.
* Hold a purge mutation barrier that blocks new page-cache and generated-CSS write locks and drains existing write/build locks before the cache directory is removed.
* Start external cache clearing and the optional warm-after-flush plan only after the purge mutation barrier is released, so any resulting queue rows belong exclusively to the new generation.
* Fail Flush All when the clean-slate queue reset cannot be committed instead of reporting success with stale queue work still present.

= 2.59.12.46 =
* Allow the authenticated HTML-variant diagnostic warm pipeline to ignore only the `DONOTCACHEPAGE` flag inherited from the current UltraCache admin/REST request while preserving all public URL eligibility, exclusion, WooCommerce, and cacheability checks.
* Revise the HTML-variant capability contract so the self-blocked 2.59.12.45 observation is invalidated and cannot remain authoritative before a fresh Test Varnish run.
* Present an incomplete upstream warm/refill observation as `Observation incomplete` with its concrete stored reason instead of collapsing it into `Not supported · 0 of N`.

= 2.59.12.45 =
* Retry only transient DNS, transport, timeout, throttling, and server failures during public Varnish HTML-variant refill while stopping immediately on successful or terminal HTTP responses.
* Remove the stale `cache-write-failed` classification from successful HTML warm results and propagate the actual failed Varnish bucket, HTTP/error code, retryability, and bounded attempt history through the warm pipeline and queue result.
* Keep HTML-variant capability observation inconclusive when the canonical warm/refill path cannot reach the per-bucket proof stage instead of converting an upstream refill failure into a false variant-unsupported result.
* Pass the explicit warmed page URL, source, and Accept bucket into the final media rewrite so cron, CLI, stale, and warm workers can queue missing AVIF/WebP files and associate them with the correct page.
* Scope missing-media discovery limits per warmed page and continue affected-page registration when a missing optimized lookup is memoized or already queued elsewhere in the same worker.
* Rewrite local upload background images emitted by page builders inside inline CSS `<style>` blocks through the same validated AVIF/WebP lookup and on-demand generation path used by image markup and style attributes.

= 2.59.12.44 =
* Separate Varnish capability observation from control transport: create and verify canaries through the canonical public WordPress route while sending PURGE or BAN only to the configured control endpoint.
* Restore HTTP exact-invalidation discovery for control-only listeners such as the Hetzner endpoint without requiring those listeners to serve ordinary frontend GET requests.
* Preserve independent Exact PURGE and Exact BAN behavior probes and derive broader capability tests from the method verified during the current run.
* Preserve terminal topology outcomes such as entire-host `not-applicable` instead of reclassifying them through generic supported/unsupported aggregation.
* Persist endpoint, basic-test, HTML-variant, ESI, and aggregate capability diagnostics in existing revisioned UltraCache state records, with one-time migration from superseded diagnostic options.
* Invalidate the incorrect 2.59.12.43 capability proofs through revised capability fingerprints so they cannot authorize runtime behavior before a fresh Test Varnish run.
* Keep capability-probe operations isolated from production recent-operation reporting and require a specific reason for every non-executed or inconclusive capability result.

= 2.59.12.43 =
* Independently behavior-test HTTP Exact PURGE and Exact BAN on every configured endpoint instead of limiting probes from the configured method or adapter classification.
* Derive the common production hard-invalidation method from current endpoint proofs and use the same verified method for targeted, HTML-only, and entire-host runtime operations.
* Probe Batch BAN, HTML-only flush, entire-host flush, soft purge, stale refresh, and origin revalidation independently without executing known-URL or TTL production fallbacks.
* Persist explicit per-endpoint capability states, reason codes, messages, applicability, conclusiveness, timestamps, and proof expiry in the existing UltraCache state table.
* Distinguish supported, not supported, not applicable, observation incomplete, configuration changed, proof expired, and not tested outcomes; every untested UI result includes its specific persisted reason.
* Migrate the legacy endpoint capability option into the existing UltraCache state record and remove the legacy option after successful persistence; no transient state is added.

= 2.59.12.42 =
* Make Automatic Varnish site flushing choose from the observed static-object route and verified production capabilities instead of preferring HTML-only flush unconditionally.
* Select verified entire-host flush when public static objects pass through Varnish, and select verified HTML-only flush when public static objects bypass Varnish.
* Report a verified HTML-only operation as degraded when static ownership is inconclusive or static objects pass through Varnish without verified entire-host invalidation.
* Display the actual site runtime strategy in the Varnish summary: HTML-only flush, entire-host flush, known site pages, or automatic expiry.
* Preserve the existing capability persistence, production transports, VCL contracts, and explicit manual scope behavior.

= 2.59.12.41 =
* Use one bounded post-invalidation observation contract for exact invalidation, batch BAN, HTML-only flush, entire-host flush, and static preservation proofs.
* Retry transient public DNS/HTTP observation failures while still requiring two successful responses that match the expected canary generation or exact written artifact.
* Fail immediately on any successful stale or mismatched observation so retries cannot manufacture a capability the production runtime does not support.
* Report exhausted transport-only observations as `observation-incomplete` instead of incorrectly classifying the server capability as unsupported.
* Preserve the existing production planner, control operations, capability tables, and persistent diagnostic contracts without adding transient state.

= 2.59.12.40 =
* Preserve the complete Varnish basic-test contract instead of truncating associative payloads by key count, recursion budget, insertion order, or string length.
* Persist the full ESI capability proof and endpoint/test evidence through the existing sanitization contract.
* Add an independent contract-bound HTML variant capability record and use it as the authoritative public-path registry source.
* Restore the HTML variant capability into the basic diagnostic response from its dedicated record and remove the redundant capability-list slice.
