=== NotchCache ===
Contributors: topnotchllc
Tags: cache, performance, page cache, optimization, diagnostics
Requires at least: 6.5
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 0.4.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A server-aware WordPress page cache with verified LiteSpeed-native acceleration, safe filesystem fallback, frontend optimization, diagnostics and runtime verification.

== Description ==

NotchCache 0.4.0 expands the proven page-cache engine into a broader WordPress performance suite while keeping risky transforms opt-in. The verified LiteSpeed-native backend and safe filesystem fallback are preserved. New modules add content-addressed local CSS/JS minification, DNS hints, optional static browser-cache rules, attachment-metadata image sizing, bounded public-URL warmup, advanced JavaScript delay, and additional font/HTML controls.

Core cache features:

* Auto backend that prefers verified LiteSpeed server-level caching on compatible hosts.
* Working filesystem HTML page-cache fallback for eligible anonymous GET requests.
* Real runtime MISS-to-HIT verification before LiteSpeed Auto mode is trusted.
* Token-aware anonymous caching with a 15-minute maximum for nonce-bearing public HTML.
* Logged-in, POST, query-string, REST/admin/feed/search/preview/404, authorization and commerce/session bypass rules.
* Automatic purge after common content, term, comment, menu, theme and update events.
* Signed drop-in ownership protection; foreign advanced-cache.php files are never overwritten or deleted.
* Native LiteSpeed purge receipts plus bounded homepage desktop/mobile warmup verification.
* JSON diagnostics, developer filters/functions and WP-CLI commands.
* No telemetry and no TopNotch cloud dependency.

0.4.0 optimization suite:

* Conservative HTML minification.
* Same-origin CSS minification into content-addressed cache files without modifying theme/plugin source files.
* Conservative same-origin JavaScript minification that preserves line boundaries and source files.
* Safe JavaScript defer with compatibility exclusions.
* Advanced JavaScript delay until interaction with a 5-second safety timeout.
* LCP/hero scoring, responsive preload hints, below-fold image/iframe lazy loading and layout-stability protection.
* Optional missing image width/height restoration only when WordPress attachment metadata proves intrinsic geometry; art-directed picture elements are skipped.
* Google Fonts preconnect, optional asynchronous Google Fonts loading, optional display=swap, or explicit removal.
* Manual DNS prefetch/preconnect lists and optional X-DNS-Prefetch-Control.
* Optional WordPress-marked browser-cache rules for static assets.
* Optional removal of WordPress legacy emoji payload and advanced removal of noscript blocks or WordPress ?ver= query strings.
* Manual bounded warmup of the homepage plus recently modified public posts/pages with per-URL cache receipts.
* Optimized-asset cache byte/file accounting so manual purge can report real local KB removed while keeping LiteSpeed server-cache byte reporting honest.

Professional safety choices:

* CSS/JS combine is not enabled in Standard mode. On HTTP/2/3 it is often unnecessary and can reorder dependencies.
* UCSS/CCSS is not advertised until NotchCache has a real generator; no fake cloud feature is shown.
* WebP/AVIF conversion is not advertised as implemented in 0.4.0; image delivery remains non-destructive.
* Database cleanup remains read-only diagnostics rather than automatic deletion.

Product information: https://topnotchagency.us/products/notchcache/

== Performance optimization in 0.4.0 ==

Standard mode keeps the proven cache/LCP/lazy-loading protections from 0.3.x and adds local asset optimization without modifying original theme/plugin files. New high-risk switches remain OFF on upgrade and must be enabled deliberately.

Recommended first test profile: HTML minify, safe JS defer, LCP optimization, safe image/iframe lazy loading, layout stability protection and emoji removal. Then enable CSS/JS minify one at a time, purge, verify the frontend and compare Lighthouse/Core Web Vitals. Advanced JS delay, async fonts, query-string removal, noscript removal and server browser-cache rules should be tested on staging or a low-risk site before broad deployment.

== Installation ==

