diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b80622..19ae6b5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,70 @@
All notable changes to JayShield are documented here.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
+## 1.3.0 - 2026-09-14
+
+A release about being usable on a real site, and honest about what a scan
+means.
+
+### Added
+
+- WordPress awareness. A scan recognises a WordPress install and prints its
+ version, and every flagged file that belongs to WordPress itself is tagged
+ `config`, `core`, `theme`, or `plugin` in the report and in `--json`. Those
+ files carry different advice: replace them with a clean copy of the same
+ version rather than only removing them, because quarantining one takes the
+ site or the theme offline. Scanning only `wp-content` still knows its site.
+- `--include
` scans folders that are skipped by name, and
+ `--include all` scans everything. The report now says how many folders were
+ skipped and which names, so a clean result is never quieter than it should
+ be. Skipped names are also listed in `--help`.
+- A clear answer when given a website address. `jayshield https://example.com`
+ used to fail with "no such file or folder"; it now explains that JayShield
+ reads files on disk and shows the two ways to scan that site, over SSH or on
+ a downloaded copy.
+- README: a Requirements section, a step-by-step guide to scanning a WordPress
+ site on any hosting, an after-the-scan checklist for the things a file
+ scanner cannot do, and a plain list of what JayShield can and cannot promise.
+- `scan()` accepts `includeDirs` and returns `sites`, `skippedDirNames`, and
+ `stats.skippedDirs`; each infected record may carry `site`. The site helpers
+ and the walker are exported from the package.
+
+### Changed
+
+- Folders named `cache` are now scanned. On WordPress, `wp-content/cache` is
+ web-served, writable, and a common place to plant a shell, and the upload
+ heuristic already treated it as one, so skipping it left a blind spot.
+- The upload heuristic no longer flags a cached page whose only PHP is the
+ `` guard that WP Super Cache writes. A payload after the
+ guard is still caught.
+- The clean-scan line now reads "Nothing in the files scanned matched a known
+ technique, heuristic, or bad hash", which is what a clean result means.
+
+### Fixed
+
+- A pristine WordPress 7.1 download was reported as 26 infected files, five
+ of them critical. Every one was a false positive, and every one is fixed:
+ - The WSO webshell rule matched the letters w-s-o inside any word, so
+ "Dawson", "WSODs", `useNewSodiumAPI`, and a certificate bundle were all
+ called a webshell. It now matches WSO's own function and constant names.
+ - The hex-escape rule flagged every long binary constant, in sodium_compat,
+ getID3, and SimplePie. It now flags a dangerous function name or request
+ variable spelled in hex, or a hex string literal called as a function,
+ and is high severity because that is never innocent.
+ - The hidden iframe rule matched `marginwidth="0"`, a hidden scratch frame
+ with a `javascript:` source, and the Google Tag Manager noscript snippet
+ that sits in most theme headers. It now requires a hidden frame with a
+ real destination, and a page full of unterminated tags can no longer
+ stall a scan.
+ - The long-line, high-entropy, and base64-blob heuristics fired on SVG
+ icons, entity tables, arrays of class names, and an embedded WebAssembly
+ module. Each now also requires a decoder, an execution call, or request
+ input on the same file or line, which a packed payload cannot do without.
+- Verified clean with the new rules against WordPress 7.1 with and without
+ `--include vendor`, WooCommerce 11.1.0, the Astra theme 4.13.11, jQuery
+ 3.7.1, and Laravel 12.x, while every planted threat in the test fixtures is
+ still found.
+
## 1.2.1 - 2026-07-13
### Changed
diff --git a/README.md b/README.md
index 4024458..d56102d 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,18 @@ site stops serving them right away.
It is one small tool with no dependencies, so you can trust it, read it, and run
it anywhere Node is installed.
+## Requirements
+
+- **Node.js 18 or newer** on the machine that runs the scan. Check with
+ `node -v`. If that prints nothing or an older version, install Node from
+ [nodejs.org](https://nodejs.org/) (macOS, Windows, and Linux installers).
+- **The site's files on that machine.** JayShield reads files on disk. It does
+ not connect to a website address, so `jayshield https://example.com` is
+ refused with an explanation. See [Scan a WordPress site](#scan-a-wordpress-site)
+ for the two ways to get the files in front of it.
+
+Nothing else: no account, no PHP, no database access, no background service.
+
## Quick start
No install required, run it straight from npm:
@@ -57,6 +69,81 @@ jayshield ./public_html
The examples below write `jayshield` for short, meaning however you choose to run it.
+## Scan a WordPress site
+
+JayShield finds the files an attacker planted or changed. To do that it needs
+the site's files, so pick whichever of these fits your hosting.
+
+**Path A: run it on the server.** If your host gives you SSH (most VPS plans,
+managed WordPress hosts, and many shared hosts), log in and check for Node:
+
+```bash
+ssh you@your-server
+node -v
+```
+
+If Node is there, scan the site root, which is usually `public_html`, `htdocs`,
+`www`, or `/var/www/`:
+
+```bash
+npx @jayhackpro/jayshield ~/public_html
+```
+
+If Node is missing and you cannot install it, use Path B. On many shared hosts
+you can install Node without root through cPanel's "Setup Node.js App" or with
+[nvm](https://github.com/nvm-sh/nvm).
+
+**Path B: scan a downloaded copy.** This works on any hosting, including
+hosting with no SSH at all. Download the whole site folder with an SFTP client
+(FileZilla, Cyberduck, WinSCP), with the "compress and download" button in your
+host's file manager, or from a full backup made by your backup plugin. Unzip it
+on your own computer and scan the folder:
+
+```bash
+npx @jayhackpro/jayshield ~/Downloads/example.com
+```
+
+The report is about the copy. Nothing on the live site changes, so clean the
+live site by hand using the paths in the report: delete planted files over SFTP
+and replace infected WordPress files with clean copies (see below).
+
+**Scan the whole site root, not just `wp-content`.** Attackers also edit
+`wp-config.php`, `.htaccess`, and the root `index.php`, and JayShield can only
+report on what it is pointed at. For a deeper scan add `--include vendor` so
+plugin dependency folders are read too.
+
+**Reading the results on a WordPress site.** JayShield recognises a WordPress
+install, prints its version, and tags each flagged file that belongs to
+WordPress itself:
+
+- **No tag** (`wp-content/uploads`, `wp-content/cache`, a stray file in the
+ root): almost always planted. Quarantine it.
+- **`[wordpress config]`**, **`[wordpress core]`**, **`[wordpress theme]`**,
+ **`[wordpress plugin]`**: a real file with injected code. The whole file is
+ untrusted, so replace it with a clean copy of the same version (core and
+ plugins from wordpress.org, the theme from where you got it) rather than only
+ removing it. Quarantining one of these takes the site or the theme offline
+ until you do; `--restore` puts it back if that happens.
+
+**After the scan.** Removing the files is the start, not the end. Do these too,
+because JayShield cannot:
+
+1. Update WordPress, every plugin, and every theme, and delete the ones you do
+ not use. The way in was almost always an outdated or nulled one.
+2. Change every password: WordPress admins, hosting panel, SFTP, and the
+ database user in `wp-config.php`. Rotate the salts in `wp-config.php` with
+ [new values](https://api.wordpress.org/secret-key/1.1/salt/).
+3. Look for admin users you did not create, in Users, and remove them.
+4. Check the database, which JayShield never reads: `siteurl` and `home` in
+ `wp_options`, unknown entries in `wp_options`, and `