1. Back up a business-critical site and test on staging first when possible.
2. Upload the `notchcache` folder to `/wp-content/plugins/` or install the ZIP through Plugins > Add Plugin > Upload Plugin.
3. Activate NotchCache.
4. Open Tools > NotchCache.
5. Review the compatibility preflight.
6. Enable the page cache and save settings.
7. Run the built-in page-cache self-test and require a verified HIT before relying on production caching.

The filesystem backend requires `WP_CACHE` to already be enabled in `wp-config.php`. A verified LiteSpeed-native backend does not require NotchCache to own `advanced-cache.php`. NotchCache does not rewrite `wp-config.php` automatically.

== Frequently Asked Questions ==

= Does NotchCache really cache pages? =

Yes. In Auto mode on a LiteSpeed host, NotchCache first verifies the native server cache with an actual HIT and then uses the server-level engine. Otherwise it uses the signed filesystem fallback. Filesystem HITs expose `X-NotchCache: HIT`; native LiteSpeed HITs expose the server cache header such as `X-LiteSpeed-Cache: hit`.

= What is cached by default? =

Only conservative public GET requests. Logged-in users, POST requests, requests with query strings, REST/admin/feed/search/preview/404 requests, authorization requests and common commerce/session cookies bypass the cache.

= Why can a public page with a WordPress nonce still be cached? =

A nonce marker in anonymous public HTML does not automatically make the whole page private. WordPress core and plugins commonly print nonces into frontend HTML. NotchCache first requires the response to pass its normal public-response safety checks: logged-in/session requests, Set-Cookie responses, private/no-store responses, POST requests and explicit DONOTCACHEPAGE responses still bypass. If the otherwise-public HTML contains a nonce-like marker, the stored entry is capped at 15 minutes even when the administrator selected a longer cache lifetime. Developers can return false from `notchcache_allow_token_bearing_response` for a known session-specific page, or filter `notchcache_token_response_ttl` to shorten/disable token-page storage.

= What happens if another cache plugin is active? =

Known page-cache plugins block the NotchCache page-cache switch. Optimization-only tools may coexist, but their settings still need normal compatibility testing.

= Will NotchCache overwrite advanced-cache.php? =

Only a NotchCache-owned drop-in carrying its ownership signature may be refreshed or removed. A foreign or unknown `advanced-cache.php` file is protected. The verified LiteSpeed-native backend does not need to install a NotchCache drop-in.

= Does NotchCache modify WP_CACHE in wp-config.php? =

No. NotchCache reports whether `WP_CACHE` is enabled but does not rewrite `wp-config.php` automatically.

= Does it cache WooCommerce cart or checkout pages? =

Not intentionally. When WooCommerce is active, NotchCache adds the configured cart, checkout and My Account page paths to its bypass list and also bypasses common WooCommerce session/cart cookies.

= Does it change CSS or JavaScript? =

Standard Performance Mode can minify eligible same-origin CSS/JS into separate content-addressed cache files, defer eligible WordPress-enqueued JavaScript, minify HTML, lazy-load safe media and add resource hints. Original theme/plugin files are never modified. CSS/JS combining remains deliberately disabled in Standard mode.

= Does it clean my database? =

No automatic database cleanup is included. Database and autoload figures are read-only indicators.

= Does NotchCache send data to TopNotch Agency? =

No. NotchCache has no telemetry and no TopNotch cloud dependency. The administrator-initiated runtime verifier first uses a short-lived synthetic same-site probe to prove the cache engine, then checks the real homepage separately. No test data is sent to TopNotch Agency.

= Why can the runtime self-test be inconclusive? =

Some hosts block WordPress loopback requests or place another server/CDN cache in front of PHP. The self-test reports that instead of claiming a pass it cannot verify.

== Privacy ==

NotchCache generates diagnostics and cache files locally inside WordPress. It does not send telemetry, analytics, site diagnostics, or personal information to Top Notch Agency LLP.

The optional runtime verifier is administrator-initiated. It uses temporary requests from the site back to itself. A random short-lived token isolates the synthetic engine test, and a second check verifies whether the actual homepage completes a MISS-to-HIT cycle. The token is removed after testing.

The administrator may explicitly export a JSON diagnostics file. That file remains under the administrator's control.

== Changelog ==

= 0.4.0 =
* Expand NotchCache from page cache into a modular performance suite while preserving the verified LiteSpeed-native backend and filesystem fallback.
* Add content-addressed same-origin CSS minification without modifying source files.
* Add conservative same-origin JavaScript minification that preserves line boundaries/ASI behavior and leaves source files untouched.
* Add Advanced JavaScript delay until interaction with exclusions and a 5-second safety timeout.
* Add manual DNS prefetch/preconnect controls and optional DNS prefetch response header.
* Add optional WordPress-marked static browser-cache rules with conservative CSS/JS/image/font lifetimes.
* Add missing image dimensions only when WordPress attachment metadata proves geometry; skip art-directed picture elements.
* Add optional asynchronous Google Fonts loading, explicit Google Fonts removal, and existing display/preconnect controls.
* Add bounded manual warmup of key public URLs with cache/status/HTML-size receipts.
* Add local optimized-asset file/byte accounting and purge integration.
* Keep CSS/JS combine, UCSS/CCSS, destructive database cleanup and fake image-conversion claims out of Standard mode.

= 0.3.11 =
* Harden native LiteSpeed purge after live testing showed that an old desktop variant could survive while a newer mobile variant was already active.
* Plugin-version migrations and performance-setting changes now use a completed signed loopback purge instead of relying only on a response header attached to the current admin request.
* Manual native purge now refills and verifies both desktop and mobile homepage variants, recording MISS/HIT status and the returned HTML payload size. The payload KB is explicitly not presented as LiteSpeed on-disk cache size.
* Every new LiteSpeed-native object receives a stable NotchCache global tag in addition to its per-path tag for safer future group invalidation.
* Make image lazy loading substantially more conservative: keep the first four content images eager, require a generous source-distance threshold, require reserved geometry, and preserve the site's existing decoding strategy.
* Keep the selected LCP/hero image, existing loading/fetchpriority choices, SEO metadata, canonical/robots/schema output, and the verified native MISS-to-HIT engine unchanged.
* Preserve exact native-cache-size honesty: LiteSpeed server storage bytes are not available to WordPress/PHP, so NotchCache reports a verified purge/warmup receipt instead of fabricating KB purged.

= 0.3.9 =
* Harden mobile CLS protection without changing the verified native LiteSpeed cache backend.
* Suppress automatic image LCP priority/preload when protected mode cannot reserve image geometry.
* Restore missing width/height only when ordinary WordPress-generated image filenames consistently prove one aspect ratio.
* Refuse geometry inference across art-directed `<picture><source>` crops.
* Preserve responsive `srcset`/`sizes`, SEO metadata, canonical/robots/schema output, and existing image URLs.

= 0.3.8 =
* Fix: allow `Vary: Content-Type` only when the verified native LiteSpeed backend is active, matching the real LAG Institutes homepage response discovered by runtime diagnostics.
* Safety: keep `Vary: Cookie`, `Vary: Authorization`, `Vary: *`, and unknown vary dimensions blocked.
* Safety: keep the filesystem backend unchanged and strict; it still rejects `Vary: Content-Type` because its URL-only key does not track that representation dimension.
* Preserve the verified LiteSpeed engine, CacheLookup helper, frontend optimizer, LCP/layout-stability protections, purge logic, and diagnostics unchanged.


= 0.3.7 =
* Fix: allow well-understood public representation variants (`Accept`, `Accept-Encoding`, `Accept-Language`, `User-Agent`) when the verified native LiteSpeed backend is active.
* Safety: continue rejecting `Vary: *`, `Cookie`, `Authorization`, and unknown vary dimensions.
* Safety: keep the filesystem backend unchanged and strict because it does not maintain representation-specific cache keys.
* Preserve the existing native LiteSpeed adapter, frontend performance engine, layout-stability protection, purge logic, and runtime diagnostics.

= 0.3.6 =
* Add signed, short-lived origin diagnostics to the real-homepage LiteSpeed verification without changing visitor cache keys.
* Report request eligibility, exact bypass reason, origin reachability, NotchCache engine/store state, Set-Cookie presence, and ordinary Cache-Control for the first homepage MISS.
* Preserve the 0.3.5 LiteSpeed native engine, CacheLookup helper, filesystem fallback, frontend optimizer, LCP work and layout-stability protection unchanged.


= 0.3.5 =
* Clear stale LiteSpeed verification state before every native probe and leave it false after any failed probe.
* Use a clean path-based native LiteSpeed probe so query-string cache policy cannot invalidate verification.
* Add an opt-in, WordPress-marked CacheLookup helper for LiteSpeed hosts where native cache lookup is not enabled at site level.
* Ensure a failed native probe truly falls back to the filesystem backend instead of accidentally emitting LiteSpeed-public storage decisions.

= 0.3.4 =
* Adds a server-aware cache backend with Auto, filesystem-only, and LiteSpeed-native-when-verified modes.
* Verifies the native LiteSpeed cache engine with a real two-request server-cache probe before Auto mode switches backends.
* Uses documented LiteSpeed response controls for public cache TTL, cookie varies, tags, and purge requests.
* Varies the native public cache on WordPress login, password, comment, WooCommerce cart/session, and PHP session cookies to protect personalized views from anonymous cache reuse.
* Removes the NotchCache advanced-cache.php drop-in after a native LiteSpeed HIT is verified so only one page-cache owner remains active.
* Keeps the hardened filesystem backend as a fallback for non-LiteSpeed servers or LiteSpeed hosts without LSCache enabled.
* Adds native LiteSpeed purge integration, including a signed same-site loopback path for non-HTTP contexts.
* Keeps the 0.3.2 layout-stability protections and 0.3.x frontend performance optimizations unchanged.

= 0.3.3 =
* Hardens filesystem cache publication for managed hosts where shared-storage metadata can become visible to different PHP workers with a short delay.
* Adds a per-key non-blocking fill lock to reduce cache stampedes and concurrent replacement of the same entry.
* Uses durable temporary body writes with fflush and fsync when PHP exposes fsync, followed by atomic rename.
* Rechecks for an already-fresh entry before replacing it, preventing repeated MISS requests from continuously restarting a shared-filesystem visibility window.
* Publishes the body before optional per-entry metadata so a safe global-TTL HIT can become available as early as possible.
* Runtime verification now allows a bounded 1-second shared-filesystem coherence window after a confirmed successful store; normal frontend requests are never intentionally delayed by this test logic.
* Keeps the 0.3.2 layout-stability safeguards and frontend optimizer behavior unchanged.

= 0.3.2 =
* Adds recommended Layout Stability Protection after live Lighthouse validation exposed CLS regressions in 0.3.1.
* Preserves the site's existing Google Fonts display strategy in Standard mode instead of forcing display=swap, preventing font-metric swaps from creating avoidable layout movement.
* Keeps LCP preload and fetchpriority gains, but only changes an LCP image from lazy to eager automatically when intrinsic width/height or an aspect ratio already reserves layout space.
* Keeps responsive imagesrcset/imagesizes preload support and semantic hero-background preload support.
* Adds a visible layout-stability status/control and marks forced Google Fonts display=swap as experimental.
* Preserves the proven page-cache engine, token-capped homepage behavior, safe JavaScript defer, conservative HTML minification, purge system and SEO-visible page content.

= 0.3.1 =
* Adds scored mobile-LCP candidate selection using hero context, dimensions and above-the-fold position while excluding logos/icons/avatars.
* Adds responsive LCP image preload using imagesrcset/imagesizes when available.
* Adds preload support for semantic inline hero background images without rewriting CSS.
* Adds Google Fonts display=swap completion for existing Google Fonts stylesheet URLs that omitted a display strategy.
* Stops adding decoding=async to the selected LCP image; existing decoding choices are preserved.
* Keeps the proven v0.2.4 cache engine and v0.3.0 safe JS/HTML optimizations unchanged.

= 0.3.0 =
* Adds opt-in Standard performance mode on top of the proven 0.2.4 cache engine.
* Adds conservative HTML minification, safe JS defer, LCP-image prioritization, below-fold iframe lazy loading, Google Fonts preconnects and optional emoji payload removal.
* Leaves all new optimization switches disabled until an administrator enables Performance mode.


= 0.2.4 =
* Fixed the real-homepage DYNAMIC-TOKEN dead-end found during WordPress 7.1 / PHP 8.5 / LiteSpeed testing.
* Replaced blanket rejection of otherwise-public anonymous nonce-bearing HTML with a bounded 15-minute per-entry cache lifetime after all existing cookie, Set-Cookie, private/no-store, request-method and DONOTCACHEPAGE checks pass.
* Added per-entry TTL metadata and taught advanced-cache.php to honor the shorter stored TTL without extending the administrator-selected global lifetime.
* Preserved an integration filter that can force strict token-page bypass and added `notchcache_token_response_ttl` for sites that need an even shorter cap or a complete token-page bypass.
* Added one-time runtime-artifact refresh on plugin-version change so ZIP replacement cannot leave an older NotchCache-owned drop-in or stale page files active.
* Updated runtime/status messaging to make the token-page safety policy visible to administrators.
* Preserved all existing cross-worker path, reverse-proxy HTTPS, foreign-drop-in, commerce/session, response-header and automatic-purge safeguards.

= 0.2.3 =
* Derive early cache storage relative to the active wp-content directory instead of trusting an absolute path written by another worker.
* Runtime verification repeats the exact same probe URL and reports early file state/path/size/age/TTL diagnostics.
* Replaced the generated executable PHP runtime config with an atomic JSON config so PHP OPcache cannot keep a stale short-lived self-test token.
* Unified request-scheme detection between the origin writer and the early advanced-cache.php reader, including common reverse-proxy HTTPS headers.
* Invalidates PHP OPcache after refreshing the NotchCache-owned advanced-cache.php so an update cannot keep executing stale drop-in bytes.
* Added self-test lookup-key, write-key and scheme diagnostics so a remaining host/proxy mismatch can be identified without weakening cache safety.
* Preserved all conservative request, cookie, WooCommerce, token, response-header and purge safety boundaries.

= 0.2.1 =
* Fixed runtime verification so the engine test no longer depends on theme/plugin homepage output.
* Added a synthetic same-site probe that still exercises the real advanced-cache.php MISS/write/HIT path.
* Added a separate real-homepage MISS-to-HIT verification with cache-store reason reporting.
* Added self-test-only store diagnostics for unsafe headers, dynamic tokens, filters and filesystem write failures.
* Preserved the v0.2.0 cache engine, compatibility rules, purge behavior, exclusions and drop-in ownership safeguards.

= 0.2.0 =
* Added working filesystem page caching with a signed early `advanced-cache.php` drop-in.
* Added conservative anonymous-request eligibility and commerce/session bypass rules.
* Added cache lifetime, automatic purge and custom path exclusion settings.
* Added WooCommerce dynamic-page exclusions when WooCommerce is active.
* Added runtime MISS/write/HIT self-test and `X-NotchCache` response diagnostics.
* Added low-memory, LiteSpeed-server and WP_CACHE/drop-in recommendations.
* Expanded cache-plugin signature detection.
* Preserved diagnostic export, developer API, purge adapters and WP-CLI.
* Added drop-in ownership protection and safe cleanup on deactivation/uninstall.

= 0.1.0 =
* Initial diagnostic-first foundation.
